From 08d45450f72403eda21ae85f76459ef9317e1f6a Mon Sep 17 00:00:00 2001 From: lijiaqi Date: Fri, 11 Oct 2024 10:27:26 +0800 Subject: [PATCH] init --- .gitignore | 34 + LICENSE | 201 + cloud/conf/common.yaml | 157 + cloud/conf/db.yaml | 27 + cloud/conf/mq.yaml | 11 + cloud/conf/redis.yaml | 37 + cloud/conf/zipkin.yaml | 9 + cloud/xingyun-cloud-api/Dockerfile | 12 + cloud/xingyun-cloud-api/pom.xml | 114 + .../api/XingYunCloudApiApplication.java | 65 + .../src/main/java/lombok.config | 2 + .../src/main/resources/banner.txt | 7 + .../src/main/resources/bootstrap.yml | 36 + .../src/main/resources/magic-editor-config.js | 21 + .../src/main/resources/project.yaml | 71 + .../src/main/resources/scripts/start.sh | 12 + .../src/main/resources/scripts/stop.sh | 10 + cloud/xingyun-cloud-gateway/Dockerfile | 12 + cloud/xingyun-cloud-gateway/pom.xml | 110 + .../xingyun/gateway/GateWayApplication.java | 14 + .../src/main/resources/banner.txt | 7 + .../src/main/resources/bootstrap.yml | 24 + .../src/main/resources/project.yaml | 29 + .../src/main/resources/scripts/start.sh | 12 + .../src/main/resources/scripts/stop.sh | 10 + codestyles/eclipse-java-google-style.xml | 337 + codestyles/intellij-java-google-style.xml | 598 ++ pom.xml | 156 + screenshots/1.jpg | Bin 0 -> 128648 bytes screenshots/10.jpg | Bin 0 -> 181302 bytes screenshots/11.jpg | Bin 0 -> 133135 bytes screenshots/12.jpg | Bin 0 -> 148287 bytes screenshots/2.jpg | Bin 0 -> 159253 bytes screenshots/3.jpg | Bin 0 -> 121058 bytes screenshots/4.jpg | Bin 0 -> 198599 bytes screenshots/5.jpg | Bin 0 -> 185965 bytes screenshots/6.jpg | Bin 0 -> 176774 bytes screenshots/7.jpg | Bin 0 -> 151753 bytes screenshots/8.jpg | Bin 0 -> 170154 bytes screenshots/9.jpg | Bin 0 -> 194688 bytes xingyun-api/Dockerfile | 16 + xingyun-api/pom.xml | 108 + .../xingyun/api/XingYunApiApplication.java | 61 + xingyun-api/src/main/java/lombok.config | 2 + .../src/main/resources/application-dev.yml | 83 + .../src/main/resources/application-prod.yml | 87 + .../src/main/resources/application-test.yml | 84 + .../src/main/resources/application.yml | 207 + xingyun-api/src/main/resources/banner.txt | 7 + .../resources/db/SQL文件说明,重要!!!!!!.txt | 5 + .../src/main/resources/db/all/platform.sql | 388 + .../src/main/resources/db/all/tenant.sql | 7141 +++++++++++++++++ .../db/migration/platform/V1.0__init.sql | 313 + .../migration/platform/V1.1__sys_module.sql | 61 + .../migration/platform/V1.2__dynamic_api.sql | 17 + .../platform/V1.3__update_qrtz_details.sql | 1 + .../db/migration/platform/V1.4__v3.sql | 1 + .../db/migration/tenant/V1.0__init.sql | 6806 ++++++++++++++++ .../db/migration/tenant/V1.1__paytype.sql | 425 + .../migration/tenant/V1.2__stock_adjust.sql | 69 + .../db/migration/tenant/V1.3__sc_transfer.sql | 74 + .../migration/tenant/V1.4__bundle_product.sql | 81 + .../db/migration/tenant/V1.5__logistics.sql | 376 + .../db/migration/tenant/V1.6__custom_page.sql | 34 + .../migration/tenant/V1.7__upload_to_oss.sql | 7 + .../db/migration/tenant/V1.8__v3.sql | 49 + .../src/main/resources/magic-editor-config.js | 21 + .../src/main/resources/scripts/start.sh | 12 + .../src/main/resources/scripts/stop.sh | 10 + xingyun-basedata/pom.xml | 21 + .../bo/address/AddressSelectorBo.java | 120 + .../basedata/bo/address/GetAddressBo.java | 161 + .../basedata/bo/address/QueryAddressBo.java | 174 + .../bo/customer/CustomerSelectorBo.java | 43 + .../basedata/bo/customer/GetCustomerBo.java | 169 + .../basedata/bo/customer/QueryCustomerBo.java | 82 + .../company/GetLogisticsCompanyBo.java | 99 + .../company/LogisticsCompanySelectorBo.java | 43 + .../company/QueryLogisticsCompanyBo.java | 82 + .../basedata/bo/member/GetMemberBo.java | 138 + .../basedata/bo/member/MemberSelectorBo.java | 39 + .../basedata/bo/member/QueryMemberBo.java | 82 + .../basedata/bo/paytype/GetPayTypeBo.java | 55 + .../bo/paytype/PayTypeSelectorBo.java | 49 + .../basedata/bo/paytype/QueryPayTypeBo.java | 82 + .../bo/product/brand/GetProductBrandBo.java | 67 + .../product/brand/ProductBrandSelectorBo.java | 43 + .../brand/ProductCategorySelectorBo.java | 49 + .../bo/product/brand/QueryProductBrandBo.java | 49 + .../category/GetProductCategoryBo.java | 78 + .../category/ProductCategoryTreeBo.java | 55 + .../bo/product/info/GetProductBo.java | 306 + .../bo/product/info/ProductBundleBo.java | 48 + .../bo/product/info/ProductSelectorBo.java | 116 + .../bo/product/info/QueryProductBo.java | 109 + .../property/GetProductPropertyBo.java | 105 + .../property/ProductPropertyModelorBo.java | 120 + .../property/QueryProductPropertyBo.java | 74 + .../item/GetProductPropertyItemBo.java | 49 + .../item/QueryProductPropertyItemBo.java | 49 + .../xingyun/basedata/bo/shop/GetShopBo.java | 96 + .../xingyun/basedata/bo/shop/QueryShopBo.java | 93 + .../basedata/bo/shop/ShopSelectorBo.java | 50 + .../bo/storecenter/GetStoreCenterBo.java | 105 + .../bo/storecenter/QueryStoreCenterBo.java | 82 + .../bo/storecenter/StoreCenterSelectorBo.java | 43 + .../basedata/bo/supplier/GetSupplierBo.java | 185 + .../basedata/bo/supplier/QuerySupplierBo.java | 82 + .../bo/supplier/SupplierSelectorBo.java | 43 + .../controller/AddressController.java | 170 + .../BaseDataSelectorController.java | 594 ++ .../controller/CustomerController.java | 180 + .../LogisticsCompanyController.java | 158 + .../basedata/controller/MemberController.java | 178 + .../controller/PayTypeController.java | 115 + .../controller/ProductBrandController.java | 183 + .../controller/ProductCategoryController.java | 202 + .../controller/ProductController.java | 150 + .../controller/ProductPropertyController.java | 201 + .../ProductPropertyItemController.java | 118 + .../basedata/controller/ShopController.java | 138 + .../controller/StoreCenterController.java | 181 + .../controller/SupplierController.java | 181 + .../product/ProductPropertyRelationDto.java | 49 + .../property/ProductPropertyModelorDto.java | 71 + .../xingyun/basedata/entity/Address.java | 119 + .../xingyun/basedata/entity/Customer.java | 158 + .../basedata/entity/LogisticsCompany.java | 106 + .../xingyun/basedata/entity/Member.java | 124 + .../xingyun/basedata/entity/PayType.java | 91 + .../xingyun/basedata/entity/Product.java | 144 + .../xingyun/basedata/entity/ProductBrand.java | 100 + .../basedata/entity/ProductBundle.java | 95 + .../basedata/entity/ProductCategory.java | 90 + .../entity/ProductCategoryProperty.java | 36 + .../basedata/entity/ProductProperty.java | 108 + .../basedata/entity/ProductPropertyItem.java | 92 + .../entity/ProductPropertyRelation.java | 48 + .../basedata/entity/ProductPurchase.java | 32 + .../basedata/entity/ProductRetail.java | 32 + .../xingyun/basedata/entity/ProductSale.java | 32 + .../xingyun/basedata/entity/Shop.java | 101 + .../xingyun/basedata/entity/StoreCenter.java | 110 + .../xingyun/basedata/entity/Supplier.java | 167 + .../basedata/enums/AddressEntityType.java | 31 + .../xingyun/basedata/enums/AddressType.java | 31 + .../basedata/enums/BaseDataOpLogType.java | 7 + .../basedata/enums/ColumnDataType.java | 32 + .../xingyun/basedata/enums/ColumnType.java | 31 + .../xingyun/basedata/enums/InvoiceType.java | 32 + .../xingyun/basedata/enums/ManageType.java | 31 + .../enums/ProductCategoryNodeType.java | 23 + .../xingyun/basedata/enums/ProductType.java | 31 + .../xingyun/basedata/enums/PropertyType.java | 31 + .../xingyun/basedata/enums/SettleType.java | 31 + .../xingyun/basedata/enums/TaxRate.java | 32 + .../excel/address/AddressExportModel.java | 134 + .../excel/address/AddressImportListener.java | 192 + .../excel/address/AddressImportModel.java | 93 + .../customer/CustomerImportListener.java | 160 + .../excel/customer/CustomerImportModel.java | 136 + .../excel/member/MemberImportListener.java | 154 + .../excel/member/MemberImportModel.java | 100 + .../excel/product/ProductImportListener.java | 274 + .../excel/product/ProductImportModel.java | 124 + .../brand/ProductBrandImportListener.java | 94 + .../brand/ProductBrandImportModel.java | 49 + .../ProductCategoryImportListener.java | 139 + .../category/ProductCategoryImportModel.java | 50 + .../excel/shop/ShopImportListener.java | 97 + .../basedata/excel/shop/ShopImportModel.java | 49 + .../StoreCenterImportListener.java | 131 + .../storecenter/StoreCenterImportModel.java | 73 + .../supplier/SupplierImportListener.java | 184 + .../excel/supplier/SupplierImportModel.java | 156 + .../impl/address/AddressServiceImpl.java | 164 + .../impl/customer/CustomerServiceImpl.java | 240 + .../LogisticsCompanyServiceImpl.java | 211 + .../impl/member/MemberServiceImpl.java | 217 + .../impl/paytype/PayTypeServiceImpl.java | 153 + .../impl/product/ProductBrandServiceImpl.java | 188 + .../product/ProductBundleServiceImpl.java | 32 + .../ProductCategoryPropertyServiceImpl.java | 48 + .../product/ProductCategoryServiceImpl.java | 253 + .../ProductPropertyItemServiceImpl.java | 155 + .../ProductPropertyRelationServiceImpl.java | 198 + .../product/ProductPropertyServiceImpl.java | 370 + .../product/ProductPurchaseServiceImpl.java | 61 + .../product/ProductRetailServiceImpl.java | 60 + .../impl/product/ProductSaleServiceImpl.java | 60 + .../impl/product/ProductServiceImpl.java | 552 ++ .../basedata/impl/shop/ShopServiceImpl.java | 133 + .../storecenter/StoreCenterServiceImpl.java | 213 + .../impl/supplier/SupplierServiceImpl.java | 246 + .../basedata/mappers/AddressMapper.java | 39 + .../basedata/mappers/CustomerMapper.java | 43 + .../mappers/LogisticsCompanyMapper.java | 43 + .../basedata/mappers/MemberMapper.java | 43 + .../basedata/mappers/PayTypeMapper.java | 41 + .../basedata/mappers/ProductBrandMapper.java | 41 + .../basedata/mappers/ProductBundleMapper.java | 16 + .../mappers/ProductCategoryMapper.java | 32 + .../ProductCategoryPropertyMapper.java | 24 + .../basedata/mappers/ProductMapper.java | 106 + .../mappers/ProductPropertyItemMapper.java | 34 + .../mappers/ProductPropertyMapper.java | 42 + .../ProductPropertyRelationMapper.java | 43 + .../mappers/ProductPurchaseMapper.java | 16 + .../basedata/mappers/ProductRetailMapper.java | 16 + .../basedata/mappers/ProductSaleMapper.java | 16 + .../xingyun/basedata/mappers/ShopMapper.java | 31 + .../basedata/mappers/StoreCenterMapper.java | 43 + .../basedata/mappers/SupplierMapper.java | 43 + .../service/address/AddressService.java | 76 + .../service/customer/CustomerService.java | 73 + .../logistics/LogisticsCompanyService.java | 75 + .../service/member/MemberService.java | 74 + .../service/paytype/PayTypeService.java | 60 + .../service/product/ProductBrandService.java | 75 + .../service/product/ProductBundleService.java | 15 + .../ProductCategoryPropertyService.java | 32 + .../product/ProductCategoryService.java | 71 + .../product/ProductPropertyItemService.java | 61 + .../ProductPropertyRelationService.java | 61 + .../product/ProductPropertyService.java | 74 + .../product/ProductPurchaseService.java | 24 + .../service/product/ProductRetailService.java | 24 + .../service/product/ProductSaleService.java | 24 + .../service/product/ProductService.java | 113 + .../basedata/service/shop/ShopService.java | 51 + .../storecenter/StoreCenterService.java | 64 + .../service/supplier/SupplierService.java | 73 + .../vo/address/AddressSelectorVo.java | 60 + .../basedata/vo/address/CreateAddressVo.java | 75 + .../basedata/vo/address/QueryAddressVo.java | 54 + .../basedata/vo/address/UpdateAddressVo.java | 82 + .../vo/customer/CreateCustomerVo.java | 127 + .../vo/customer/QueryCustomerSelectorVo.java | 31 + .../basedata/vo/customer/QueryCustomerVo.java | 31 + .../vo/customer/UpdateCustomerVo.java | 131 + .../company/CreateLogisticsCompanyVo.java | 59 + .../QueryLogisticsCompanySelectorVo.java | 31 + .../company/QueryLogisticsCompanyVo.java | 31 + .../company/UpdateLogisticsCompanyVo.java | 74 + .../basedata/vo/member/CreateMemberVo.java | 87 + .../vo/member/QueryMemberSelectorVo.java | 31 + .../basedata/vo/member/QueryMemberVo.java | 31 + .../basedata/vo/member/UpdateMemberVo.java | 100 + .../basedata/vo/paytype/CreatePayTypeVo.java | 43 + .../vo/paytype/PayTypeSelectorVo.java | 31 + .../basedata/vo/paytype/QueryPayTypeVo.java | 31 + .../basedata/vo/paytype/UpdatePayTypeVo.java | 57 + .../product/brand/CreateProductBrandVo.java | 55 + .../brand/QueryProductBrandSelectorVo.java | 31 + .../vo/product/brand/QueryProductBrandVo.java | 31 + .../product/brand/UpdateProductBrandVo.java | 70 + .../category/CreateProductCategoryVo.java | 41 + .../QueryProductCategorySelectorVo.java | 18 + .../category/UpdateProductCategoryVo.java | 50 + .../vo/product/info/CreateProductVo.java | 154 + .../vo/product/info/ProductBundleVo.java | 51 + .../info/ProductPropertyRelationVo.java | 23 + .../product/info/QueryProductSelectorVo.java | 77 + .../vo/product/info/QueryProductVo.java | 77 + .../vo/product/info/UpdateProductVo.java | 166 + .../CreateProductSalePropItemRelationVo.java | 29 + .../vo/product/poly/CreateProductPolyVo.java | 220 + .../vo/product/poly/QueryProductPolyVo.java | 38 + .../vo/product/poly/UpdateProductPolyVo.java | 104 + .../property/CreateProductPolyPropertyVo.java | 39 + .../CreateProductPolySalePropGroupVo.java | 22 + .../property/CreateProductPropertyVo.java | 77 + .../property/QueryProductPropertyVo.java | 31 + .../property/UpdateProductPropertyVo.java | 91 + .../item/CreateProductPropertyItemVo.java | 42 + .../item/QueryProductPropertyItemVo.java | 39 + .../item/UpdateProductPropertyItemVo.java | 50 + .../CreateProductPropertyRelationVo.java | 39 + .../purchase/CreateProductPurchaseVo.java | 31 + .../purchase/UpdateProductPurchaseVo.java | 33 + .../product/retail/CreateProductRetailVo.java | 31 + .../product/retail/UpdateProductRetailVo.java | 33 + .../vo/product/sale/CreateProductSaleVo.java | 31 + .../vo/product/sale/UpdateProductSaleVo.java | 33 + .../CreateProductSalePropGroupVo.java | 35 + .../QueryProductSalePropGroupSelectorVo.java | 37 + .../saleprop/QueryProductSalePropGroupVo.java | 31 + .../UpdateProductSalePropGroupVo.java | 50 + .../item/CreateProductSalePropItemVo.java | 42 + .../QueryProductSalePropItemSelectorVo.java | 37 + .../item/QueryProductSalePropItemVo.java | 39 + .../item/UpdateProductSalePropItemVo.java | 50 + .../basedata/vo/shop/CreateShopVo.java | 58 + .../xingyun/basedata/vo/shop/QueryShopVo.java | 55 + .../basedata/vo/shop/ShopSelectorVo.java | 33 + .../basedata/vo/shop/UpdateShopVo.java | 74 + .../vo/storecenter/CreateStoreCenterVo.java | 65 + .../QueryStoreCenterSelectorVo.java | 31 + .../vo/storecenter/QueryStoreCenterVo.java | 32 + .../vo/storecenter/UpdateStoreCenterVo.java | 80 + .../vo/supplier/CreateSupplierVo.java | 144 + .../vo/supplier/QuerySupplierSelectorVo.java | 40 + .../basedata/vo/supplier/QuerySupplierVo.java | 32 + .../vo/supplier/UpdateSupplierVo.java | 139 + xingyun-basedata/src/main/java/lombok.config | 2 + .../mappers/address/AddressMapper.xml | 65 + .../mappers/customer/CustomerMapper.xml | 94 + .../logistics/LogisticsCompanyMapper.xml | 46 + .../resources/mappers/member/MemberMapper.xml | 76 + .../mappers/paytype/PayTypeMapper.xml | 44 + .../mappers/product/ProductBrandMapper.xml | 71 + .../mappers/product/ProductCategoryMapper.xml | 41 + .../product/ProductCategoryPropertyMapper.xml | 27 + .../mappers/product/ProductMapper.xml | 166 + .../product/ProductPropertyItemMapper.xml | 55 + .../mappers/product/ProductPropertyMapper.xml | 83 + .../product/ProductPropertyRelationMapper.xml | 41 + .../mappers/product/ProductPurchaseMapper.xml | 5 + .../mappers/product/ProductRetailMapper.xml | 5 + .../mappers/product/ProductSaleMapper.xml | 5 + .../resources/mappers/shop/ShopMapper.xml | 63 + .../mappers/storecenter/StoreCenterMapper.xml | 76 + .../mappers/supplier/SupplierMapper.xml | 49 + xingyun-chart/pom.xml | 22 + .../chart/bo/OrderChartSameMonthBo.java | 38 + .../chart/bo/OrderChartSameMonthSumBo.java | 39 + .../xingyun/chart/bo/OrderChartTodayBo.java | 38 + .../chart/bo/OrderChartTodaySumBo.java | 39 + .../chart/controller/ChartController.java | 114 + .../chart/dto/OrderChartSameMonthDto.java | 27 + .../xingyun/chart/dto/OrderChartSumDto.java | 24 + .../xingyun/chart/dto/OrderChartTodayDto.java | 27 + .../xingyun/chart/entity/OrderChart.java | 57 + .../chart/enums/OrderChartBizType.java | 32 + .../chart/impl/OrderChartServiceImpl.java | 149 + .../chart/listeners/OrderDataListener.java | 59 + .../chart/mappers/OrderChartMapper.java | 55 + .../chart/service/OrderChartService.java | 54 + .../xingyun/chart/vo/CreateOrderChartVo.java | 38 + .../xingyun/chart/vo/GetOrderChartVo.java | 21 + .../xingyun/chart/vo/QueryOrderChartVo.java | 21 + xingyun-chart/src/main/java/lombok.config | 2 + .../resources/mappers/OrderChartMapper.xml | 83 + xingyun-common/pom.xml | 22 + .../common/bo/components/MapLocationBo.java | 22 + .../common/bo/components/OrderTimeLineBo.java | 67 + .../xingyun/common/bo/dic/CitySelectorBo.java | 37 + .../common/bo/sw/excel/GetOnlineExcelBo.java | 66 + .../bo/sw/excel/QueryOnlineExcelBo.java | 66 + .../common/bo/sw/filebox/GetFileBoxBo.java | 82 + .../common/bo/sw/filebox/QueryFileBoxBo.java | 56 + .../common/controller/SelectorController.java | 49 + .../components/ComponentController.java | 153 + .../controller/sw/FileBoxController.java | 124 + .../controller/sw/OnlineExcelController.java | 158 + xingyun-common/src/main/java/lombok.config | 2 + xingyun-core/pom.xml | 25 + .../core/annations/OrderTimeLineLog.java | 60 + .../core/aop/OrderTimeLineLogAspect.java | 224 + .../core/bo/print/A4ExcelPortraitPrintBo.java | 34 + .../xingyun/core/dto/dic/city/DicCityDto.java | 40 + .../core/dto/stock/ProductStockChangeDto.java | 38 + .../xingyun/core/entity/DicCity.java | 51 + .../xingyun/core/entity/FileBox.java | 104 + .../xingyun/core/entity/OnlineExcel.java | 83 + .../xingyun/core/entity/OrderTimeLine.java | 65 + .../xingyun/core/enums/FileBoxFileType.java | 30 + .../xingyun/core/enums/FileBoxNodeType.java | 23 + .../core/enums/OrderTimeLineBizType.java | 42 + .../xingyun/core/enums/SwOpLogType.java | 7 + .../events/order/ApprovePassOrderEvent.java | 56 + .../impl/ApprovePassPurchaseOrderEvent.java | 17 + .../impl/ApprovePassPurchaseReturnEvent.java | 17 + .../impl/ApprovePassRetailOutSheetEvent.java | 17 + .../impl/ApprovePassRetailReturnEvent.java | 17 + .../order/impl/ApprovePassSaleOrderEvent.java | 17 + .../impl/ApprovePassSaleReturnEvent.java | 17 + .../core/events/stock/AddStockEvent.java | 26 + .../core/events/stock/SubStockEvent.java | 26 + .../stock/take/DeleteTakeStockPlanEvent.java | 26 + .../xingyun/core/impl/DicCityServiceImpl.java | 62 + .../xingyun/core/impl/FileBoxServiceImpl.java | 222 + .../core/impl/OnlineExcelServiceImpl.java | 208 + .../core/impl/OrderTimeLineServiceImpl.java | 45 + .../xingyun/core/mappers/DicCityMapper.java | 32 + .../xingyun/core/mappers/FileBoxMapper.java | 23 + .../core/mappers/OnlineExcelMapper.java | 23 + .../core/mappers/OrderTimeLineMapper.java | 12 + .../xingyun/core/service/DicCityService.java | 32 + .../xingyun/core/service/FileBoxService.java | 66 + .../core/service/OnlineExcelService.java | 78 + .../core/service/OrderTimeLineService.java | 25 + .../xingyun/core/utils/SplitNumberUtil.java | 61 + .../vo/sw/excel/BatchSendOnlineExcelVo.java | 39 + .../core/vo/sw/excel/CreateOnlineExcelVo.java | 34 + .../core/vo/sw/excel/QueryOnlineExcelVo.java | 43 + .../core/vo/sw/excel/SendOnlineExcelVo.java | 37 + .../sw/excel/UpdateOnlineExcelContentVo.java | 27 + .../core/vo/sw/excel/UpdateOnlineExcelVo.java | 44 + .../vo/sw/filebox/CreateFileBoxDirVo.java | 23 + .../core/vo/sw/filebox/QueryFileBoxVo.java | 23 + .../core/vo/sw/filebox/UpdateFileBoxVo.java | 34 + .../core/vo/sw/filebox/UploadFileBoxVo.java | 26 + xingyun-core/src/main/java/lombok.config | 2 + .../main/resources/mappers/DicCityMapper.xml | 31 + .../main/resources/mappers/FileBoxMapper.xml | 24 + .../resources/mappers/OnlineExcelMapper.xml | 52 + xingyun-sc/pom.xml | 26 + .../sc/bo/logistics/GetLogisticsSheetBo.java | 376 + .../GetLogisticsSheetDeliveryBo.java | 44 + .../QueryLogisticsSheetBizOrderBo.java | 102 + .../bo/logistics/QueryLogisticsSheetBo.java | 124 + .../xingyun/sc/bo/paytype/OrderPayTypeBo.java | 61 + .../sc/bo/purchase/GetPurchaseOrderBo.java | 375 + .../sc/bo/purchase/PrintPurchaseOrderBo.java | 258 + .../bo/purchase/PurchaseOrderSelectorBo.java | 104 + .../purchase/PurchaseOrderWithReceiveBo.java | 296 + .../sc/bo/purchase/PurchaseProductBo.java | 131 + .../sc/bo/purchase/QueryPurchaseOrderBo.java | 169 + .../QueryPurchaseOrderWithReceiveBo.java | 86 + .../purchase/config/GetPurchaseConfigBo.java | 43 + .../bo/purchase/receive/GetPaymentDateBo.java | 35 + .../purchase/receive/GetReceiveSheetBo.java | 429 + .../purchase/receive/PrintReceiveSheetBo.java | 283 + .../purchase/receive/QueryReceiveSheetBo.java | 197 + .../QueryReceiveSheetWithReturnBo.java | 96 + .../receive/ReceiveSheetSelectorBo.java | 104 + .../receive/ReceiveSheetWithReturnBo.java | 294 + .../returned/GetPurchaseReturnBo.java | 418 + .../returned/PrintPurchaseReturnBo.java | 283 + .../returned/QueryPurchaseReturnBo.java | 188 + .../xingyun/sc/bo/retail/RetailProductBo.java | 120 + .../bo/retail/config/GetRetailConfigBo.java | 49 + .../sc/bo/retail/out/GetRetailOutSheetBo.java | 420 + .../bo/retail/out/PrintRetailOutSheetBo.java | 259 + .../bo/retail/out/QueryRetailOutSheetBo.java | 170 + .../out/QueryRetailOutSheetWithReturnBo.java | 99 + .../out/RetailOutSheetWithReturnBo.java | 299 + .../bo/retail/returned/GetRetailReturnBo.java | 412 + .../retail/returned/PrintRetailReturnBo.java | 272 + .../retail/returned/QueryRetailReturnBo.java | 191 + .../xingyun/sc/bo/sale/GetSaleOrderBo.java | 390 + .../xingyun/sc/bo/sale/PrintSaleOrderBo.java | 249 + .../xingyun/sc/bo/sale/QuerySaleOrderBo.java | 161 + .../sc/bo/sale/QuerySaleOrderWithOutBo.java | 86 + .../sc/bo/sale/SaleOrderWithOutBo.java | 318 + .../xingyun/sc/bo/sale/SaleProductBo.java | 120 + .../sc/bo/sale/config/GetSaleConfigBo.java | 49 + .../sc/bo/sale/out/GetSaleOutSheetBo.java | 446 + .../sc/bo/sale/out/PrintSaleOutSheetBo.java | 270 + .../sc/bo/sale/out/QuerySaleOutSheetBo.java | 188 + .../out/QuerySaleOutSheetWithReturnBo.java | 96 + .../bo/sale/out/SaleOutSheetWithReturnBo.java | 296 + .../sc/bo/sale/returned/GetSaleReturnBo.java | 409 + .../bo/sale/returned/PrintSaleReturnBo.java | 267 + .../bo/sale/returned/QuerySaleReturnBo.java | 188 + .../cost/QueryStockCostAdjustSheetBo.java | 131 + .../adjust/cost/StockCostAdjustProductBo.java | 100 + .../cost/StockCostAdjustSheetFullBo.java | 321 + .../adjust/stock/QueryStockAdjustSheetBo.java | 139 + .../adjust/stock/StockAdjustProductBo.java | 105 + .../adjust/stock/StockAdjustSheetFullBo.java | 320 + .../stock/reason/GetStockAdjustReasonBo.java | 49 + .../reason/QueryStockAdjustReasonBo.java | 82 + .../reason/StockAdjustReasonSelectorBo.java | 43 + .../bo/stock/product/QueryProductStockBo.java | 129 + .../product/log/QueryProductStockLogBo.java | 190 + .../take/config/GetTakeStockConfigBo.java | 63 + .../stock/take/plan/GetTakeStockPlanBo.java | 127 + .../stock/take/plan/QueryTakeStockPlanBo.java | 162 + .../plan/QueryTakeStockPlanProductBo.java | 114 + .../stock/take/plan/TakeStockPlanFullBo.java | 279 + .../take/plan/TakeStockPlanSelectorBo.java | 89 + .../take/pre/GetPreTakeStockSheetBo.java | 226 + .../stock/take/pre/PreTakeStockProductBo.java | 81 + .../take/pre/PreTakeStockSheetSelectorBo.java | 75 + .../take/pre/QueryPreTakeStockSheetBo.java | 98 + .../pre/QueryPreTakeStockSheetProductBo.java | 143 + .../take/sheet/QueryTakeStockSheetBo.java | 147 + .../take/sheet/TakeStockSheetFullBo.java | 351 + .../take/sheet/TakeStockSheetProductBo.java | 128 + .../transfer/QueryScTransferOrderBo.java | 147 + .../QueryScTransferOrderDetailReceiveBo.java | 42 + .../stock/transfer/ScTransferOrderFullBo.java | 319 + .../stock/transfer/ScTransferProductBo.java | 105 + .../components/code/GenerateCodeTypePool.java | 81 + .../sc/controller/ScSelectorController.java | 281 + .../logistics/LogisticsSheetController.java | 372 + .../purchase/PurchaseConfigController.java | 60 + .../purchase/PurchaseOrderController.java | 479 ++ .../purchase/PurchaseReturnController.java | 273 + .../purchase/ReceiveSheetController.java | 410 + .../retail/RetailConfigController.java | 60 + .../retail/RetailOutSheetController.java | 425 + .../retail/RetailReturnController.java | 279 + .../controller/sale/SaleConfigController.java | 60 + .../controller/sale/SaleOrderController.java | 398 + .../sale/SaleOutSheetController.java | 358 + .../controller/sale/SaleReturnController.java | 276 + .../stock/ProductStockController.java | 92 + .../stock/ProductStockLogController.java | 93 + .../adjust/StockAdjustReasonController.java | 157 + .../adjust/StockAdjustSheetController.java | 347 + .../StockCostAdjustSheetController.java | 314 + .../take/PreTakeStockSheetController.java | 272 + .../stock/take/TakeStockConfigController.java | 68 + .../stock/take/TakeStockPlanController.java | 284 + .../stock/take/TakeStockSheetController.java | 342 + .../transfer/ScTransferOrderController.java | 367 + .../ydool/YdoolPurchaseOrderController.java | 46 + .../ydool/YdoolRetailOutSheetController.java | 44 + .../ydool/YdoolSaleOrderController.java | 43 + .../YdoolStockAdjustSheetController.java | 44 + .../logistics/LogisticsSheetBizOrderDto.java | 48 + .../dto/logistics/LogisticsSheetFullDto.java | 182 + .../sc/dto/purchase/PurchaseOrderFullDto.java | 164 + .../purchase/PurchaseOrderWithReceiveDto.java | 92 + .../sc/dto/purchase/PurchaseProductDto.java | 82 + .../purchase/receive/GetPaymentDateDto.java | 22 + .../purchase/receive/ReceiveSheetFullDto.java | 178 + .../receive/ReceiveSheetWithReturnDto.java | 92 + .../returned/PurchaseReturnFullDto.java | 173 + .../sc/dto/retail/RetailProductDto.java | 82 + .../out/RetailOutSheetDetailLotDto.java | 48 + .../dto/retail/out/RetailOutSheetFullDto.java | 193 + .../out/RetailOutSheetWithReturnDto.java | 99 + .../retail/returned/RetailReturnFullDto.java | 188 + .../xingyun/sc/dto/sale/SaleOrderFullDto.java | 171 + .../sc/dto/sale/SaleOrderWithOutDto.java | 107 + .../xingyun/sc/dto/sale/SaleProductDto.java | 82 + .../sale/out/SaleOutSheetDetailLotDto.java | 48 + .../sc/dto/sale/out/SaleOutSheetFullDto.java | 193 + .../sale/out/SaleOutSheetWithReturnDto.java | 99 + .../dto/sale/returned/SaleReturnFullDto.java | 188 + .../adjust/cost/StockCostAdjustDiffDto.java | 27 + .../cost/StockCostAdjustProductDto.java | 82 + .../cost/StockCostAdjustSheetFullDto.java | 134 + .../adjust/stock/StockAdjustProductDto.java | 71 + .../adjust/stock/StockAdjustSheetFullDto.java | 119 + .../GetTakeStockPlanDetailProductDto.java | 29 + .../plan/QueryTakeStockPlanProductDto.java | 31 + .../stock/take/plan/TakeStockPlanFullDto.java | 123 + .../take/pre/PreTakeStockProductDto.java | 66 + .../take/pre/PreTakeStockSheetFullDto.java | 92 + .../pre/QueryPreTakeStockSheetProductDto.java | 37 + .../take/sheet/TakeStockSheetFullDto.java | 123 + .../take/sheet/TakeStockSheetProductDto.java | 66 + .../transfer/ScTransferOrderFullDto.java | 124 + .../stock/transfer/ScTransferProductDto.java | 71 + .../xingyun/sc/entity/LogisticsSheet.java | 178 + .../sc/entity/LogisticsSheetDetail.java | 44 + .../xingyun/sc/entity/OrderPayType.java | 48 + .../xingyun/sc/entity/PreTakeStockSheet.java | 86 + .../sc/entity/PreTakeStockSheetDetail.java | 56 + .../xingyun/sc/entity/ProductStock.java | 52 + .../xingyun/sc/entity/ProductStockLog.java | 111 + .../xingyun/sc/entity/PurchaseConfig.java | 46 + .../xingyun/sc/entity/PurchaseOrder.java | 133 + .../sc/entity/PurchaseOrderDetail.java | 72 + .../xingyun/sc/entity/PurchaseReturn.java | 146 + .../sc/entity/PurchaseReturnDetail.java | 74 + .../xingyun/sc/entity/ReceiveSheet.java | 149 + .../xingyun/sc/entity/ReceiveSheetDetail.java | 79 + .../xingyun/sc/entity/RetailConfig.java | 51 + .../xingyun/sc/entity/RetailOutSheet.java | 139 + .../sc/entity/RetailOutSheetDetail.java | 93 + .../sc/entity/RetailOutSheetDetailBundle.java | 78 + .../sc/entity/RetailOutSheetDetailLot.java | 60 + .../xingyun/sc/entity/RetailReturn.java | 146 + .../xingyun/sc/entity/RetailReturnDetail.java | 90 + .../xingyun/sc/entity/SaleConfig.java | 51 + .../xingyun/sc/entity/SaleOrder.java | 129 + .../xingyun/sc/entity/SaleOrderDetail.java | 87 + .../sc/entity/SaleOrderDetailBundle.java | 78 + .../xingyun/sc/entity/SaleOutSheet.java | 144 + .../xingyun/sc/entity/SaleOutSheetDetail.java | 98 + .../sc/entity/SaleOutSheetDetailBundle.java | 78 + .../sc/entity/SaleOutSheetDetailLot.java | 60 + .../xingyun/sc/entity/SaleReturn.java | 146 + .../xingyun/sc/entity/SaleReturnDetail.java | 90 + .../xingyun/sc/entity/ScTransferOrder.java | 118 + .../sc/entity/ScTransferOrderDetail.java | 63 + .../entity/ScTransferOrderDetailReceive.java | 62 + .../xingyun/sc/entity/StockAdjustReason.java | 87 + .../xingyun/sc/entity/StockAdjustSheet.java | 113 + .../sc/entity/StockAdjustSheetDetail.java | 52 + .../sc/entity/StockCostAdjustSheet.java | 112 + .../sc/entity/StockCostAdjustSheetDetail.java | 72 + .../xingyun/sc/entity/TakeStockConfig.java | 51 + .../xingyun/sc/entity/TakeStockPlan.java | 97 + .../sc/entity/TakeStockPlanDetail.java | 71 + .../xingyun/sc/entity/TakeStockSheet.java | 111 + .../sc/entity/TakeStockSheetDetail.java | 51 + .../sc/enums/LogisticsSheetDetailBizType.java | 31 + .../sc/enums/LogisticsSheetStatus.java | 31 + .../sc/enums/OrderAddressOrderType.java | 33 + .../sc/enums/PreTakeStockSheetStatus.java | 32 + .../xingyun/sc/enums/ProductStockBizType.java | 35 + .../xingyun/sc/enums/PurchaseOrderStatus.java | 34 + .../sc/enums/PurchaseReturnStatus.java | 31 + .../xingyun/sc/enums/ReceiveSheetStatus.java | 31 + .../sc/enums/RetailOutSheetStatus.java | 31 + .../xingyun/sc/enums/RetailReturnStatus.java | 31 + .../xingyun/sc/enums/SaleOrderStatus.java | 34 + .../xingyun/sc/enums/SaleOutSheetStatus.java | 31 + .../xingyun/sc/enums/SaleReturnStatus.java | 31 + .../xingyun/sc/enums/ScOpLogType.java | 25 + .../sc/enums/ScTransferOrderStatus.java | 31 + .../xingyun/sc/enums/SettleStatus.java | 31 + .../sc/enums/StockAdjustSheetBizType.java | 45 + .../sc/enums/StockAdjustSheetStatus.java | 31 + .../sc/enums/StockCostAdjustSheetStatus.java | 34 + .../xingyun/sc/enums/TakeStockPlanStatus.java | 31 + .../xingyun/sc/enums/TakeStockPlanType.java | 31 + .../sc/enums/TakeStockSheetStatus.java | 31 + .../LogisticsSheetDeliveryImportListener.java | 83 + .../LogisticsSheetDeliveryImportModel.java | 37 + .../logistics/LogisticsSheetExportModel.java | 211 + .../LogisticsSheetImportListener.java | 336 + .../logistics/LogisticsSheetImportModel.java | 200 + .../purchase/PurchaseOrderExportModel.java | 198 + .../purchase/PurchaseOrderImportListener.java | 169 + .../purchase/PurchaseOrderImportModel.java | 103 + .../PurchaseOrderPayTypeImportListener.java | 143 + .../PurchaseOrderPayTypeImportModel.java | 57 + .../receive/ReceiveSheetExportModel.java | 199 + .../receive/ReceiveSheetImportListener.java | 179 + .../receive/ReceiveSheetImportModel.java | 111 + .../ReceiveSheetPayTypeImportListener.java | 133 + .../ReceiveSheetPayTypeImportModel.java | 57 + .../returned/PurchaseReturnExportModel.java | 190 + .../retail/out/RetailOutSheetExportModel.java | 202 + .../returned/RetailReturnExportModel.java | 217 + .../sc/excel/sale/SaleOrderExportModel.java | 196 + .../sale/out/SaleOutSheetExportModel.java | 190 + .../sale/returned/SaleReturnExportModel.java | 190 + .../excel/stock/ProductStockExportModel.java | 120 + .../stock/ProductStockLogExportModel.java | 172 + .../adjust/StockAdjustSheetExportModel.java | 128 + .../StockCostAdjustSheetExportModel.java | 115 + .../take/plan/TakeStockPlanExportModel.java | 146 + .../pre/PreTakeStockSheetExportModel.java | 88 + .../take/sheet/TakeStockSheetExportModel.java | 136 + .../transfer/ScTransferOrderExportModel.java | 138 + .../sc/filter/RequestLoggingFilter.java | 52 + .../LogisticsSheetDetailServiceImpl.java | 23 + .../logistics/LogisticsSheetServiceImpl.java | 278 + .../impl/paytype/OrderPayTypeServiceImpl.java | 59 + .../purchase/PurchaseConfigServiceImpl.java | 53 + .../PurchaseOrderDetailServiceImpl.java | 83 + .../purchase/PurchaseOrderServiceImpl.java | 841 ++ .../PurchaseReturnDetailServiceImpl.java | 14 + .../purchase/PurchaseReturnServiceImpl.java | 669 ++ .../ReceiveSheetDetailServiceImpl.java | 82 + .../purchase/ReceiveSheetServiceImpl.java | 725 ++ .../impl/retail/RetailConfigServiceImpl.java | 53 + ...RetailOutSheetDetailBundleServiceImpl.java | 14 + .../RetailOutSheetDetailLotServiceImpl.java | 99 + .../RetailOutSheetDetailServiceImpl.java | 169 + .../retail/RetailOutSheetServiceImpl.java | 1178 +++ .../retail/RetailReturnDetailServiceImpl.java | 14 + .../impl/retail/RetailReturnServiceImpl.java | 654 ++ .../sc/impl/sale/SaleConfigServiceImpl.java | 53 + .../SaleOrderDetailBundleServiceImpl.java | 14 + .../impl/sale/SaleOrderDetailServiceImpl.java | 83 + .../sc/impl/sale/SaleOrderServiceImpl.java | 997 +++ .../SaleOutSheetDetailBundleServiceImpl.java | 14 + .../SaleOutSheetDetailLotServiceImpl.java | 99 + .../sale/SaleOutSheetDetailServiceImpl.java | 169 + .../sc/impl/sale/SaleOutSheetServiceImpl.java | 939 +++ .../sale/SaleReturnDetailServiceImpl.java | 14 + .../sc/impl/sale/SaleReturnServiceImpl.java | 675 ++ .../stock/ProductStockLogServiceImpl.java | 152 + .../impl/stock/ProductStockServiceImpl.java | 358 + .../adjust/StockAdjustReasonServiceImpl.java | 174 + .../StockAdjustSheetDetailServiceImpl.java | 14 + .../adjust/StockAdjustSheetServiceImpl.java | 738 ++ ...StockCostAdjustSheetDetailServiceImpl.java | 14 + .../StockCostAdjustSheetServiceImpl.java | 478 ++ .../PreTakeStockSheetDetailServiceImpl.java | 14 + .../take/PreTakeStockSheetServiceImpl.java | 246 + .../take/TakeStockConfigServiceImpl.java | 63 + .../take/TakeStockPlanDetailServiceImpl.java | 82 + .../stock/take/TakeStockPlanServiceImpl.java | 490 ++ .../take/TakeStockSheetDetailServiceImpl.java | 14 + .../stock/take/TakeStockSheetServiceImpl.java | 533 ++ ...TransferOrderDetailReceiveServiceImpl.java | 14 + .../ScTransferOrderDetailServiceImpl.java | 25 + .../transfer/ScTransferOrderServiceImpl.java | 541 ++ .../mappers/LogisticsSheetDetailMapper.java | 15 + .../sc/mappers/LogisticsSheetMapper.java | 74 + .../sc/mappers/OrderPayTypeMapper.java | 15 + .../PreTakeStockSheetDetailMapper.java | 15 + .../sc/mappers/PreTakeStockSheetMapper.java | 97 + .../sc/mappers/ProductStockLogMapper.java | 49 + .../sc/mappers/ProductStockMapper.java | 106 + .../sc/mappers/PurchaseConfigMapper.java | 8 + .../sc/mappers/PurchaseOrderDetailMapper.java | 43 + .../sc/mappers/PurchaseOrderMapper.java | 132 + .../mappers/PurchaseReturnDetailMapper.java | 16 + .../sc/mappers/PurchaseReturnMapper.java | 62 + .../sc/mappers/ReceiveSheetDetailMapper.java | 43 + .../sc/mappers/ReceiveSheetMapper.java | 97 + .../sc/mappers/RetailConfigMapper.java | 8 + .../RetailOutSheetDetailBundleMapper.java | 8 + .../RetailOutSheetDetailLotMapper.java | 43 + .../mappers/RetailOutSheetDetailMapper.java | 43 + .../sc/mappers/RetailOutSheetMapper.java | 120 + .../sc/mappers/RetailReturnDetailMapper.java | 16 + .../sc/mappers/RetailReturnMapper.java | 48 + .../xingyun/sc/mappers/SaleConfigMapper.java | 8 + .../mappers/SaleOrderDetailBundleMapper.java | 8 + .../sc/mappers/SaleOrderDetailMapper.java | 43 + .../xingyun/sc/mappers/SaleOrderMapper.java | 118 + .../SaleOutSheetDetailBundleMapper.java | 8 + .../mappers/SaleOutSheetDetailLotMapper.java | 43 + .../sc/mappers/SaleOutSheetDetailMapper.java | 43 + .../sc/mappers/SaleOutSheetMapper.java | 97 + .../sc/mappers/SaleReturnDetailMapper.java | 16 + .../xingyun/sc/mappers/SaleReturnMapper.java | 62 + .../mappers/ScTransferOrderDetailMapper.java | 33 + .../ScTransferOrderDetailReceiveMapper.java | 16 + .../sc/mappers/ScTransferOrderMapper.java | 78 + .../sc/mappers/StockAdjustReasonMapper.java | 43 + .../mappers/StockAdjustSheetDetailMapper.java | 15 + .../sc/mappers/StockAdjustSheetMapper.java | 92 + .../StockCostAdjustSheetDetailMapper.java | 15 + .../mappers/StockCostAdjustSheetMapper.java | 78 + .../sc/mappers/TakeStockConfigMapper.java | 15 + .../sc/mappers/TakeStockPlanDetailMapper.java | 65 + .../sc/mappers/TakeStockPlanMapper.java | 68 + .../mappers/TakeStockSheetDetailMapper.java | 15 + .../sc/mappers/TakeStockSheetMapper.java | 92 + .../LogisticsSheetDetailService.java | 17 + .../logistics/LogisticsSheetService.java | 101 + .../service/paytype/OrderPayTypeService.java | 32 + .../purchase/PurchaseConfigService.java | 22 + .../purchase/PurchaseOrderDetailService.java | 32 + .../purchase/PurchaseOrderService.java | 200 + .../purchase/PurchaseReturnDetailService.java | 8 + .../purchase/PurchaseReturnService.java | 145 + .../purchase/ReceiveSheetDetailService.java | 32 + .../service/purchase/ReceiveSheetService.java | 185 + .../service/retail/RetailConfigService.java | 22 + .../RetailOutSheetDetailBundleService.java | 9 + .../RetailOutSheetDetailLotService.java | 32 + .../retail/RetailOutSheetDetailService.java | 47 + .../service/retail/RetailOutSheetService.java | 188 + .../retail/RetailReturnDetailService.java | 8 + .../service/retail/RetailReturnService.java | 107 + .../sc/service/sale/SaleConfigService.java | 22 + .../sale/SaleOrderDetailBundleService.java | 8 + .../service/sale/SaleOrderDetailService.java | 32 + .../sc/service/sale/SaleOrderService.java | 186 + .../sale/SaleOutSheetDetailBundleService.java | 8 + .../sale/SaleOutSheetDetailLotService.java | 32 + .../sale/SaleOutSheetDetailService.java | 47 + .../sc/service/sale/SaleOutSheetService.java | 185 + .../service/sale/SaleReturnDetailService.java | 8 + .../sc/service/sale/SaleReturnService.java | 145 + .../service/stock/ProductStockLogService.java | 48 + .../sc/service/stock/ProductStockService.java | 73 + .../adjust/StockAdjustReasonService.java | 75 + .../adjust/StockAdjustSheetDetailService.java | 9 + .../stock/adjust/StockAdjustSheetService.java | 161 + .../StockCostAdjustSheetDetailService.java | 9 + .../adjust/StockCostAdjustSheetService.java | 136 + .../take/PreTakeStockSheetDetailService.java | 8 + .../stock/take/PreTakeStockSheetService.java | 116 + .../stock/take/TakeStockConfigService.java | 29 + .../take/TakeStockPlanDetailService.java | 43 + .../stock/take/TakeStockPlanService.java | 108 + .../take/TakeStockSheetDetailService.java | 8 + .../stock/take/TakeStockSheetService.java | 156 + .../ScTransferOrderDetailReceiveService.java | 9 + .../ScTransferOrderDetailService.java | 24 + .../transfer/ScTransferOrderService.java | 138 + .../lframework/xingyun/sc/utils/WebUtils.java | 109 + .../sc/vo/address/CreateOrderAddressVo.java | 81 + .../vo/logistics/CreateLogisticsSheetVo.java | 149 + .../logistics/DeliveryLogisticsSheetVo.java | 34 + .../logistics/LogisticsSheetBizOrderVo.java | 30 + .../LogisticsSheetCalcWeightOrVolumeVo.java | 45 + .../logistics/LogisticsSheetSelectorVo.java | 75 + .../QueryLogisticsSheetBizOrderVo.java | 36 + .../vo/logistics/QueryLogisticsSheetVo.java | 75 + .../vo/logistics/UpdateLogisticsSheetVo.java | 19 + .../xingyun/sc/vo/paytype/OrderPayTypeVo.java | 34 + .../purchase/ApprovePassPurchaseOrderVo.java | 26 + .../ApproveRefusePurchaseOrderVo.java | 27 + .../BatchApprovePassPurchaseOrderVo.java | 21 + .../BatchApproveRefusePurchaseOrderVo.java | 29 + .../sc/vo/purchase/CreatePurchaseOrderVo.java | 111 + .../vo/purchase/PurchaseOrderSelectorVo.java | 57 + .../sc/vo/purchase/PurchaseProductVo.java | 37 + .../sc/vo/purchase/QueryPurchaseOrderVo.java | 81 + .../QueryPurchaseOrderWithReceiveVo.java | 48 + .../vo/purchase/QueryPurchaseProductVo.java | 37 + .../sc/vo/purchase/UpdatePurchaseOrderVo.java | 19 + .../config/UpdatePurchaseConfigVo.java | 41 + .../receive/ApprovePassReceiveSheetVo.java | 26 + .../receive/ApproveRefuseReceiveSheetVo.java | 27 + .../BatchApprovePassReceiveSheetVo.java | 21 + .../BatchApproveRefuseReceiveSheetVo.java | 29 + .../receive/CreateReceiveSheetVo.java | 168 + .../purchase/receive/QueryReceiveSheetVo.java | 95 + .../QueryReceiveSheetWithReturnVo.java | 48 + .../vo/purchase/receive/ReceiveProductVo.java | 43 + .../receive/ReceiveSheetSelectorVo.java | 57 + .../receive/UpdateReceiveSheetVo.java | 31 + .../returned/ApprovePassPurchaseReturnVo.java | 26 + .../ApproveRefusePurchaseReturnVo.java | 27 + .../BatchApprovePassPurchaseReturnVo.java | 21 + .../BatchApproveRefusePurchaseReturnVo.java | 29 + .../returned/CreatePurchaseReturnVo.java | 162 + .../returned/QueryPurchaseReturnVo.java | 95 + .../vo/purchase/returned/ReturnProductVo.java | 43 + .../returned/UpdatePurchaseReturnVo.java | 32 + .../retail/config/UpdateRetailConfigVo.java | 48 + .../out/ApprovePassRetailOutSheetVo.java | 26 + .../out/ApproveRefuseRetailOutSheetVo.java | 27 + .../out/BatchApprovePassRetailOutSheetVo.java | 21 + .../BatchApproveRefuseRetailOutSheetVo.java | 29 + .../vo/retail/out/CreateRetailOutSheetVo.java | 151 + .../vo/retail/out/QueryRetailOutSheetVo.java | 89 + .../out/QueryRetailOutSheetWithReturnVo.java | 48 + .../vo/retail/out/QueryRetailProductVo.java | 43 + .../sc/vo/retail/out/RetailOutProductVo.java | 49 + .../retail/out/RetailOutSheetSelectorVo.java | 57 + .../vo/retail/out/UpdateRetailOutSheetVo.java | 20 + .../returned/ApprovePassRetailReturnVo.java | 26 + .../returned/ApproveRefuseRetailReturnVo.java | 27 + .../BatchApprovePassRetailReturnVo.java | 21 + .../BatchApproveRefuseRetailReturnVo.java | 29 + .../retail/returned/CreateRetailReturnVo.java | 200 + .../retail/returned/QueryRetailReturnVo.java | 95 + .../returned/RetailReturnProductVo.java | 55 + .../retail/returned/UpdateRetailReturnVo.java | 31 + .../sc/vo/sale/ApprovePassSaleOrderVo.java | 26 + .../sc/vo/sale/ApproveRefuseSaleOrderVo.java | 27 + .../vo/sale/BatchApprovePassSaleOrderVo.java | 21 + .../sale/BatchApproveRefuseSaleOrderVo.java | 29 + .../xingyun/sc/vo/sale/CreateSaleOrderVo.java | 116 + .../xingyun/sc/vo/sale/QuerySaleOrderVo.java | 81 + .../sc/vo/sale/QuerySaleOrderWithOutVo.java | 48 + .../sc/vo/sale/QuerySaleProductVo.java | 43 + .../sc/vo/sale/SaleOrderSelectorVo.java | 57 + .../xingyun/sc/vo/sale/SaleProductVo.java | 49 + .../xingyun/sc/vo/sale/UpdateSaleOrderVo.java | 19 + .../sc/vo/sale/config/UpdateSaleConfigVo.java | 48 + .../sale/out/ApprovePassSaleOutSheetVo.java | 26 + .../sale/out/ApproveRefuseSaleOutSheetVo.java | 27 + .../out/BatchApprovePassSaleOutSheetVo.java | 21 + .../out/BatchApproveRefuseSaleOutSheetVo.java | 29 + .../sc/vo/sale/out/CreateSaleOutSheetVo.java | 170 + .../sc/vo/sale/out/QuerySaleOutSheetVo.java | 95 + .../out/QuerySaleOutSheetWithReturnVo.java | 48 + .../sc/vo/sale/out/SaleOutProductVo.java | 55 + .../vo/sale/out/SaleOutSheetSelectorVo.java | 57 + .../sc/vo/sale/out/UpdateSaleOutSheetVo.java | 33 + .../returned/ApprovePassSaleReturnVo.java | 26 + .../returned/ApproveRefuseSaleReturnVo.java | 27 + .../BatchApprovePassSaleReturnVo.java | 21 + .../BatchApproveRefuseSaleReturnVo.java | 29 + .../vo/sale/returned/CreateSaleReturnVo.java | 169 + .../vo/sale/returned/QuerySaleReturnVo.java | 95 + .../vo/sale/returned/SaleReturnProductVo.java | 55 + .../vo/sale/returned/UpdateSaleReturnVo.java | 31 + .../sc/vo/stock/AddProductStockVo.java | 87 + .../sc/vo/stock/QueryProductStockVo.java | 39 + .../sc/vo/stock/StockCostAdjustVo.java | 71 + .../sc/vo/stock/SubProductStockVo.java | 80 + .../ApprovePassStockCostAdjustSheetVo.java | 26 + .../ApproveRefuseStockCostAdjustSheetVo.java | 27 + ...atchApprovePassStockCostAdjustSheetVo.java | 21 + ...chApproveRefuseStockCostAdjustSheetVo.java | 29 + .../cost/CreateStockCostAdjustSheetVo.java | 54 + .../cost/QueryStockCostAdjustProductVo.java | 37 + .../cost/QueryStockCostAdjustSheetVo.java | 78 + .../adjust/cost/StockCostAdjustProductVo.java | 37 + .../cost/UpdateStockCostAdjustSheetVo.java | 18 + .../stock/ApprovePassStockAdjustSheetVo.java | 26 + .../ApproveRefuseStockAdjustSheetVo.java | 27 + .../BatchApprovePassStockAdjustSheetVo.java | 21 + .../BatchApproveRefuseStockAdjustSheetVo.java | 29 + .../stock/CreateStockAdjustSheetVo.java | 68 + .../stock/QueryStockAdjustProductVo.java | 37 + .../adjust/stock/QueryStockAdjustSheetVo.java | 90 + .../adjust/stock/StockAdjustProductVo.java | 36 + .../stock/UpdateStockAdjustSheetVo.java | 18 + .../reason/CreateStockAdjustReasonVo.java | 35 + .../reason/QueryStockAdjustReasonVo.java | 31 + .../reason/StockAdjustReasonSelectorVo.java | 31 + .../reason/UpdateStockAdjustReasonVo.java | 50 + .../sc/vo/stock/log/AddLogWithAddStockVo.java | 122 + .../log/AddLogWithStockCostAdjustVo.java | 97 + .../sc/vo/stock/log/AddLogWithSubStockVo.java | 122 + .../vo/stock/log/QueryProductStockLogVo.java | 63 + .../sc/vo/stock/lot/AddProductLotStockVo.java | 30 + .../sc/vo/stock/lot/CreateProductLotVo.java | 73 + .../sc/vo/stock/lot/QueryProductLotVo.java | 58 + .../take/config/UpdateTakeStockConfigVo.java | 65 + .../take/plan/CancelTakeStockPlanVo.java | 20 + .../take/plan/CreateTakeStockPlanVo.java | 64 + .../take/plan/HandleTakeStockPlanVo.java | 74 + .../stock/take/plan/QueryTakeStockPlanVo.java | 78 + .../take/plan/TakeStockPlanSelectorVo.java | 82 + .../take/plan/UpdateTakeStockPlanVo.java | 35 + .../take/pre/CreatePreTakeStockSheetVo.java | 85 + .../stock/take/pre/PreTakeStockProductVo.java | 38 + .../take/pre/PreTakeStockSheetSelectorVo.java | 52 + .../take/pre/QueryPreTakeStockProductVo.java | 29 + .../take/pre/QueryPreTakeStockSheetVo.java | 58 + .../take/pre/UpdatePreTakeStockSheetVo.java | 18 + .../sheet/ApprovePassTakeStockSheetVo.java | 26 + .../sheet/ApproveRefuseTakeStockSheetVo.java | 27 + .../BatchApprovePassTakeStockSheetVo.java | 21 + .../BatchApproveRefuseTakeStockSheetVo.java | 29 + .../take/sheet/CreateTakeStockSheetVo.java | 43 + .../sheet/QueryTakeStockSheetProductVo.java | 37 + .../take/sheet/QueryTakeStockSheetVo.java | 99 + .../take/sheet/TakeStockSheetProductVo.java | 36 + .../take/sheet/UpdateTakeStockSheetVo.java | 37 + .../ApprovePassScTransferOrderVo.java | 26 + .../ApproveRefuseScTransferOrderVo.java | 27 + .../BatchApprovePassScTransferOrderVo.java | 21 + .../BatchApproveRefuseScTransferOrderVo.java | 29 + .../transfer/CreateScTransferOrderVo.java | 57 + .../QueryScTransferOrderDetailReceiveVo.java | 22 + .../transfer/QueryScTransferOrderVo.java | 84 + .../transfer/QueryScTransferProductVo.java | 37 + .../transfer/ReceiveScTransferOrderVo.java | 54 + .../stock/transfer/ScTransferProductVo.java | 36 + .../transfer/UpdateScTransferOrderVo.java | 18 + .../sc/vo/ydool/YdoolApproveOrderVo.java | 35 + xingyun-sc/src/main/java/lombok.config | 2 + .../logistics/LogisticsSheetMapper.xml | 219 + .../purchase/PurchaseOrderDetailMapper.xml | 49 + .../mappers/purchase/PurchaseOrderMapper.xml | 348 + .../mappers/purchase/PurchaseReturnMapper.xml | 190 + .../purchase/ReceiveSheetDetailMapper.xml | 49 + .../mappers/purchase/ReceiveSheetMapper.xml | 309 + .../retail/RetailOutSheetDetailLotMapper.xml | 41 + .../retail/RetailOutSheetDetailMapper.xml | 52 + .../mappers/retail/RetailOutSheetMapper.xml | 364 + .../mappers/retail/RetailReturnMapper.xml | 153 + .../mappers/sale/SaleOrderDetailMapper.xml | 53 + .../mappers/sale/SaleOrderMapper.xml | 352 + .../sale/SaleOutSheetDetailLotMapper.xml | 41 + .../mappers/sale/SaleOutSheetDetailMapper.xml | 52 + .../mappers/sale/SaleOutSheetMapper.xml | 301 + .../mappers/sale/SaleReturnMapper.xml | 169 + .../mappers/stock/ProductStockLogMapper.xml | 82 + .../mappers/stock/ProductStockMapper.xml | 90 + .../stock/adjust/StockAdjustReasonMapper.xml | 44 + .../stock/adjust/StockAdjustSheetMapper.xml | 186 + .../adjust/StockCostAdjustSheetMapper.xml | 215 + .../stock/take/PreTaskStockSheetMapper.xml | 223 + .../stock/take/TakeStockConfigMapper.xml | 5 + .../stock/take/TakeStockPlanDetailMapper.xml | 64 + .../stock/take/TakeStockPlanMapper.xml | 184 + .../stock/take/TakeStockSheetMapper.xml | 227 + .../transfer/ScTransferOrderDetailMapper.xml | 16 + .../stock/transfer/ScTransferOrderMapper.xml | 177 + .../main/resources/print/purchase-order.ftl | 179 + .../main/resources/print/purchase-return.ftl | 191 + .../main/resources/print/receive-sheet.ftl | 192 + .../main/resources/print/retail-out-sheet.ftl | 165 + .../main/resources/print/retail-return.ftl | 170 + .../src/main/resources/print/sale-order.ftl | 175 + .../main/resources/print/sale-out-sheet.ftl | 192 + .../src/main/resources/print/sale-return.ftl | 183 + xingyun-settle/pom.xml | 26 + .../bo/check/GetSettleCheckSheetBo.java | 277 + .../bo/check/QuerySettleCheckSheetBo.java | 178 + .../settle/bo/check/SettleCheckBizItemBo.java | 73 + .../CustomerSettleCheckBizItemBo.java | 74 + .../GetCustomerSettleCheckSheetBo.java | 282 + .../QueryCustomerSettleCheckSheetBo.java | 179 + .../settle/bo/fee/GetSettleFeeSheetBo.java | 209 + .../settle/bo/fee/QuerySettleFeeSheetBo.java | 140 + .../customer/GetCustomerSettleFeeSheetBo.java | 212 + .../QueryCustomerSettleFeeSheetBo.java | 141 + .../settle/bo/item/in/GetSettleInItemBo.java | 49 + .../bo/item/in/QuerySettleInItemBo.java | 82 + .../bo/item/in/SettleInItemSelectorBo.java | 43 + .../bo/item/out/GetSettleOutItemBo.java | 49 + .../bo/item/out/QuerySettleOutItemBo.java | 82 + .../bo/item/out/SettleOutItemSelectorBo.java | 43 + .../settle/bo/pre/GetSettlePreSheetBo.java | 189 + .../settle/bo/pre/QuerySettlePreSheetBo.java | 132 + .../customer/GetCustomerSettlePreSheetBo.java | 191 + .../QueryCustomerSettlePreSheetBo.java | 133 + .../settle/bo/sheet/GetSettleSheetBo.java | 266 + .../settle/bo/sheet/QuerySettleSheetBo.java | 149 + .../settle/bo/sheet/SettleBizItemBo.java | 77 + .../customer/CustomerSettleBizItemBo.java | 77 + .../customer/GetCustomerSettleSheetBo.java | 270 + .../customer/QueryCustomerSettleSheetBo.java | 149 + .../components/code/GenerateCodeTypePool.java | 46 + .../CustomerSettleCheckSheetController.java | 281 + .../CustomerSettleFeeSheetController.java | 258 + .../CustomerSettlePreSheetController.java | 258 + .../CustomerSettleSheetController.java | 278 + .../SettleCheckSheetController.java | 267 + .../controller/SettleFeeSheetController.java | 247 + .../controller/SettleInItemController.java | 186 + .../controller/SettleOutItemController.java | 186 + .../controller/SettlePreSheetController.java | 247 + .../controller/SettleSelectorController.java | 132 + .../controller/SettleSheetController.java | 267 + .../dto/check/SettleCheckBizItemDto.java | 45 + .../dto/check/SettleCheckSheetFullDto.java | 155 + .../CustomerSettleCheckBizItemDto.java | 45 + .../CustomerSettleCheckSheetFullDto.java | 155 + .../settle/dto/fee/SettleFeeSheetFullDto.java | 118 + .../CustomerSettleFeeSheetFullDto.java | 118 + .../settle/dto/pre/SettlePreSheetFullDto.java | 112 + .../CustomerSettlePreSheetFullDto.java | 112 + .../settle/dto/sheet/SettleBizItemDto.java | 48 + .../settle/dto/sheet/SettleSheetFullDto.java | 132 + .../customer/CustomerSettleBizItemDto.java | 48 + .../customer/CustomerSettleSheetFullDto.java | 132 + .../entity/CustomerSettleCheckSheet.java | 138 + .../CustomerSettleCheckSheetDetail.java | 66 + .../settle/entity/CustomerSettleFeeSheet.java | 119 + .../entity/CustomerSettleFeeSheetDetail.java | 49 + .../settle/entity/CustomerSettlePreSheet.java | 112 + .../entity/CustomerSettlePreSheetDetail.java | 49 + .../settle/entity/CustomerSettleSheet.java | 123 + .../entity/CustomerSettleSheetDetail.java | 59 + .../settle/entity/SettleCheckSheet.java | 138 + .../settle/entity/SettleCheckSheetDetail.java | 66 + .../xingyun/settle/entity/SettleFeeSheet.java | 119 + .../settle/entity/SettleFeeSheetDetail.java | 49 + .../xingyun/settle/entity/SettleInItem.java | 87 + .../xingyun/settle/entity/SettleOutItem.java | 87 + .../xingyun/settle/entity/SettlePreSheet.java | 112 + .../settle/entity/SettlePreSheetDetail.java | 49 + .../xingyun/settle/entity/SettleSheet.java | 123 + .../settle/entity/SettleSheetDetail.java | 59 + .../CustomerSettleCheckSheetBizType.java | 32 + .../CustomerSettleCheckSheetCalcType.java | 31 + .../enums/CustomerSettleCheckSheetStatus.java | 31 + .../enums/CustomerSettleFeeSheetStatus.java | 31 + .../enums/CustomerSettleFeeSheetType.java | 31 + .../enums/CustomerSettlePreSheetStatus.java | 31 + .../enums/CustomerSettleSheetStatus.java | 31 + .../settle/enums/SettleCheckSheetBizType.java | 32 + .../enums/SettleCheckSheetCalcType.java | 31 + .../settle/enums/SettleCheckSheetStatus.java | 31 + .../settle/enums/SettleFeeSheetStatus.java | 31 + .../settle/enums/SettleFeeSheetType.java | 31 + .../xingyun/settle/enums/SettleOpLogType.java | 7 + .../settle/enums/SettlePreSheetStatus.java | 31 + .../settle/enums/SettleSheetStatus.java | 31 + .../check/SettleCheckSheetExportModel.java | 167 + .../CustomerSettleCheckSheetExportModel.java | 170 + .../excel/fee/SettleFeeSheetExportModel.java | 137 + .../CustomerSettleFeeSheetExportModel.java | 139 + .../item/in/SettleInItemExportModel.java | 43 + .../item/out/SettleOutItemExportModel.java | 43 + .../excel/pre/SettlePreSheetExportModel.java | 137 + .../CustomerSettlePreSheetExportModel.java | 139 + .../excel/sheet/SettleSheetExportModel.java | 136 + .../CustomerSettleSheetExportModel.java | 138 + ...omerSettleCheckSheetDetailServiceImpl.java | 15 + .../CustomerSettleCheckSheetServiceImpl.java | 856 ++ ...stomerSettleFeeSheetDetailServiceImpl.java | 14 + .../CustomerSettleFeeSheetServiceImpl.java | 464 ++ ...stomerSettlePreSheetDetailServiceImpl.java | 14 + .../CustomerSettlePreSheetServiceImpl.java | 446 + .../CustomerSettleSheetDetailServiceImpl.java | 14 + .../impl/CustomerSettleSheetServiceImpl.java | 558 ++ .../SettleCheckSheetDetailServiceImpl.java | 14 + .../impl/SettleCheckSheetServiceImpl.java | 799 ++ .../impl/SettleFeeSheetDetailServiceImpl.java | 13 + .../impl/SettleFeeSheetServiceImpl.java | 440 + .../settle/impl/SettleInItemServiceImpl.java | 166 + .../settle/impl/SettleOutItemServiceImpl.java | 166 + .../impl/SettlePreSheetDetailServiceImpl.java | 13 + .../impl/SettlePreSheetServiceImpl.java | 426 + .../impl/SettleSheetDetailServiceImpl.java | 13 + .../settle/impl/SettleSheetServiceImpl.java | 542 ++ .../CustomerSettleCheckSheetDetailMapper.java | 17 + .../CustomerSettleCheckSheetMapper.java | 60 + .../CustomerSettleFeeSheetDetailMapper.java | 17 + .../mappers/CustomerSettleFeeSheetMapper.java | 62 + .../CustomerSettlePreSheetDetailMapper.java | 17 + .../mappers/CustomerSettlePreSheetMapper.java | 62 + .../CustomerSettleSheetDetailMapper.java | 16 + .../mappers/CustomerSettleSheetMapper.java | 48 + .../mappers/SettleCheckSheetDetailMapper.java | 16 + .../mappers/SettleCheckSheetMapper.java | 61 + .../mappers/SettleFeeSheetDetailMapper.java | 16 + .../settle/mappers/SettleFeeSheetMapper.java | 63 + .../settle/mappers/SettleInItemMapper.java | 36 + .../settle/mappers/SettleOutItemMapper.java | 36 + .../mappers/SettlePreSheetDetailMapper.java | 16 + .../settle/mappers/SettlePreSheetMapper.java | 63 + .../mappers/SettleSheetDetailMapper.java | 16 + .../settle/mappers/SettleSheetMapper.java | 49 + ...CustomerSettleCheckSheetDetailService.java | 9 + .../CustomerSettleCheckSheetService.java | 198 + .../CustomerSettleFeeSheetDetailService.java | 9 + .../CustomerSettleFeeSheetService.java | 146 + .../CustomerSettlePreSheetDetailService.java | 9 + .../CustomerSettlePreSheetService.java | 146 + .../CustomerSettleSheetDetailService.java | 9 + .../service/CustomerSettleSheetService.java | 147 + .../SettleCheckSheetDetailService.java | 8 + .../service/SettleCheckSheetService.java | 190 + .../service/SettleFeeSheetDetailService.java | 8 + .../settle/service/SettleFeeSheetService.java | 139 + .../settle/service/SettleInItemService.java | 74 + .../settle/service/SettleOutItemService.java | 77 + .../service/SettlePreSheetDetailService.java | 8 + .../settle/service/SettlePreSheetService.java | 139 + .../service/SettleSheetDetailService.java | 8 + .../settle/service/SettleSheetService.java | 140 + .../check/ApprovePassSettleCheckSheetVo.java | 26 + .../ApproveRefuseSettleCheckSheetVo.java | 27 + .../BatchApprovePassSettleCheckSheetVo.java | 21 + .../BatchApproveRefuseSettleCheckSheetVo.java | 29 + .../vo/check/CreateSettleCheckSheetVo.java | 72 + .../vo/check/QuerySettleCheckSheetVo.java | 77 + .../vo/check/QueryUnCheckBizItemVo.java | 33 + .../vo/check/SettleCheckSheetItemVo.java | 40 + .../vo/check/UpdateSettleCheckSheetVo.java | 18 + ...ApprovePassCustomerSettleCheckSheetVo.java | 26 + ...proveRefuseCustomerSettleCheckSheetVo.java | 27 + ...ApprovePassCustomerSettleCheckSheetVo.java | 21 + ...proveRefuseCustomerSettleCheckSheetVo.java | 29 + .../CreateCustomerSettleCheckSheetVo.java | 72 + .../CustomerSettleCheckSheetItemVo.java | 40 + .../QueryCustomerSettleCheckSheetVo.java | 77 + .../QueryCustomerUnCheckBizItemVo.java | 33 + .../UpdateCustomerSettleCheckSheetVo.java | 18 + .../vo/fee/ApprovePassSettleFeeSheetVo.java | 26 + .../vo/fee/ApproveRefuseSettleFeeSheetVo.java | 27 + .../fee/BatchApprovePassSettleFeeSheetVo.java | 21 + .../BatchApproveRefuseSettleFeeSheetVo.java | 29 + .../settle/vo/fee/CreateSettleFeeSheetVo.java | 76 + .../settle/vo/fee/QuerySettleFeeSheetVo.java | 77 + .../settle/vo/fee/SettleFeeSheetItemVo.java | 25 + .../settle/vo/fee/UpdateSettleFeeSheetVo.java | 18 + .../ApprovePassCustomerSettleFeeSheetVo.java | 26 + ...ApproveRefuseCustomerSettleFeeSheetVo.java | 27 + ...chApprovePassCustomerSettleFeeSheetVo.java | 21 + ...ApproveRefuseCustomerSettleFeeSheetVo.java | 29 + .../CreateCustomerSettleFeeSheetVo.java | 76 + .../CustomerSettleFeeSheetItemVo.java | 25 + .../QueryCustomerSettleFeeSheetVo.java | 77 + .../UpdateCustomerSettleFeeSheetVo.java | 18 + .../vo/item/in/CreateSettleInItemVo.java | 35 + .../vo/item/in/QuerySettleInItemVo.java | 31 + .../vo/item/in/SettleInItemSelectorVo.java | 31 + .../vo/item/in/UpdateSettleInItemVo.java | 50 + .../vo/item/out/CreateSettleOutItemVo.java | 35 + .../vo/item/out/QuerySettleOutItemVo.java | 31 + .../vo/item/out/SettleOutItemSelectorVo.java | 31 + .../vo/item/out/UpdateSettleOutItemVo.java | 50 + .../vo/pre/ApprovePassSettlePreSheetVo.java | 26 + .../vo/pre/ApproveRefuseSettlePreSheetVo.java | 27 + .../pre/BatchApprovePassSettlePreSheetVo.java | 21 + .../BatchApproveRefuseSettlePreSheetVo.java | 29 + .../settle/vo/pre/CreateSettlePreSheetVo.java | 66 + .../settle/vo/pre/QuerySettlePreSheetVo.java | 77 + .../settle/vo/pre/SettlePreSheetItemVo.java | 25 + .../settle/vo/pre/UpdateSettlePreSheetVo.java | 18 + .../ApprovePassCustomerSettlePreSheetVo.java | 26 + ...ApproveRefuseCustomerSettlePreSheetVo.java | 27 + ...chApprovePassCustomerSettlePreSheetVo.java | 21 + ...ApproveRefuseCustomerSettlePreSheetVo.java | 29 + .../CreateCustomerSettlePreSheetVo.java | 66 + .../CustomerSettlePreSheetItemVo.java | 25 + .../QueryCustomerSettlePreSheetVo.java | 77 + .../UpdateCustomerSettlePreSheetVo.java | 18 + .../vo/sheet/ApprovePassSettleSheetVo.java | 26 + .../vo/sheet/ApproveRefuseSettleSheetVo.java | 27 + .../sheet/BatchApprovePassSettleSheetVo.java | 21 + .../BatchApproveRefuseSettleSheetVo.java | 29 + .../settle/vo/sheet/CreateSettleSheetVo.java | 72 + .../settle/vo/sheet/QuerySettleSheetVo.java | 69 + .../vo/sheet/QueryUnSettleBizItemVo.java | 33 + .../settle/vo/sheet/SettleSheetItemVo.java | 37 + .../settle/vo/sheet/UpdateSettleSheetVo.java | 18 + .../ApprovePassCustomerSettleSheetVo.java | 26 + .../ApproveRefuseCustomerSettleSheetVo.java | 27 + ...BatchApprovePassCustomerSettleSheetVo.java | 21 + ...tchApproveRefuseCustomerSettleSheetVo.java | 29 + .../customer/CreateCustomerSettleSheetVo.java | 72 + .../customer/CustomerSettleSheetItemVo.java | 37 + .../customer/QueryCustomerSettleSheetVo.java | 69 + .../QueryCustomerUnSettleBizItemVo.java | 33 + .../customer/UpdateCustomerSettleSheetVo.java | 18 + xingyun-settle/src/main/java/lombok.config | 2 + .../CustomerSettleCheckSheetMapper.xml | 181 + .../mappers/CustomerSettleFeeSheetMapper.xml | 155 + .../mappers/CustomerSettlePreSheetMapper.xml | 151 + .../mappers/CustomerSettleSheetMapper.xml | 145 + .../mappers/SettleCheckSheetMapper.xml | 180 + .../mappers/SettleFeeSheetMapper.xml | 154 + .../resources/mappers/SettleInItemMapper.xml | 63 + .../resources/mappers/SettleOutItemMapper.xml | 63 + .../mappers/SettlePreSheetMapper.xml | 150 + .../resources/mappers/SettleSheetMapper.xml | 144 + xingyun-template-core/pom.xml | 22 + .../template/core/annotations/OpLog.java | 56 + .../permission/DataPermission.java | 17 + .../permission/DataPermissions.java | 18 + .../template/core/annotations/sort/Sort.java | 36 + .../template/core/annotations/sort/Sorts.java | 15 + .../template/core/aop/OpLogAspector.java | 190 + .../core/components/WebExceptionHandler.java | 391 + .../permission/DataPermissionHandlerImpl.java | 155 + .../SysDataPermissionDataPermissionType.java | 23 + .../core/components/qrtz/QrtzHandler.java | 321 + .../core/components/qrtz/QrtzJob.java | 52 + .../config/MpInterceptorConfiguration.java | 26 + .../xingyun/template/core/dto/DeptDto.java | 28 + .../xingyun/template/core/dto/UserDto.java | 33 + .../xingyun/template/core/entity/OpLogs.java | 66 + .../core/entity/RecursionMapping.java | 43 + .../core/entity/SysDataPermissionData.java | 44 + .../entity/SysDataPermissionModelDetail.java | 67 + .../xingyun/template/core/entity/SysUser.java | 118 + .../template/core/enums/Available.java | 32 + .../template/core/enums/DefaultOpLogType.java | 24 + .../xingyun/template/core/enums/Gender.java | 31 + .../xingyun/template/core/enums/NodeType.java | 7 + .../enums/SysDataPermissionDataBizType.java | 31 + .../SysDataPermissionModelDetailCalcType.java | 39 + ...ataPermissionModelDetailConditionType.java | 43 + ...SysDataPermissionModelDetailInputType.java | 33 + .../SysDataPermissionModelDetailNodeType.java | 32 + .../template/core/impl/DeptServiceImpl.java | 43 + .../template/core/impl/OpLogsServiceImpl.java | 120 + .../impl/RecursionMappingServiceImpl.java | 102 + ...sDataPermissionModelDetailServiceImpl.java | 145 + .../template/core/impl/UserServiceImpl.java | 45 + .../interceptors/CustomSortInterceptor.java | 132 + .../template/core/mappers/DeptMapper.java | 25 + .../template/core/mappers/OpLogsMapper.java | 41 + .../core/mappers/RecursionMappingMapper.java | 19 + .../SysDataPermissionModelDetailMapper.java | 9 + .../template/core/mappers/UserMapper.java | 27 + .../template/core/service/DeptService.java | 28 + .../template/core/service/OpLogsService.java | 58 + .../core/service/RecursionMappingService.java | 62 + .../SysDataPermissionModelDetailService.java | 29 + .../template/core/service/UserService.java | 28 + .../template/core/utils/OpLogUtil.java | 117 + .../xingyun/template/core/utils/WebUtils.java | 117 + .../template/core/vo/CreateOpLogsVo.java | 51 + .../template/core/vo/QueryOpLogsVo.java | 47 + .../CreateSysDataPermissionDataVo.java | 45 + .../SysDataPermissionModelDetailVo.java | 65 + .../src/main/java/lombok.config | 2 + .../src/main/resources/mappers/DeptMapper.xml | 14 + .../main/resources/mappers/OpLogsMapper.xml | 49 + .../mappers/RecursionMappingMappre.xml | 12 + .../src/main/resources/mappers/UserMapper.xml | 15 + xingyun-template/pom.xml | 38 + .../config/TemplateApiConfiguration.java | 31 + .../custom/list/GenCustomListSelectorBo.java | 55 + .../bo/custom/list/GetGenCustomListBo.java | 500 ++ .../bo/custom/list/QueryGenCustomListBo.java | 97 + .../GenCustomListCategorySelectorBo.java | 35 + .../category/GetGenCustomListCategoryBo.java | 38 + .../QueryGenCustomListCategoryBo.java | 38 + .../custom/page/GenCustomPageSelectorBo.java | 50 + .../bo/custom/page/GetGenCustomPageBo.java | 74 + .../bo/custom/page/QueryGenCustomPageBo.java | 92 + .../GenCustomPageCategorySelectorBo.java | 41 + .../category/GetGenCustomPageCategoryBo.java | 44 + .../QueryGenCustomPageCategoryBo.java | 44 + .../selector/GenCustomSelectorSelectorBo.java | 50 + .../selector/GetGenCustomSelectorBo.java | 125 + .../selector/QueryGenCustomSelectorBo.java | 98 + .../GenCustomSelectorCategorySelectorBo.java | 35 + .../GetGenCustomSelectorCategoryBo.java | 38 + .../QueryGenCustomSelectorCategoryBo.java | 38 + .../bo/data/entity/DataEntityGenerateBo.java | 114 + .../bo/data/entity/GenDataEntityDetailBo.java | 169 + .../entity/GenDataEntityDetailGenerateBo.java | 119 + .../entity/GenDataEntityDetailSelectorBo.java | 33 + .../data/entity/GenDataEntitySelectorBo.java | 49 + .../gen/bo/data/entity/GetDataEntityBo.java | 95 + .../gen/bo/data/entity/QueryDataEntityBo.java | 104 + .../GenDataEntityCategorySelectorBo.java | 35 + .../category/GetGenDataEntityCategoryBo.java | 38 + .../QueryGenDataEntityCategoryBo.java | 38 + .../gen/bo/data/obj/GenDataObjColumnBo.java | 68 + .../gen/bo/data/obj/GenDataObjDetailBo.java | 92 + .../bo/data/obj/GenDataObjQueryDetailBo.java | 60 + .../gen/bo/data/obj/GenDataObjSelectorBo.java | 49 + .../gen/bo/data/obj/GetGenDataObjBo.java | 131 + .../gen/bo/data/obj/QueryGenDataObjBo.java | 97 + .../GenDataObjCategorySelectorBo.java | 35 + .../obj/category/GetGenDataObjCategoryBo.java | 38 + .../category/QueryGenDataObjCategoryBo.java | 38 + .../gen/bo/gen/GenCreateColumnConfigBo.java | 49 + .../gen/bo/gen/GenDetailColumnConfigBo.java | 49 + .../gen/bo/gen/GenGenerateInfoBo.java | 121 + .../gen/bo/gen/GenQueryColumnConfigBo.java | 61 + .../bo/gen/GenQueryParamsColumnConfigBo.java | 49 + .../gen/bo/gen/GenUpdateColumnConfigBo.java | 49 + .../gen/bo/simpledb/SimpleDBSelectorBo.java | 33 + .../gen/builders/CustomListBuilder.java | 370 + .../gen/builders/CustomPageBuilder.java | 40 + .../gen/builders/CustomSelectorBuilder.java | 65 + .../gen/builders/DataEntityBuilder.java | 117 + .../gen/builders/DataObjectBuilder.java | 151 + .../gen/components/CreateColumnConfig.java | 19 + .../template/gen/components/DataEntity.java | 42 + .../gen/components/DataEntityColumn.java | 130 + .../gen/components/DetailColumnConfig.java | 18 + .../gen/components/QueryColumnConfig.java | 34 + .../components/QueryParamsColumnConfig.java | 20 + .../template/gen/components/Table.java | 34 + .../template/gen/components/TableColumn.java | 11 + .../gen/components/UpdateColumnConfig.java | 18 + .../custom/list/CustomListConfig.java | 377 + .../custom/page/CustomPageConfig.java | 27 + .../custom/selector/CustomSelectorConfig.java | 51 + .../data/obj/DataObjectQueryObj.java | 122 + .../data/obj/DataObjectQueryParamObj.java | 58 + .../MagicCustomAuthorizationInterceptor.java | 63 + .../magic/MagicCustomJsonValueProvider.java | 38 + .../magic/MagicCustomMagicFunction.java | 27 + .../components/magic/MagicCustomSqlCache.java | 33 + .../gen/config/MagicCustomConfiguration.java | 62 + .../template/gen/constants/GenStringPool.java | 5 + .../gen/controller/GenController.java | 174 + .../GenCustomListCategoryController.java | 116 + .../controller/GenCustomListController.java | 140 + .../GenCustomPageCategoryController.java | 118 + .../controller/GenCustomPageController.java | 114 + .../GenCustomSelectorCategoryController.java | 118 + .../GenCustomSelectorController.java | 141 + .../GenDataEntityCategoryController.java | 116 + .../controller/GenDataEntityController.java | 307 + .../GenDataObjCategoryController.java | 116 + .../gen/controller/GenDataObjController.java | 259 + .../gen/controller/GenSelectorController.java | 523 ++ .../converters/GenMysqlDataTypeConverter.java | 21 + .../gen/converters/GenStringConverter.java | 61 + .../gen/converters/GenViewTypeConverter.java | 62 + .../gen/directives/FormatDirective.java | 117 + .../data/entity/DataEntityGenerateDto.java | 52 + .../data/entity/GenDataEntityDetailDto.java | 84 + .../gen/dto/gen/GenCreateColumnConfigDto.java | 27 + .../gen/dto/gen/GenDetailColumnConfigDto.java | 27 + .../gen/dto/gen/GenGenerateInfoDto.java | 88 + .../gen/dto/gen/GenQueryColumnConfigDto.java | 38 + .../gen/GenQueryParamsColumnConfigDto.java | 29 + .../gen/dto/gen/GenUpdateColumnConfigDto.java | 27 + .../gen/dto/generate/GenerateDto.java | 26 + .../dto/simpledb/OriSimpleTableColumnDto.java | 72 + .../gen/dto/simpledb/OriSimpleTableDto.java | 64 + .../gen/dto/simpledb/SimpleDBDto.java | 21 + .../gen/dto/simpledb/SimpleTableDto.java | 64 + .../gen/entity/GenCreateColumnConfig.java | 38 + .../template/gen/entity/GenCustomList.java | 168 + .../gen/entity/GenCustomListCategory.java | 76 + .../gen/entity/GenCustomListDetail.java | 73 + .../gen/entity/GenCustomListHandleColumn.java | 75 + .../gen/entity/GenCustomListQueryParams.java | 72 + .../gen/entity/GenCustomListToolbar.java | 70 + .../template/gen/entity/GenCustomPage.java | 95 + .../gen/entity/GenCustomPageCategory.java | 81 + .../gen/entity/GenCustomSelector.java | 126 + .../gen/entity/GenCustomSelectorCategory.java | 76 + .../template/gen/entity/GenDataEntity.java | 135 + .../gen/entity/GenDataEntityCategory.java | 76 + .../gen/entity/GenDataEntityDetail.java | 160 + .../template/gen/entity/GenDataObj.java | 97 + .../gen/entity/GenDataObjCategory.java | 76 + .../template/gen/entity/GenDataObjDetail.java | 70 + .../gen/entity/GenDataObjQueryDetail.java | 59 + .../gen/entity/GenDetailColumnConfig.java | 38 + .../template/gen/entity/GenGenerateInfo.java | 98 + .../gen/entity/GenQueryColumnConfig.java | 49 + .../entity/GenQueryParamsColumnConfig.java | 39 + .../template/gen/entity/GenSimpleTable.java | 63 + .../gen/entity/GenSimpleTableColumn.java | 83 + .../gen/entity/GenUpdateColumnConfig.java | 38 + .../gen/entity/GenerateColumnConfig.java | 5 + .../template/gen/entity/GenerateConfig.java | 13 + .../template/gen/enums/GenConvertType.java | 31 + .../gen/enums/GenCustomListBtnType.java | 34 + .../gen/enums/GenCustomListBtnViewType.java | 37 + .../gen/enums/GenCustomListDetailType.java | 33 + .../template/gen/enums/GenCustomListType.java | 33 + .../template/gen/enums/GenDataType.java | 86 + .../template/gen/enums/GenKeyType.java | 31 + .../template/gen/enums/GenMySqlDataType.java | 72 + .../template/gen/enums/GenOrderType.java | 31 + .../template/gen/enums/GenQueryType.java | 39 + .../template/gen/enums/GenQueryWidthType.java | 31 + .../template/gen/enums/GenRelaMode.java | 37 + .../template/gen/enums/GenRelaType.java | 29 + .../xingyun/template/gen/enums/GenStatus.java | 31 + .../template/gen/enums/GenTemplateType.java | 31 + .../xingyun/template/gen/enums/GenType.java | 31 + .../template/gen/enums/GenViewType.java | 34 + .../gen/events/CustomListDeleteEvent.java | 36 + .../gen/events/DataEntityDeleteEvent.java | 58 + .../events/DataEntityDetailDeleteEvent.java | 45 + .../gen/events/DataObjDeleteEvent.java | 63 + .../events/DataObjQueryDetailDeleteEvent.java | 45 + .../template/gen/generate/Generator.java | 1658 ++++ .../templates/ControllerTemplate.java | 116 + .../generate/templates/CreateTemplate.java | 210 + .../generate/templates/DetailTemplate.java | 160 + .../generate/templates/EntityTemplate.java | 112 + .../generate/templates/MapperTemplate.java | 100 + .../templates/QueryParamsTemplate.java | 131 + .../gen/generate/templates/QueryTemplate.java | 170 + .../generate/templates/ServiceTemplate.java | 106 + .../gen/generate/templates/SqlTemplate.java | 60 + .../generate/templates/UpdateTemplate.java | 205 + .../GenCreateColumnConfigServiceImpl.java | 74 + .../GenCustomListCategoryServiceImpl.java | 132 + .../impl/GenCustomListDetailServiceImpl.java | 33 + .../GenCustomListHandleColumnServiceImpl.java | 32 + .../GenCustomListQueryParamsServiceImpl.java | 34 + .../gen/impl/GenCustomListServiceImpl.java | 526 ++ .../impl/GenCustomListToolbarServiceImpl.java | 31 + .../GenCustomPageCategoryServiceImpl.java | 135 + .../gen/impl/GenCustomPageServiceImpl.java | 129 + .../GenCustomSelectorCategoryServiceImpl.java | 134 + .../impl/GenCustomSelectorServiceImpl.java | 184 + .../GenDataEntityCategoryServiceImpl.java | 132 + .../impl/GenDataEntityDetailServiceImpl.java | 44 + .../gen/impl/GenDataEntityServiceImpl.java | 546 ++ .../impl/GenDataObjCategoryServiceImpl.java | 132 + .../gen/impl/GenDataObjDetailServiceImpl.java | 37 + .../GenDataObjQueryDetailServiceImpl.java | 33 + .../gen/impl/GenDataObjServiceImpl.java | 327 + .../GenDetailColumnConfigServiceImpl.java | 73 + .../impl/GenQueryColumnConfigServiceImpl.java | 78 + ...GenQueryParamsColumnConfigServiceImpl.java | 76 + .../GenUpdateColumnConfigServiceImpl.java | 73 + .../gen/impl/GenerateInfoServiceImpl.java | 67 + .../gen/impl/SimpleDBServiceImpl.java | 72 + .../impl/SimpleTableColumnServiceImpl.java | 53 + .../listeners/CreateColumnConfigListener.java | 40 + .../listeners/DetailColumnConfigListener.java | 40 + .../gen/listeners/GenCustomListListener.java | 90 + .../listeners/GenCustomSelectorListener.java | 32 + .../gen/listeners/GenDataObjListener.java | 59 + .../gen/listeners/GenTenantListener.java | 39 + .../gen/listeners/GenerateInfoListener.java | 23 + .../listeners/QueryColumnConfigListener.java | 40 + .../QueryParamsColumnConfigListener.java | 40 + .../listeners/UpdateColumnConfigListener.java | 40 + .../template/gen/mappers/DBMapper.java | 13 + .../mappers/GenCreateColumnConfigMapper.java | 34 + .../mappers/GenCustomListCategoryMapper.java | 32 + .../mappers/GenCustomListDetailMapper.java | 8 + .../GenCustomListHandleColumnMapper.java | 17 + .../gen/mappers/GenCustomListMapper.java | 52 + .../GenCustomListQueryParamsMapper.java | 8 + .../mappers/GenCustomListToolbarMapper.java | 17 + .../mappers/GenCustomPageCategoryMapper.java | 22 + .../gen/mappers/GenCustomPageMapper.java | 35 + .../GenCustomSelectorCategoryMapper.java | 32 + .../gen/mappers/GenCustomSelectorMapper.java | 43 + .../mappers/GenDataEntityCategoryMapper.java | 32 + .../mappers/GenDataEntityDetailMapper.java | 16 + .../gen/mappers/GenDataEntityMapper.java | 35 + .../gen/mappers/GenDataObjCategoryMapper.java | 32 + .../gen/mappers/GenDataObjDetailMapper.java | 24 + .../gen/mappers/GenDataObjMapper.java | 43 + .../mappers/GenDataObjQueryDetailMapper.java | 16 + .../mappers/GenDetailColumnConfigMapper.java | 34 + .../gen/mappers/GenGenerateInfoMapper.java | 24 + .../template/gen/mappers/GenMapper.java | 11 + .../mappers/GenQueryColumnConfigMapper.java | 34 + .../GenQueryParamsColumnConfigMapper.java | 34 + .../mappers/GenSimpleTableColumnMapper.java | 26 + .../gen/mappers/GenSimpleTableMapper.java | 25 + .../mappers/GenUpdateColumnConfigMapper.java | 34 + .../template/gen/mappers/SimpleDBMapper.java | 35 + .../service/GenCreateColumnConfigService.java | 40 + .../service/GenCustomListCategoryService.java | 63 + .../service/GenCustomListDetailService.java | 22 + .../GenCustomListHandleColumnService.java | 24 + .../GenCustomListQueryParamsService.java | 22 + .../gen/service/GenCustomListService.java | 103 + .../service/GenCustomListToolbarService.java | 23 + .../service/GenCustomPageCategoryService.java | 52 + .../gen/service/GenCustomPageService.java | 80 + .../GenCustomSelectorCategoryService.java | 64 + .../gen/service/GenCustomSelectorService.java | 101 + .../service/GenDataEntityCategoryService.java | 63 + .../service/GenDataEntityDetailService.java | 32 + .../gen/service/GenDataEntityService.java | 118 + .../service/GenDataObjCategoryService.java | 63 + .../gen/service/GenDataObjDetailService.java | 31 + .../service/GenDataObjQueryDetailService.java | 23 + .../gen/service/GenDataObjService.java | 98 + .../service/GenDetailColumnConfigService.java | 40 + .../service/GenQueryColumnConfigService.java | 40 + .../GenQueryParamsColumnConfigService.java | 41 + .../service/GenUpdateColumnConfigService.java | 40 + .../gen/service/GenerateInfoService.java | 31 + .../template/gen/service/SimpleDBService.java | 41 + .../gen/service/SimpleTableColumnService.java | 17 + .../xingyun/template/gen/utils/WebUtils.java | 117 + .../vo/custom/list/CreateGenCustomListVo.java | 174 + .../vo/custom/list/GenCustomListDetailVo.java | 67 + .../list/GenCustomListHandleColumnVo.java | 66 + .../list/GenCustomListQueryParamsVo.java | 71 + .../custom/list/GenCustomListSelectorVo.java | 29 + .../custom/list/GenCustomListToolbarVo.java | 57 + .../vo/custom/list/QueryGenCustomListVo.java | 32 + .../vo/custom/list/UpdateGenCustomListVo.java | 187 + .../CreateGenCustomListCategoryVo.java | 29 + .../GenCustomListCategorySelectorVo.java | 23 + .../UpdateGenCustomListCategoryVo.java | 37 + .../vo/custom/page/CreateGenCustomPageVo.java | 46 + .../custom/page/GenCustomPageSelectorVo.java | 29 + .../vo/custom/page/QueryGenCustomPageVo.java | 32 + .../vo/custom/page/UpdateGenCustomPageVo.java | 47 + .../CreateGenCustomPageCategoryVo.java | 35 + .../UpdateGenCustomPageCategoryVo.java | 37 + .../selector/CreateGenCustomSelectorVo.java | 86 + .../selector/GenCustomSelectorSelectorVo.java | 29 + .../selector/QueryGenCustomSelectorVo.java | 32 + .../selector/UpdateGenCustomSelectorVo.java | 90 + .../CreateGenCustomSelectorCategoryVo.java | 29 + .../GenCustomSelectorCategorySelectorVo.java | 23 + .../UpdateGenCustomSelectorCategoryVo.java | 37 + .../vo/data/entity/CreateDataEntityVo.java | 50 + .../entity/GenDataEntityDetailSelectorVo.java | 20 + .../vo/data/entity/GenDataEntityDetailVo.java | 119 + .../data/entity/GenDataEntitySelectorVo.java | 29 + .../gen/vo/data/entity/QueryDataEntityVo.java | 32 + .../entity/UpdateDataEntityGenerateVo.java | 72 + .../vo/data/entity/UpdateDataEntityVo.java | 58 + .../CreateGenDataEntityCategoryVo.java | 29 + .../GenDataEntityCategorySelectorVo.java | 23 + .../UpdateGenDataEntityCategoryVo.java | 37 + .../gen/vo/data/obj/CreateGenDataObjVo.java | 62 + .../gen/vo/data/obj/GenDataObjDetailVo.java | 70 + .../vo/data/obj/GenDataObjQueryDetailVo.java | 53 + .../gen/vo/data/obj/GenDataObjSelectorVo.java | 29 + .../gen/vo/data/obj/QueryGenDataObjVo.java | 32 + .../gen/vo/data/obj/UpdateGenDataObjVo.java | 70 + .../category/CreateGenDataObjCategoryVo.java | 29 + .../GenDataObjCategorySelectorVo.java | 23 + .../category/UpdateGenDataObjCategoryVo.java | 37 + .../vo/gen/UpdateCreateColumnConfigVo.java | 27 + .../vo/gen/UpdateDetailColumnConfigVo.java | 27 + .../gen/vo/gen/UpdateGenerateInfoVo.java | 117 + .../gen/vo/gen/UpdateQueryColumnConfigVo.java | 46 + .../gen/UpdateQueryParamsColumnConfigVo.java | 30 + .../vo/gen/UpdateUpdateColumnConfigVo.java | 27 + .../vo/simpledb/QuerySimpleTableColumnVo.java | 26 + .../vo/simpledb/SimpleTableSelectorVo.java | 17 + .../template/inner/bo/auth/CollectMenuBo.java | 34 + .../inner/bo/auth/ForgetPswUserInfoBo.java | 27 + .../template/inner/bo/auth/LoginBo.java | 62 + .../template/inner/bo/auth/MenuBo.java | 114 + .../inner/bo/auth/TelephoneLoginBo.java | 43 + .../inner/bo/oplog/OpLogInUserCenterBo.java | 53 + .../template/inner/bo/qrtz/GetQrtzBo.java | 100 + .../template/inner/bo/qrtz/QueryQrtzBo.java | 63 + .../inner/bo/system/dept/GetSysDeptBo.java | 61 + .../bo/system/dept/SysDeptSelectorBo.java | 43 + .../inner/bo/system/dept/SysDeptTreeBo.java | 43 + .../inner/bo/system/dic/GetSysDataDicBo.java | 64 + .../bo/system/dic/QuerySysDataDicBo.java | 64 + .../bo/system/dic/SysDataDicSelectorBo.java | 35 + .../dic/category/GetSysDataDicCategoryBo.java | 38 + .../category/QuerySysDataDicCategoryBo.java | 38 + .../SysDataDicCategorySelectorBo.java | 35 + .../system/dic/item/GetSysDataDicItemBo.java | 50 + .../dic/item/QuerySysDataDicItemBo.java | 50 + .../bo/system/dic/item/SysDataDicItemBo.java | 48 + .../inner/bo/system/menu/GetSysMenuBo.java | 192 + .../inner/bo/system/menu/QuerySysMenuBo.java | 93 + .../bo/system/menu/SysMenuSelectorBo.java | 39 + .../bo/system/module/QuerySysModuleBo.java | 45 + .../bo/system/notice/GetSysNoticeBo.java | 57 + .../bo/system/notice/QueryMySysNoticeBo.java | 54 + .../bo/system/notice/QuerySysNoticeBo.java | 89 + .../bo/system/open/GetSysOpenDomainBo.java | 57 + .../bo/system/open/QuerySysOpenDomainBo.java | 57 + .../system/open/SysOpenDomainSelectorBo.java | 35 + .../inner/bo/system/oplog/GetOpLogBo.java | 65 + .../inner/bo/system/oplog/QueryOpLogBo.java | 59 + .../system/parameter/GetSysParameterBo.java | 54 + .../system/parameter/QuerySysParameterBo.java | 73 + .../QuerySysDataPermissionModelDetailBo.java | 94 + .../SysDataPermissionModelDetailBo.java | 61 + .../bo/system/position/GetSysPositionBo.java | 54 + .../system/position/QuerySysPositionBo.java | 82 + .../position/SysPositionSelectorBo.java | 48 + .../inner/bo/system/role/GetSysRoleBo.java | 55 + .../inner/bo/system/role/QueryRoleMenuBo.java | 85 + .../inner/bo/system/role/QuerySysRoleBo.java | 88 + .../bo/system/role/SysRoleSelectorBo.java | 43 + .../inner/bo/system/tenant/GetTenantBo.java | 55 + .../inner/bo/system/tenant/QueryTenantBo.java | 55 + .../bo/system/tenant/TenantSelectorBo.java | 37 + .../inner/bo/system/user/GetSysUserBo.java | 228 + .../inner/bo/system/user/QuerySysUserBo.java | 187 + .../inner/bo/system/user/QueryUserRoleBo.java | 49 + .../bo/system/user/SysUserSelectorBo.java | 43 + .../inner/bo/usercenter/UserInfoBo.java | 61 + .../inner/components/qrtz/DynamicQrtzJob.java | 59 + .../inner/config/OpLogTimerConfiguration.java | 86 + .../inner/controller/AuthController.java | 575 ++ .../inner/controller/QrtzController.java | 170 + .../controller/UserCenterController.java | 192 + .../system/DefaultSysSelectorController.java | 414 + .../controller/system/OpLogController.java | 83 + .../system/SysDataDicCategoryController.java | 122 + .../system/SysDataDicController.java | 127 + .../system/SysDataDicItemController.java | 162 + .../SysDataPermissionDataController.java | 94 + ...ysDataPermissionModelDetailController.java | 153 + .../controller/system/SysDeptController.java | 179 + .../controller/system/SysMenuController.java | 245 + .../system/SysModuleController.java | 101 + .../system/SysNoticeController.java | 175 + .../system/SysOpenDomainController.java | 129 + .../system/SysParameterController.java | 138 + .../system/SysPositionController.java | 154 + .../controller/system/SysRoleController.java | 154 + .../system/SysRoleMenuController.java | 98 + .../controller/system/SysUserController.java | 170 + .../system/SysUserRoleController.java | 91 + .../controller/system/TenantController.java | 143 + .../xingyun/template/inner/dto/LoginDto.java | 53 + .../xingyun/template/inner/dto/MenuDto.java | 82 + .../template/inner/dto/MenuMetaDto.java | 33 + .../template/inner/dto/UserInfoDto.java | 51 + .../inner/dto/message/SysNoticeTaskDto.java | 49 + .../template/inner/dto/qrtz/QrtzDto.java | 78 + .../notice/QuerySysNoticeByUserDto.java | 37 + .../inner/dto/system/notice/SysNoticeDto.java | 34 + .../template/inner/entity/SysDataDic.java | 81 + .../inner/entity/SysDataDicCategory.java | 76 + .../template/inner/entity/SysDataDicItem.java | 86 + .../template/inner/entity/SysDept.java | 100 + .../template/inner/entity/SysMenu.java | 149 + .../template/inner/entity/SysModule.java | 78 + .../inner/entity/SysModuleTenant.java | 42 + .../template/inner/entity/SysNotice.java | 100 + .../template/inner/entity/SysNoticeLog.java | 47 + .../template/inner/entity/SysOpenDomain.java | 95 + .../template/inner/entity/SysParameter.java | 83 + .../template/inner/entity/SysPosition.java | 87 + .../template/inner/entity/SysRole.java | 92 + .../template/inner/entity/SysRoleMenu.java | 38 + .../template/inner/entity/SysUserDept.java | 38 + .../inner/entity/SysUserPosition.java | 36 + .../template/inner/entity/SysUserRole.java | 36 + .../inner/entity/SysUserTelephone.java | 28 + .../xingyun/template/inner/entity/Tenant.java | 71 + .../template/inner/enums/QrtzJobType.java | 33 + .../template/inner/enums/TriggerState.java | 34 + .../inner/enums/system/SysDeptNodeType.java | 23 + .../enums/system/SysMenuComponentType.java | 32 + .../inner/enums/system/SysMenuDisplay.java | 32 + .../template/inner/events/LoginEvent.java | 40 + .../template/inner/events/LogoutEvent.java | 33 + .../inner/events/UpdateUserEvent.java | 27 + .../impl/AbstractUserDetailsService.java | 91 + .../template/inner/impl/QrtzServiceImpl.java | 201 + .../inner/impl/SysModuleServiceImpl.java | 15 + .../impl/SysModuleTenantServiceImpl.java | 70 + .../inner/impl/TenantServiceImpl.java | 108 + .../inner/impl/UserDetailsService.java | 31 + .../system/SysDataDicCategoryServiceImpl.java | 130 + .../system/SysDataDicItemServiceImpl.java | 156 + .../impl/system/SysDataDicServiceImpl.java | 145 + .../SysDataPermissionDataServiceImpl.java | 33 + .../inner/impl/system/SysDeptServiceImpl.java | 284 + .../inner/impl/system/SysMenuServiceImpl.java | 443 + .../impl/system/SysNoticeLogServiceImpl.java | 28 + .../impl/system/SysNoticeServiceImpl.java | 259 + .../impl/system/SysOpenDomainServiceImpl.java | 113 + .../impl/system/SysParameterServiceImpl.java | 197 + .../impl/system/SysPositionServiceImpl.java | 219 + .../impl/system/SysRoleMenuServiceImpl.java | 80 + .../inner/impl/system/SysRoleServiceImpl.java | 299 + .../impl/system/SysUserDeptServiceImpl.java | 83 + .../system/SysUserPositionServiceImpl.java | 61 + .../impl/system/SysUserRoleServiceImpl.java | 79 + .../inner/impl/system/SysUserServiceImpl.java | 468 ++ .../system/SysUserTelephoneServiceImpl.java | 14 + .../inner/listeners/LoginListener.java | 28 + .../inner/listeners/LogoutListener.java | 25 + .../template/inner/mappers/QrtzMapper.java | 30 + .../inner/mappers/SysModuleMapper.java | 8 + .../inner/mappers/SysModuleTenantMapper.java | 8 + .../template/inner/mappers/TenantMapper.java | 33 + .../inner/mappers/UserDetailsMapper.java | 28 + .../system/SysDataDicCategoryMapper.java | 32 + .../mappers/system/SysDataDicItemMapper.java | 30 + .../mappers/system/SysDataDicMapper.java | 38 + .../system/SysDataPermissionDataMapper.java | 9 + .../inner/mappers/system/SysDeptMapper.java | 31 + .../inner/mappers/system/SysMenuMapper.java | 113 + .../mappers/system/SysNoticeLogMapper.java | 15 + .../inner/mappers/system/SysNoticeMapper.java | 44 + .../mappers/system/SysOpenDomainMapper.java | 40 + .../mappers/system/SysParameterMapper.java | 31 + .../mappers/system/SysPositionMapper.java | 52 + .../inner/mappers/system/SysRoleMapper.java | 59 + .../mappers/system/SysRoleMenuMapper.java | 16 + .../mappers/system/SysUserDeptMapper.java | 32 + .../inner/mappers/system/SysUserMapper.java | 99 + .../mappers/system/SysUserPositionMapper.java | 24 + .../mappers/system/SysUserRoleMapper.java | 24 + .../system/SysUserTelephoneMapper.java | 8 + .../template/inner/service/QrtzService.java | 80 + .../inner/service/SysModuleService.java | 7 + .../inner/service/SysModuleTenantService.java | 30 + .../template/inner/service/TenantService.java | 60 + .../system/SysDataDicCategoryService.java | 63 + .../service/system/SysDataDicItemService.java | 81 + .../service/system/SysDataDicService.java | 75 + .../system/SysDataPermissionDataService.java | 26 + .../inner/service/system/SysDeptService.java | 55 + .../inner/service/system/SysMenuService.java | 136 + .../service/system/SysNoticeLogService.java | 20 + .../service/system/SysNoticeService.java | 108 + .../service/system/SysOpenDomainService.java | 58 + .../service/system/SysParameterService.java | 63 + .../service/system/SysPositionService.java | 66 + .../service/system/SysRoleMenuService.java | 15 + .../inner/service/system/SysRoleService.java | 81 + .../service/system/SysUserDeptService.java | 32 + .../system/SysUserPositionService.java | 24 + .../service/system/SysUserRoleService.java | 24 + .../inner/service/system/SysUserService.java | 133 + .../system/SysUserTelephoneService.java | 8 + .../sign/handler/DefaultCheckSignHandler.java | 69 + .../template/inner/sign/util/SignUtil.java | 97 + .../template/inner/vo/qrtz/CreateQrtzVo.java | 91 + .../template/inner/vo/qrtz/QueryQrtzVo.java | 41 + .../template/inner/vo/qrtz/UpdateQrtzVo.java | 31 + .../vo/system/config/UpdateSysConfigVo.java | 96 + .../inner/vo/system/dept/CreateSysDeptVo.java | 48 + .../vo/system/dept/SysUserDeptSettingVo.java | 24 + .../inner/vo/system/dept/UpdateSysDeptVo.java | 63 + .../vo/system/dic/CreateSysDataDicVo.java | 35 + .../vo/system/dic/QuerySysDataDicVo.java | 30 + .../vo/system/dic/SysDataDicSelectorVo.java | 29 + .../vo/system/dic/UpdateSysDataDicVo.java | 43 + .../category/CreateSysDataDicCategoryVo.java | 29 + .../SysDataDicCategorySelectorVo.java | 23 + .../category/UpdateSysDataDicCategoryVo.java | 37 + .../dic/item/CreateSysDataDicItemVo.java | 44 + .../dic/item/QuerySysDataDicItemVo.java | 31 + .../dic/item/UpdateSysDataDicItemVo.java | 44 + .../inner/vo/system/menu/CreateSysMenuVo.java | 113 + .../vo/system/menu/SysMenuSelectorVo.java | 21 + .../inner/vo/system/menu/UpdateSysMenuVo.java | 30 + .../vo/system/module/SysModuleTenantVo.java | 50 + .../vo/system/notice/CreateSysNoticeVo.java | 38 + .../system/notice/QuerySysNoticeByUserVo.java | 48 + .../vo/system/notice/QuerySysNoticeVo.java | 42 + .../vo/system/notice/UpdateSysNoticeVo.java | 52 + .../vo/system/open/CreateSysOpenDomainVo.java | 39 + .../vo/system/open/QuerySysOpenDomainVo.java | 31 + .../system/open/SysOpenDomainSelectorVo.java | 31 + .../open/UpdateSysOpenDomainSecretVo.java | 28 + .../vo/system/open/UpdateSysOpenDomainVo.java | 48 + .../parameter/CreateSysParameterVo.java | 35 + .../system/parameter/QuerySysParameterVo.java | 36 + .../parameter/UpdateSysParameterVo.java | 33 + .../system/position/CreateSysPositionVo.java | 35 + .../system/position/QuerySysPositionVo.java | 31 + .../position/SysPositionSelectorVo.java | 31 + .../position/SysUserPositionSettingVo.java | 24 + .../system/position/UpdateSysPositionVo.java | 50 + .../inner/vo/system/role/CreateSysRoleVo.java | 41 + .../inner/vo/system/role/QuerySysRoleVo.java | 31 + .../vo/system/role/SysRoleMenuSettingVo.java | 24 + .../vo/system/role/SysRoleSelectorVo.java | 31 + .../inner/vo/system/role/UpdateSysRoleVo.java | 56 + .../vo/system/tenant/CreateTenantVo.java | 41 + .../inner/vo/system/tenant/QueryTenantVo.java | 31 + .../vo/system/tenant/TenantSelectorVo.java | 31 + .../vo/system/tenant/UpdateTenantVo.java | 53 + .../inner/vo/system/user/CreateSysUserVo.java | 96 + .../user/GetTelephoneLoginCaptchaVo.java | 23 + .../inner/vo/system/user/LoginVo.java | 42 + .../inner/vo/system/user/QuerySysUserVo.java | 56 + .../inner/vo/system/user/RegistUserVo.java | 51 + .../vo/system/user/SysUserRoleSettingVo.java | 27 + .../vo/system/user/SysUserSelectorVo.java | 37 + .../vo/system/user/TelephoneBindUserVo.java | 43 + .../vo/system/user/TelephoneLoginVo.java | 33 + .../inner/vo/system/user/UpdateSysUserVo.java | 104 + xingyun-template/src/main/java/lombok.config | 2 + .../src/main/resources/mappers/QrtzMapper.xml | 43 + .../resources/mappers/SysParameterMapper.xml | 46 + .../main/resources/mappers/TenantMapper.xml | 43 + .../resources/mappers/UserDetailsMapper.xml | 23 + .../main/resources/mappers/gen/DBMapper.xml | 8 + .../gen/GenCreateColumnConfigMapper.xml | 27 + .../gen/GenCustomListCategoryMapper.xml | 46 + .../gen/GenCustomListHandleColumnMapper.xml | 36 + .../mappers/gen/GenCustomListMapper.xml | 88 + .../gen/GenCustomListToolbarMapper.xml | 34 + .../gen/GenCustomPageCategoryMapper.xml | 15 + .../mappers/gen/GenCustomPageMapper.xml | 46 + .../gen/GenCustomSelectorCategoryMapper.xml | 46 + .../mappers/gen/GenCustomSelectorMapper.xml | 69 + .../gen/GenDataEntityCategoryMapper.xml | 46 + .../mappers/gen/GenDataEntityMapper.xml | 67 + .../mappers/gen/GenDataObjDetailMapper.xml | 11 + .../mappers/gen/GenDataObjMapper.xml | 73 + .../gen/GenDetailColumnConfigMapper.xml | 27 + .../mappers/gen/GenGenerateInfoMapper.xml | 45 + .../main/resources/mappers/gen/GenMapper.xml | 33 + .../gen/GenQueryColumnConfigMapper.xml | 31 + .../gen/GenQueryParamsColumnConfigMapper.xml | 28 + .../gen/GenSimpleTableColumnMapper.xml | 44 + .../mappers/gen/GenSimpleTableMapper.xml | 30 + .../gen/GenUpdateColumnConfigMapper.xml | 27 + .../gen/GenUpdateColumnConfigService.xml | 46 + .../resources/mappers/gen/SimpleDBMapper.xml | 50 + .../system/SysDataDicCategoryMapper.xml | 46 + .../mappers/system/SysDataDicItemMapper.xml | 48 + .../mappers/system/SysDataDicMapper.xml | 63 + .../mappers/system/SysDeptMapper.xml | 19 + .../mappers/system/SysMenuMapper.xml | 181 + .../mappers/system/SysNoticeLogMapper.xml | 22 + .../mappers/system/SysNoticeMapper.xml | 101 + .../mappers/system/SysOpenDomainMapper.xml | 43 + .../mappers/system/SysPositionMapper.xml | 48 + .../mappers/system/SysRoleMapper.xml | 59 + .../mappers/system/SysUserDeptMapper.xml | 22 + .../mappers/system/SysUserMapper.xml | 99 + .../mappers/system/SysUserPositionMapper.xml | 16 + .../mappers/system/SysUserRoleMapper.xml | 15 + .../src/main/resources/templates/add.vue.ftl | 111 + .../src/main/resources/templates/api.ts.ftl | 113 + .../resources/templates/controller.java.ftl | 149 + .../resources/templates/createvo.java.ftl | 51 + .../main/resources/templates/createvo.ts.ftl | 10 + .../main/resources/templates/detail.vue.ftl | 91 + .../main/resources/templates/entity.java.ftl | 49 + .../main/resources/templates/getbo.java.ftl | 97 + .../src/main/resources/templates/getbo.ts.ftl | 29 + .../main/resources/templates/index.vue.ftl | 205 + .../resources/templates/input-components.ftl | 78 + .../main/resources/templates/mapper.java.ftl | 35 + .../resources/templates/mapper.list.xml.ftl | 49 + .../main/resources/templates/modify.vue.ftl | 128 + .../resources/templates/query-type-sql.ftl | 27 + .../main/resources/templates/querybo.java.ftl | 89 + .../main/resources/templates/querybo.ts.ftl | 22 + .../main/resources/templates/queryvo.java.ftl | 57 + .../main/resources/templates/queryvo.ts.ftl | 25 + .../main/resources/templates/service.java.ftl | 79 + .../resources/templates/serviceimpl.java.ftl | 167 + .../src/main/resources/templates/sql.ftl | 9 + .../resources/templates/updatevo.java.ftl | 62 + .../main/resources/templates/updatevo.ts.ftl | 17 + 1870 files changed, 178926 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 cloud/conf/common.yaml create mode 100644 cloud/conf/db.yaml create mode 100644 cloud/conf/mq.yaml create mode 100644 cloud/conf/redis.yaml create mode 100644 cloud/conf/zipkin.yaml create mode 100644 cloud/xingyun-cloud-api/Dockerfile create mode 100644 cloud/xingyun-cloud-api/pom.xml create mode 100644 cloud/xingyun-cloud-api/src/main/java/com/lframework/xingyun/api/XingYunCloudApiApplication.java create mode 100644 cloud/xingyun-cloud-api/src/main/java/lombok.config create mode 100644 cloud/xingyun-cloud-api/src/main/resources/banner.txt create mode 100644 cloud/xingyun-cloud-api/src/main/resources/bootstrap.yml create mode 100644 cloud/xingyun-cloud-api/src/main/resources/magic-editor-config.js create mode 100644 cloud/xingyun-cloud-api/src/main/resources/project.yaml create mode 100644 cloud/xingyun-cloud-api/src/main/resources/scripts/start.sh create mode 100644 cloud/xingyun-cloud-api/src/main/resources/scripts/stop.sh create mode 100644 cloud/xingyun-cloud-gateway/Dockerfile create mode 100644 cloud/xingyun-cloud-gateway/pom.xml create mode 100644 cloud/xingyun-cloud-gateway/src/main/java/com/lframework/xingyun/gateway/GateWayApplication.java create mode 100644 cloud/xingyun-cloud-gateway/src/main/resources/banner.txt create mode 100644 cloud/xingyun-cloud-gateway/src/main/resources/bootstrap.yml create mode 100644 cloud/xingyun-cloud-gateway/src/main/resources/project.yaml create mode 100644 cloud/xingyun-cloud-gateway/src/main/resources/scripts/start.sh create mode 100644 cloud/xingyun-cloud-gateway/src/main/resources/scripts/stop.sh create mode 100644 codestyles/eclipse-java-google-style.xml create mode 100644 codestyles/intellij-java-google-style.xml create mode 100644 pom.xml create mode 100644 screenshots/1.jpg create mode 100644 screenshots/10.jpg create mode 100644 screenshots/11.jpg create mode 100644 screenshots/12.jpg create mode 100644 screenshots/2.jpg create mode 100644 screenshots/3.jpg create mode 100644 screenshots/4.jpg create mode 100644 screenshots/5.jpg create mode 100644 screenshots/6.jpg create mode 100644 screenshots/7.jpg create mode 100644 screenshots/8.jpg create mode 100644 screenshots/9.jpg create mode 100644 xingyun-api/Dockerfile create mode 100644 xingyun-api/pom.xml create mode 100644 xingyun-api/src/main/java/com/lframework/xingyun/api/XingYunApiApplication.java create mode 100644 xingyun-api/src/main/java/lombok.config create mode 100644 xingyun-api/src/main/resources/application-dev.yml create mode 100644 xingyun-api/src/main/resources/application-prod.yml create mode 100644 xingyun-api/src/main/resources/application-test.yml create mode 100644 xingyun-api/src/main/resources/application.yml create mode 100644 xingyun-api/src/main/resources/banner.txt create mode 100644 xingyun-api/src/main/resources/db/SQL文件说明,重要!!!!!!.txt create mode 100644 xingyun-api/src/main/resources/db/all/platform.sql create mode 100644 xingyun-api/src/main/resources/db/all/tenant.sql create mode 100644 xingyun-api/src/main/resources/db/migration/platform/V1.0__init.sql create mode 100644 xingyun-api/src/main/resources/db/migration/platform/V1.1__sys_module.sql create mode 100644 xingyun-api/src/main/resources/db/migration/platform/V1.2__dynamic_api.sql create mode 100644 xingyun-api/src/main/resources/db/migration/platform/V1.3__update_qrtz_details.sql create mode 100644 xingyun-api/src/main/resources/db/migration/platform/V1.4__v3.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.0__init.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.1__paytype.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.2__stock_adjust.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.3__sc_transfer.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.4__bundle_product.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.5__logistics.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.6__custom_page.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.7__upload_to_oss.sql create mode 100644 xingyun-api/src/main/resources/db/migration/tenant/V1.8__v3.sql create mode 100644 xingyun-api/src/main/resources/magic-editor-config.js create mode 100644 xingyun-api/src/main/resources/scripts/start.sh create mode 100644 xingyun-api/src/main/resources/scripts/stop.sh create mode 100644 xingyun-basedata/pom.xml create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/AddressSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/GetAddressBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/QueryAddressBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/CustomerSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/GetCustomerBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/QueryCustomerBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/GetLogisticsCompanyBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/LogisticsCompanySelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/QueryLogisticsCompanyBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/GetMemberBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/MemberSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/QueryMemberBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/GetPayTypeBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/PayTypeSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/QueryPayTypeBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/GetProductBrandBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductBrandSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductCategorySelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/QueryProductBrandBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/GetProductCategoryBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/ProductCategoryTreeBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/GetProductBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductBundleBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/QueryProductBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/GetProductPropertyBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/ProductPropertyModelorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/QueryProductPropertyBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/GetProductPropertyItemBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/QueryProductPropertyItemBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/GetShopBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/QueryShopBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/ShopSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/GetStoreCenterBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/QueryStoreCenterBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/StoreCenterSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/GetSupplierBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/QuerySupplierBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/SupplierSelectorBo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/AddressController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/BaseDataSelectorController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/CustomerController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/LogisticsCompanyController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/MemberController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/PayTypeController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductBrandController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductCategoryController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyItemController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ShopController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/StoreCenterController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/SupplierController.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/ProductPropertyRelationDto.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/property/ProductPropertyModelorDto.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Address.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Customer.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/LogisticsCompany.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Member.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/PayType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Product.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBrand.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBundle.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategory.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategoryProperty.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductProperty.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyItem.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyRelation.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPurchase.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductRetail.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductSale.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Shop.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/StoreCenter.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Supplier.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressEntityType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/BaseDataOpLogType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnDataType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/InvoiceType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ManageType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductCategoryNodeType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/PropertyType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/SettleType.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/TaxRate.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressExportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportListener.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportModel.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/address/AddressServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/customer/CustomerServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/logistics/LogisticsCompanyServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/member/MemberServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/paytype/PayTypeServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBrandServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBundleServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryPropertyServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyItemServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyRelationServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPurchaseServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductRetailServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductSaleServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/shop/ShopServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/storecenter/StoreCenterServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/supplier/SupplierServiceImpl.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/AddressMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/CustomerMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/LogisticsCompanyMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/MemberMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/PayTypeMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBrandMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBundleMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryPropertyMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyItemMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyRelationMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPurchaseMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductRetailMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductSaleMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ShopMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/StoreCenterMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/SupplierMapper.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/address/AddressService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/customer/CustomerService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/logistics/LogisticsCompanyService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/member/MemberService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/paytype/PayTypeService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBrandService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBundleService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryPropertyService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyItemService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyRelationService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPurchaseService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductRetailService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductSaleService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/shop/ShopService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/storecenter/StoreCenterService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/supplier/SupplierService.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/AddressSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/CreateAddressVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/QueryAddressVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/UpdateAddressVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/CreateCustomerVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/UpdateCustomerVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/CreateLogisticsCompanyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanySelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/UpdateLogisticsCompanyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/CreateMemberVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/UpdateMemberVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/CreatePayTypeVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/PayTypeSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/QueryPayTypeVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/UpdatePayTypeVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/CreateProductBrandVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/UpdateProductBrandVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/CreateProductCategoryVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/QueryProductCategorySelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/UpdateProductCategoryVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/CreateProductVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductBundleVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductPropertyRelationVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/UpdateProductVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/saleprop/CreateProductSalePropItemRelationVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/CreateProductPolyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/QueryProductPolyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/UpdateProductPolyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/property/CreateProductPolyPropertyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/saleprop/CreateProductPolySalePropGroupVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/CreateProductPropertyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/QueryProductPropertyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/UpdateProductPropertyVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/CreateProductPropertyItemVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/QueryProductPropertyItemVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/UpdateProductPropertyItemVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/realtion/CreateProductPropertyRelationVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/CreateProductPurchaseVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/UpdateProductPurchaseVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/CreateProductRetailVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/UpdateProductRetailVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/CreateProductSaleVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/UpdateProductSaleVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/CreateProductSalePropGroupVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/UpdateProductSalePropGroupVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/CreateProductSalePropItemVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/UpdateProductSalePropItemVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/CreateShopVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/QueryShopVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/ShopSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/UpdateShopVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/CreateStoreCenterVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/UpdateStoreCenterVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/CreateSupplierVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierSelectorVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierVo.java create mode 100644 xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/UpdateSupplierVo.java create mode 100644 xingyun-basedata/src/main/java/lombok.config create mode 100644 xingyun-basedata/src/main/resources/mappers/address/AddressMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/customer/CustomerMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/logistics/LogisticsCompanyMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/member/MemberMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/paytype/PayTypeMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductBrandMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductCategoryMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductCategoryPropertyMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductPropertyItemMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductPropertyMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductPropertyRelationMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductPurchaseMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductRetailMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/product/ProductSaleMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/shop/ShopMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/storecenter/StoreCenterMapper.xml create mode 100644 xingyun-basedata/src/main/resources/mappers/supplier/SupplierMapper.xml create mode 100644 xingyun-chart/pom.xml create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthBo.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthSumBo.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodayBo.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodaySumBo.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/controller/ChartController.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSameMonthDto.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSumDto.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartTodayDto.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/entity/OrderChart.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/enums/OrderChartBizType.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/impl/OrderChartServiceImpl.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/listeners/OrderDataListener.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/mappers/OrderChartMapper.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/service/OrderChartService.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/CreateOrderChartVo.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/GetOrderChartVo.java create mode 100644 xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/QueryOrderChartVo.java create mode 100644 xingyun-chart/src/main/java/lombok.config create mode 100644 xingyun-chart/src/main/resources/mappers/OrderChartMapper.xml create mode 100644 xingyun-common/pom.xml create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/MapLocationBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/OrderTimeLineBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/dic/CitySelectorBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/GetOnlineExcelBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/QueryOnlineExcelBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/GetFileBoxBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/QueryFileBoxBo.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/controller/SelectorController.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/controller/components/ComponentController.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/FileBoxController.java create mode 100644 xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/OnlineExcelController.java create mode 100644 xingyun-common/src/main/java/lombok.config create mode 100644 xingyun-core/pom.xml create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/annations/OrderTimeLineLog.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/aop/OrderTimeLineLogAspect.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/bo/print/A4ExcelPortraitPrintBo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/dto/dic/city/DicCityDto.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/dto/stock/ProductStockChangeDto.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/entity/DicCity.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/entity/FileBox.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OnlineExcel.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OrderTimeLine.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxFileType.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxNodeType.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/enums/OrderTimeLineBizType.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/enums/SwOpLogType.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/ApprovePassOrderEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseOrderEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseReturnEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailOutSheetEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailReturnEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleOrderEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleReturnEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/AddStockEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/SubStockEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/take/DeleteTakeStockPlanEvent.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/impl/DicCityServiceImpl.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/impl/FileBoxServiceImpl.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OnlineExcelServiceImpl.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OrderTimeLineServiceImpl.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/DicCityMapper.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/FileBoxMapper.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OnlineExcelMapper.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OrderTimeLineMapper.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/service/DicCityService.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/service/FileBoxService.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/service/OnlineExcelService.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/service/OrderTimeLineService.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/utils/SplitNumberUtil.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/BatchSendOnlineExcelVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/CreateOnlineExcelVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/QueryOnlineExcelVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/SendOnlineExcelVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelContentVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/CreateFileBoxDirVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/QueryFileBoxVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UpdateFileBoxVo.java create mode 100644 xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UploadFileBoxVo.java create mode 100644 xingyun-core/src/main/java/lombok.config create mode 100644 xingyun-core/src/main/resources/mappers/DicCityMapper.xml create mode 100644 xingyun-core/src/main/resources/mappers/FileBoxMapper.xml create mode 100644 xingyun-core/src/main/resources/mappers/OnlineExcelMapper.xml create mode 100644 xingyun-sc/pom.xml create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetDeliveryBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBizOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/paytype/OrderPayTypeBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/GetPurchaseOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PrintPurchaseOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderSelectorBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderWithReceiveBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderWithReceiveBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/config/GetPurchaseConfigBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetPaymentDateBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetReceiveSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/PrintReceiveSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetWithReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetSelectorBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetWithReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/GetPurchaseReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/PrintPurchaseReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/QueryPurchaseReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/RetailProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/config/GetRetailConfigBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/GetRetailOutSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/PrintRetailOutSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetWithReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/RetailOutSheetWithReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/GetRetailReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/PrintRetailReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/QueryRetailReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/GetSaleOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/PrintSaleOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderWithOutBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleOrderWithOutBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/config/GetSaleConfigBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/GetSaleOutSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/PrintSaleOutSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetWithReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/SaleOutSheetWithReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/GetSaleReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/PrintSaleReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/QuerySaleReturnBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/QueryStockCostAdjustSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustSheetFullBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/QueryStockAdjustSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustSheetFullBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/GetStockAdjustReasonBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/QueryStockAdjustReasonBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/StockAdjustReasonSelectorBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/QueryProductStockBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/log/QueryProductStockLogBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/config/GetTakeStockConfigBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/GetTakeStockPlanBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanFullBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanSelectorBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/GetPreTakeStockSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockSheetSelectorBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/QueryTakeStockSheetBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetFullBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderDetailReceiveBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferOrderFullBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferProductBo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/components/code/GenerateCodeTypePool.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ScSelectorController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/logistics/LogisticsSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseConfigController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseOrderController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseReturnController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/ReceiveSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailConfigController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailOutSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailReturnController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleConfigController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOrderController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOutSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleReturnController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockLogController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustReasonController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockCostAdjustSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/PreTakeStockSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockConfigController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockPlanController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/transfer/ScTransferOrderController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolPurchaseOrderController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolRetailOutSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolSaleOrderController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolStockAdjustSheetController.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetBizOrderDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderWithReceiveDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/GetPaymentDateDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetWithReturnDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/returned/PurchaseReturnFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/RetailProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetDetailLotDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetWithReturnDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/returned/RetailReturnFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderWithOutDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetDetailLotDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetWithReturnDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/returned/SaleReturnFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustDiffDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/GetTakeStockPlanDetailProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/QueryTakeStockPlanProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/TakeStockPlanFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/QueryPreTakeStockSheetProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferOrderFullDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferProductDto.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/OrderPayType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStock.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStockLog.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseConfig.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrder.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrderDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturn.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturnDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailConfig.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailBundle.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailLot.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturn.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturnDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleConfig.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrder.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetailBundle.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailBundle.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailLot.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturn.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturnDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrder.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetailReceive.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustReason.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockConfig.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlan.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlanDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheet.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheetDetail.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetDetailBizType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/OrderAddressOrderType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PreTakeStockSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ProductStockBizType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseOrderStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseReturnStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ReceiveSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailOutSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailReturnStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOrderStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOutSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleReturnStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScOpLogType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScTransferOrderStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SettleStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetBizType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockCostAdjustSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanType.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockSheetStatus.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportListener.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportListener.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportListener.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportListener.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportListener.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportListener.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/returned/PurchaseReturnExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/out/RetailOutSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/returned/RetailReturnExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/SaleOrderExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/out/SaleOutSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/returned/SaleReturnExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockLogExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockAdjustSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockCostAdjustSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/plan/TakeStockPlanExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/pre/PreTakeStockSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/sheet/TakeStockSheetExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/transfer/ScTransferOrderExportModel.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/filter/RequestLoggingFilter.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/paytype/OrderPayTypeServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseConfigServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailConfigServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailBundleServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailLotServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleConfigServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailBundleServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailBundleServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailLotServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockLogServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustReasonServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockConfigServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailReceiveServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderServiceImpl.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/OrderPayTypeMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockLogMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseConfigMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailConfigMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailBundleMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailLotMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleConfigMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailBundleMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailBundleMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailLotMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailReceiveMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustReasonMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockConfigMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetDetailMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetMapper.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/paytype/OrderPayTypeService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseConfigService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailConfigService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailBundleService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailLotService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleConfigService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailBundleService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailBundleService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailLotService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockLogService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustReasonService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockConfigService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailReceiveService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderService.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/utils/WebUtils.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/address/CreateOrderAddressVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/CreateLogisticsSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/DeliveryLogisticsSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetBizOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetCalcWeightOrVolumeVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetBizOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/UpdateLogisticsSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/paytype/OrderPayTypeVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApprovePassPurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApproveRefusePurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApprovePassPurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApproveRefusePurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/CreatePurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseOrderSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderWithReceiveVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/UpdatePurchaseOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/config/UpdatePurchaseConfigVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApprovePassReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApproveRefuseReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApprovePassReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApproveRefuseReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/CreateReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetWithReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveSheetSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/UpdateReceiveSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApprovePassPurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApproveRefusePurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApprovePassPurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApproveRefusePurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/CreatePurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/QueryPurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ReturnProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/UpdatePurchaseReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/config/UpdateRetailConfigVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApprovePassRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApproveRefuseRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApprovePassRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApproveRefuseRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/CreateRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetWithReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutSheetSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/UpdateRetailOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApprovePassRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApproveRefuseRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApprovePassRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApproveRefuseRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/CreateRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/QueryRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/RetailReturnProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/UpdateRetailReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApprovePassSaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApproveRefuseSaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApprovePassSaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApproveRefuseSaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/CreateSaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderWithOutVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleOrderSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/UpdateSaleOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/config/UpdateSaleConfigVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApprovePassSaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApproveRefuseSaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApprovePassSaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApproveRefuseSaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/CreateSaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetWithReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutSheetSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/UpdateSaleOutSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApprovePassSaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApproveRefuseSaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApprovePassSaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApproveRefuseSaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/CreateSaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/QuerySaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/SaleReturnProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/UpdateSaleReturnVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/AddProductStockVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/QueryProductStockVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/StockCostAdjustVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/SubProductStockVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApprovePassStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApproveRefuseStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApprovePassStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApproveRefuseStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/CreateStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/StockCostAdjustProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/UpdateStockCostAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApprovePassStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApproveRefuseStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApprovePassStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApproveRefuseStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/CreateStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/StockAdjustProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/UpdateStockAdjustSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/CreateStockAdjustReasonVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/QueryStockAdjustReasonVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/StockAdjustReasonSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/UpdateStockAdjustReasonVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithAddStockVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithStockCostAdjustVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithSubStockVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/QueryProductStockLogVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/AddProductLotStockVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/CreateProductLotVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/QueryProductLotVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/config/UpdateTakeStockConfigVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CancelTakeStockPlanVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CreateTakeStockPlanVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/HandleTakeStockPlanVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/QueryTakeStockPlanVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/TakeStockPlanSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/UpdateTakeStockPlanVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/CreatePreTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockSheetSelectorVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/UpdatePreTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApprovePassTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApproveRefuseTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApprovePassTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApproveRefuseTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/CreateTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/TakeStockSheetProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/UpdateTakeStockSheetVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApprovePassScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApproveRefuseScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApprovePassScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApproveRefuseScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/CreateScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderDetailReceiveVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ReceiveScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ScTransferProductVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/UpdateScTransferOrderVo.java create mode 100644 xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/ydool/YdoolApproveOrderVo.java create mode 100644 xingyun-sc/src/main/java/lombok.config create mode 100644 xingyun-sc/src/main/resources/mappers/logistics/LogisticsSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/purchase/PurchaseReturnMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailLotMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/retail/RetailReturnMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/sale/SaleOrderDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/sale/SaleOrderMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailLotMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/sale/SaleReturnMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/ProductStockLogMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/ProductStockMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustReasonMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/adjust/StockCostAdjustSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/take/PreTaskStockSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/take/TakeStockConfigMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/take/TakeStockSheetMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderDetailMapper.xml create mode 100644 xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderMapper.xml create mode 100644 xingyun-sc/src/main/resources/print/purchase-order.ftl create mode 100644 xingyun-sc/src/main/resources/print/purchase-return.ftl create mode 100644 xingyun-sc/src/main/resources/print/receive-sheet.ftl create mode 100644 xingyun-sc/src/main/resources/print/retail-out-sheet.ftl create mode 100644 xingyun-sc/src/main/resources/print/retail-return.ftl create mode 100644 xingyun-sc/src/main/resources/print/sale-order.ftl create mode 100644 xingyun-sc/src/main/resources/print/sale-out-sheet.ftl create mode 100644 xingyun-sc/src/main/resources/print/sale-return.ftl create mode 100644 xingyun-settle/pom.xml create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/GetSettleCheckSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/QuerySettleCheckSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/SettleCheckBizItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/CustomerSettleCheckBizItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/GetCustomerSettleCheckSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/QueryCustomerSettleCheckSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/GetSettleFeeSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/QuerySettleFeeSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/GetCustomerSettleFeeSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/QueryCustomerSettleFeeSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/GetSettleInItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/QuerySettleInItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/SettleInItemSelectorBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/GetSettleOutItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/QuerySettleOutItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/SettleOutItemSelectorBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/GetSettlePreSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/QuerySettlePreSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/GetCustomerSettlePreSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/QueryCustomerSettlePreSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/GetSettleSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/QuerySettleSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/SettleBizItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/CustomerSettleBizItemBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/GetCustomerSettleSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/QueryCustomerSettleSheetBo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/components/code/GenerateCodeTypePool.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleCheckSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleFeeSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettlePreSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleCheckSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleFeeSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleInItemController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleOutItemController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettlePreSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSelectorController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSheetController.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckBizItemDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckBizItemDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/SettleFeeSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/customer/CustomerSettleFeeSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/SettlePreSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/customer/CustomerSettlePreSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleBizItemDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleBizItemDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleSheetFullDto.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleInItem.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleOutItem.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheet.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheetDetail.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetBizType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetCalcType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettlePreSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetBizType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetCalcType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleOpLogType.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettlePreSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleSheetStatus.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/SettleCheckSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/customer/CustomerSettleCheckSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/SettleFeeSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/customer/CustomerSettleFeeSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/in/SettleInItemExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/out/SettleOutItemExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/SettlePreSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/customer/CustomerSettlePreSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/SettleSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/customer/CustomerSettleSheetExportModel.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleInItemServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleOutItemServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetDetailServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetServiceImpl.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleInItemMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleOutItemMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetDetailMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetMapper.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleInItemService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleOutItemService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetDetailService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetService.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApprovePassSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApproveRefuseSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApprovePassSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApproveRefuseSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/CreateSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QuerySettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QueryUnCheckBizItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/SettleCheckSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/UpdateSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApprovePassCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApproveRefuseCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApprovePassCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApproveRefuseCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CreateCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CustomerSettleCheckSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerUnCheckBizItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/UpdateCustomerSettleCheckSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApprovePassSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApproveRefuseSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApprovePassSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApproveRefuseSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/CreateSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/QuerySettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/SettleFeeSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/UpdateSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApprovePassCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApproveRefuseCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApprovePassCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApproveRefuseCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CreateCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CustomerSettleFeeSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/QueryCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/UpdateCustomerSettleFeeSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/CreateSettleInItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/QuerySettleInItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/SettleInItemSelectorVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/UpdateSettleInItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/CreateSettleOutItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/QuerySettleOutItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/SettleOutItemSelectorVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/UpdateSettleOutItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApprovePassSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApproveRefuseSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApprovePassSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApproveRefuseSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/CreateSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/QuerySettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/SettlePreSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/UpdateSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApprovePassCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApproveRefuseCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApprovePassCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApproveRefuseCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CreateCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CustomerSettlePreSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/QueryCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/UpdateCustomerSettlePreSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApprovePassSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApproveRefuseSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApprovePassSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApproveRefuseSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/CreateSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QuerySettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QueryUnSettleBizItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/SettleSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/UpdateSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApprovePassCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApproveRefuseCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApprovePassCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApproveRefuseCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CreateCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CustomerSettleSheetItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerUnSettleBizItemVo.java create mode 100644 xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/UpdateCustomerSettleSheetVo.java create mode 100644 xingyun-settle/src/main/java/lombok.config create mode 100644 xingyun-settle/src/main/resources/mappers/CustomerSettleCheckSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/CustomerSettleFeeSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/CustomerSettlePreSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/CustomerSettleSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/SettleCheckSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/SettleFeeSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/SettleInItemMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/SettleOutItemMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/SettlePreSheetMapper.xml create mode 100644 xingyun-settle/src/main/resources/mappers/SettleSheetMapper.xml create mode 100644 xingyun-template-core/pom.xml create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/OpLog.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermission.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermissions.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sort.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sorts.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/aop/OpLogAspector.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/WebExceptionHandler.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/DataPermissionHandlerImpl.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/SysDataPermissionDataPermissionType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzHandler.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzJob.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/config/MpInterceptorConfiguration.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/DeptDto.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/UserDto.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/OpLogs.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/RecursionMapping.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionData.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionModelDetail.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysUser.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Available.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/DefaultOpLogType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Gender.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/NodeType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionDataBizType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailCalcType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailConditionType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailInputType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailNodeType.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/DeptServiceImpl.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/OpLogsServiceImpl.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/RecursionMappingServiceImpl.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/SysDataPermissionModelDetailServiceImpl.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/UserServiceImpl.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/interceptors/CustomSortInterceptor.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/DeptMapper.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/OpLogsMapper.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/RecursionMappingMapper.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/SysDataPermissionModelDetailMapper.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/UserMapper.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/DeptService.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/OpLogsService.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/RecursionMappingService.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/SysDataPermissionModelDetailService.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/UserService.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/OpLogUtil.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/WebUtils.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/CreateOpLogsVo.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/QueryOpLogsVo.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/CreateSysDataPermissionDataVo.java create mode 100644 xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/SysDataPermissionModelDetailVo.java create mode 100644 xingyun-template-core/src/main/java/lombok.config create mode 100644 xingyun-template-core/src/main/resources/mappers/DeptMapper.xml create mode 100644 xingyun-template-core/src/main/resources/mappers/OpLogsMapper.xml create mode 100644 xingyun-template-core/src/main/resources/mappers/RecursionMappingMappre.xml create mode 100644 xingyun-template-core/src/main/resources/mappers/UserMapper.xml create mode 100644 xingyun-template/pom.xml create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/config/TemplateApiConfiguration.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GenCustomListSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GetGenCustomListBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/QueryGenCustomListBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GenCustomListCategorySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GetGenCustomListCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/QueryGenCustomListCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GenCustomPageSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GetGenCustomPageBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/QueryGenCustomPageBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GenCustomPageCategorySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GetGenCustomPageCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/QueryGenCustomPageCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GenCustomSelectorSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GetGenCustomSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/QueryGenCustomSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GenCustomSelectorCategorySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GetGenCustomSelectorCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/QueryGenCustomSelectorCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/DataEntityGenerateBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailGenerateBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntitySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GetDataEntityBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/QueryDataEntityBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GenDataEntityCategorySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GetGenDataEntityCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/QueryGenDataEntityCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjColumnBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjDetailBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjQueryDetailBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GetGenDataObjBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/QueryGenDataObjBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GenDataObjCategorySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GetGenDataObjCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/QueryGenDataObjCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenCreateColumnConfigBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenDetailColumnConfigBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenGenerateInfoBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryColumnConfigBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryParamsColumnConfigBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenUpdateColumnConfigBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/simpledb/SimpleDBSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomListBuilder.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomPageBuilder.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomSelectorBuilder.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataEntityBuilder.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataObjectBuilder.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/CreateColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntity.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntityColumn.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DetailColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryParamsColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/Table.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/TableColumn.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/UpdateColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/list/CustomListConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/page/CustomPageConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/selector/CustomSelectorConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryObj.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryParamObj.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomAuthorizationInterceptor.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomJsonValueProvider.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomMagicFunction.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomSqlCache.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/config/MagicCustomConfiguration.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/constants/GenStringPool.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListCategoryController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageCategoryController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorCategoryController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityCategoryController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjCategoryController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenSelectorController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenMysqlDataTypeConverter.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenStringConverter.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenViewTypeConverter.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/directives/FormatDirective.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/DataEntityGenerateDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/GenDataEntityDetailDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenCreateColumnConfigDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenDetailColumnConfigDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenGenerateInfoDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryColumnConfigDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryParamsColumnConfigDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenUpdateColumnConfigDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/generate/GenerateDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableColumnDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleDBDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleTableDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCreateColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomList.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListCategory.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListDetail.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListHandleColumn.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListQueryParams.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListToolbar.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPage.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPageCategory.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelector.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelectorCategory.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntity.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityCategory.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityDetail.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObj.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjCategory.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjDetail.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjQueryDetail.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDetailColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenGenerateInfo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryParamsColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTable.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTableColumn.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenUpdateColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateColumnConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateConfig.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenConvertType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnViewType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListDetailType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenDataType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenKeyType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenMySqlDataType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenOrderType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryWidthType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaMode.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenStatus.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenTemplateType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenViewType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/CustomListDeleteEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDeleteEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDetailDeleteEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjDeleteEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjQueryDetailDeleteEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/Generator.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ControllerTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/CreateTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/DetailTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/EntityTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/MapperTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryParamsTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ServiceTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/SqlTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/UpdateTemplate.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCreateColumnConfigServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListCategoryServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListDetailServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListHandleColumnServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListQueryParamsServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListToolbarServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageCategoryServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorCategoryServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityCategoryServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityDetailServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjCategoryServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjDetailServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjQueryDetailServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDetailColumnConfigServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryColumnConfigServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryParamsColumnConfigServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenUpdateColumnConfigServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenerateInfoServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleDBServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleTableColumnServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/CreateColumnConfigListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/DetailColumnConfigListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomListListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomSelectorListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenDataObjListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenTenantListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenerateInfoListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryColumnConfigListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryParamsColumnConfigListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/UpdateColumnConfigListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/DBMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCreateColumnConfigMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListCategoryMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListDetailMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListHandleColumnMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListQueryParamsMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListToolbarMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageCategoryMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorCategoryMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityCategoryMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityDetailMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjCategoryMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjDetailMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjQueryDetailMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDetailColumnConfigMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenGenerateInfoMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryColumnConfigMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryParamsColumnConfigMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableColumnMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenUpdateColumnConfigMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/SimpleDBMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCreateColumnConfigService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListCategoryService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListDetailService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListHandleColumnService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListQueryParamsService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListToolbarService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageCategoryService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorCategoryService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityCategoryService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityDetailService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjCategoryService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjDetailService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjQueryDetailService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDetailColumnConfigService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryColumnConfigService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryParamsColumnConfigService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenUpdateColumnConfigService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenerateInfoService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleDBService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleTableColumnService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/utils/WebUtils.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/CreateGenCustomListVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListDetailVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListHandleColumnVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListQueryParamsVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListToolbarVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/QueryGenCustomListVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/UpdateGenCustomListVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/CreateGenCustomListCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/GenCustomListCategorySelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/UpdateGenCustomListCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/CreateGenCustomPageVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/GenCustomPageSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/QueryGenCustomPageVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/UpdateGenCustomPageVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/CreateGenCustomPageCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/UpdateGenCustomPageCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/CreateGenCustomSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/GenCustomSelectorSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/QueryGenCustomSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/UpdateGenCustomSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/CreateGenCustomSelectorCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/GenCustomSelectorCategorySelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/UpdateGenCustomSelectorCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/CreateDataEntityVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntitySelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/QueryDataEntityVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityGenerateVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/CreateGenDataEntityCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/GenDataEntityCategorySelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/UpdateGenDataEntityCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/CreateGenDataObjVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjDetailVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjQueryDetailVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/QueryGenDataObjVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/UpdateGenDataObjVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/CreateGenDataObjCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/GenDataObjCategorySelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/UpdateGenDataObjCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateCreateColumnConfigVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateDetailColumnConfigVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateGenerateInfoVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryColumnConfigVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryParamsColumnConfigVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateUpdateColumnConfigVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/QuerySimpleTableColumnVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/SimpleTableSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/CollectMenuBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/ForgetPswUserInfoBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/LoginBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/MenuBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/TelephoneLoginBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/oplog/OpLogInUserCenterBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/GetQrtzBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/QueryQrtzBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/GetSysDeptBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptTreeBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/GetSysDataDicBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/QuerySysDataDicBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/SysDataDicSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/GetSysDataDicItemBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/QuerySysDataDicItemBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/SysDataDicItemBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/GetSysMenuBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/QuerySysMenuBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/SysMenuSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/module/QuerySysModuleBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/GetSysNoticeBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QueryMySysNoticeBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QuerySysNoticeBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/GetSysOpenDomainBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/QuerySysOpenDomainBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/SysOpenDomainSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/GetOpLogBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/QueryOpLogBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/GetSysParameterBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/QuerySysParameterBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/SysDataPermissionModelDetailBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/GetSysPositionBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/QuerySysPositionBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/SysPositionSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/GetSysRoleBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QueryRoleMenuBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QuerySysRoleBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/SysRoleSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/GetTenantBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/QueryTenantBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/TenantSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/GetSysUserBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QuerySysUserBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QueryUserRoleBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/SysUserSelectorBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/usercenter/UserInfoBo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/components/qrtz/DynamicQrtzJob.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/config/OpLogTimerConfiguration.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/AuthController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/QrtzController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/UserCenterController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/DefaultSysSelectorController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/OpLogController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicCategoryController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicItemController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionDataController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionModelDetailController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDeptController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysMenuController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysModuleController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysNoticeController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysOpenDomainController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysParameterController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysPositionController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleMenuController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserRoleController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/TenantController.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/LoginDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuMetaDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/UserInfoDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/message/SysNoticeTaskDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/qrtz/QrtzDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/QuerySysNoticeByUserDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/SysNoticeDto.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDic.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicCategory.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicItem.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDept.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysMenu.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModule.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModuleTenant.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNotice.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNoticeLog.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysOpenDomain.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysParameter.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysPosition.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRole.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRoleMenu.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserDept.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserPosition.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserRole.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserTelephone.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/Tenant.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/QrtzJobType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/TriggerState.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysDeptNodeType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuComponentType.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuDisplay.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LoginEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LogoutEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/UpdateUserEvent.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/AbstractUserDetailsService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/QrtzServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleTenantServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/TenantServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/UserDetailsService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicCategoryServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicItemServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataPermissionDataServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDeptServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysMenuServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeLogServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysOpenDomainServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysParameterServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysPositionServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleMenuServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserDeptServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserPositionServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserRoleServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserTelephoneServiceImpl.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LoginListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LogoutListener.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/QrtzMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleTenantMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/TenantMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/UserDetailsMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicCategoryMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicItemMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataPermissionDataMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDeptMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysMenuMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeLogMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysOpenDomainMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysParameterMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysPositionMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMenuMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserDeptMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserPositionMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserRoleMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserTelephoneMapper.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/QrtzService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleTenantService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/TenantService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicCategoryService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicItemService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataPermissionDataService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDeptService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysMenuService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeLogService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysOpenDomainService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysParameterService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysPositionService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleMenuService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserDeptService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserPositionService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserRoleService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserTelephoneService.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/handler/DefaultCheckSignHandler.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/util/SignUtil.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/CreateQrtzVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/QueryQrtzVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/UpdateQrtzVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/config/UpdateSysConfigVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/CreateSysDeptVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/SysUserDeptSettingVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/UpdateSysDeptVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/CreateSysDataDicVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/QuerySysDataDicVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/SysDataDicSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/UpdateSysDataDicVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/CreateSysDataDicItemVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/QuerySysDataDicItemVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/CreateSysMenuVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/SysMenuSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/UpdateSysMenuVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/module/SysModuleTenantVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/CreateSysNoticeVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeByUserVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/UpdateSysNoticeVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/CreateSysOpenDomainVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/QuerySysOpenDomainVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/SysOpenDomainSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/CreateSysParameterVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/QuerySysParameterVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/UpdateSysParameterVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/CreateSysPositionVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/QuerySysPositionVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysPositionSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysUserPositionSettingVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/UpdateSysPositionVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/CreateSysRoleVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/QuerySysRoleVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleMenuSettingVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/UpdateSysRoleVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/CreateTenantVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/QueryTenantVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/TenantSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/UpdateTenantVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/CreateSysUserVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/LoginVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/QuerySysUserVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/RegistUserVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserRoleSettingVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserSelectorVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneBindUserVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneLoginVo.java create mode 100644 xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/UpdateSysUserVo.java create mode 100644 xingyun-template/src/main/java/lombok.config create mode 100644 xingyun-template/src/main/resources/mappers/QrtzMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/SysParameterMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/TenantMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/UserDetailsMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/DBMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCreateColumnConfigMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomListCategoryMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomListHandleColumnMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomListMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomListToolbarMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomPageCategoryMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomPageMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorCategoryMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenDataEntityCategoryMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenDataEntityMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenDataObjDetailMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenDataObjMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenDetailColumnConfigMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenGenerateInfoMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenQueryColumnConfigMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenQueryParamsColumnConfigMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenSimpleTableColumnMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenSimpleTableMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigService.xml create mode 100644 xingyun-template/src/main/resources/mappers/gen/SimpleDBMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysDataDicItemMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysDataDicMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysDeptMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysMenuMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysNoticeLogMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysNoticeMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysOpenDomainMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysPositionMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysRoleMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysUserDeptMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysUserMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysUserPositionMapper.xml create mode 100644 xingyun-template/src/main/resources/mappers/system/SysUserRoleMapper.xml create mode 100644 xingyun-template/src/main/resources/templates/add.vue.ftl create mode 100644 xingyun-template/src/main/resources/templates/api.ts.ftl create mode 100644 xingyun-template/src/main/resources/templates/controller.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/createvo.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/createvo.ts.ftl create mode 100644 xingyun-template/src/main/resources/templates/detail.vue.ftl create mode 100644 xingyun-template/src/main/resources/templates/entity.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/getbo.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/getbo.ts.ftl create mode 100644 xingyun-template/src/main/resources/templates/index.vue.ftl create mode 100644 xingyun-template/src/main/resources/templates/input-components.ftl create mode 100644 xingyun-template/src/main/resources/templates/mapper.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/mapper.list.xml.ftl create mode 100644 xingyun-template/src/main/resources/templates/modify.vue.ftl create mode 100644 xingyun-template/src/main/resources/templates/query-type-sql.ftl create mode 100644 xingyun-template/src/main/resources/templates/querybo.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/querybo.ts.ftl create mode 100644 xingyun-template/src/main/resources/templates/queryvo.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/queryvo.ts.ftl create mode 100644 xingyun-template/src/main/resources/templates/service.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/serviceimpl.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/sql.ftl create mode 100644 xingyun-template/src/main/resources/templates/updatevo.java.ftl create mode 100644 xingyun-template/src/main/resources/templates/updatevo.ts.ftl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7bb241e --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ + +logs +*.log diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/cloud/conf/common.yaml b/cloud/conf/common.yaml new file mode 100644 index 0000000..1a10bf7 --- /dev/null +++ b/cloud/conf/common.yaml @@ -0,0 +1,157 @@ +spring: + servlet: + multipart: + #是否开启文件上传 + enabled: true + #临时文件路径 + location: D:\tmp\tmp-datas + #单个文件最大值 + max-file-size: 10MB + #请求中所有文件的最大值 + max-request-size: 100MB + #将文件写入磁盘的阈值 + #file-size-threshold: 0 + #是否要延迟解析文件 + #resolve-lazily: false + quartz: + jdbc: + initialize-schema: never + job-store-type: jdbc + wait-for-jobs-to-complete-on-shutdown: true + properties: + # ID设置为自动获取 每一个必须不同 + "org.quartz.scheduler.instanceId": AUTO + # 开启集群 + "org.quartz.jobStore.isClustered": true + #时间格式 + jackson: + date-format: yyyy-MM-dd HH:mm:ss + default-property-inclusion: non_null + #使用redis存储SESSION + session: + store-type: redis + +knife4j: + enable: true + setting: + language: zh-CN + # 是否显示界面中SwaggerModel功能 + enableSwaggerModels: false + # 是否显示界面中"文档管理"功能 + enableDocumentManage: true + # 是否默认显示底部Footer + enableFooter: false + # 是否自定义Footer + enableFooterCustom: true + # 自定义Footer内容(支持Markdown语法) + footerCustomContent: Apache License 2.0 | Copyright 2019-[星云ERP](https://gitee.com/lframework/xingyun) + # 是否开启调试 + enableDebug: true + # 是否显示OpenAPI原始结构的Tab框,默认显示 + enableOpenApi: false + # 是否生产环境 + production: false + +# Sa-Token配置 +sa-token: + # token名称 (同时也是cookie名称),此值不要修改 + token-name: X-Auth-Token + # token有效期,单位s 默认30天, -1代表永不过期 + timeout: 25920000 + # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 + activity-timeout: 7200 + # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) + is-share: false + # token风格 + token-style: uuid + # 是否输出操作日志 + is-log: false + +jugg: + secret: + # 秘钥,用于敏感信息加密,生产环境一定要更改此项,并且产生数据后不要更改秘钥 + # 提供了EncryptUtil工具类,包含:生成秘钥、加密、解密方法。 + key: eRE2drUFINojkG9ivqtfOA== + upload: + #下载时的baseUrl,与domain的区别:会在url后面拼接/**作为静态资源的url,而domain是后端系统的具体域名,下载时的完整url例如:upload.domain + upload.url/xxx.jpg + url: /oss + #下载时的域名 + domain: http://localhost:8080 + #上传文件的路径 + location: D:\upload\upload-data + #默认配置 + default-setting: + #默认单号生成类型 FLOW:流水号 SNOW_FLAKE:雪花算法,如果不配置,默认是SNOW_FLAKE + generator-type: SNOW_FLAKE + #默认的用户ID,用于写入数据库时的createById和updateById的自动赋值,如果有登录人则取登录人ID,如果没有则取默认用户ID,如果不配置,默认是1 + default-user-id: 1 + #默认的用户姓名,用于写入数据库时的createBy和updateBy的自动赋值,如果有登录人则取登录人姓名,如果没有则取默认用户姓名,如果不配置,默认是系统管理员 + default-user-name: 系统管理员 + #缓存TTL配置 单位:秒 + cache: + #公共缓存过期时间 + ttl: 1800 + #特殊指定缓存过期时间,以下示例为cacheName的过期时间是3600秒、cacheName2的过期是7200秒。cacheName、cacheName2对应的是@Cacheable的Value属性 + #regions: + # cacheName: 3600 + # cacheName2: 7200 + #验证码配置 + kaptcha: + #过期时间(单位:分钟) + expire-time: 5 + session-config-key: KAPTCHA_SESSION_KEY + session-config-date: KAPTCHA_SESSION_DATE + border: true + border-color: black + border-thickness: 1 + noise-color: black + noise-impl: com.google.code.kaptcha.impl.DefaultNoise + obscurificator-impl: com.google.code.kaptcha.impl.WaterRipple + producer-impl: com.google.code.kaptcha.impl.DefaultKaptcha + text-producer-impl: com.google.code.kaptcha.text.impl.DefaultTextCreator + text-producer-char-string: abcde2345678gfynmnpwx + text-producer-char-length: 4 + text-producer-font-names: Arial,Courier + text-producer-font-color: black + text-producer-font-size: 28 + text-producer-char-space: 2 + word-render-impl: com.google.code.kaptcha.text.impl.DefaultWordRenderer + back-ground-impl: com.google.code.kaptcha.impl.DefaultBackground + back-ground-clr-from: lightGray + back-ground-clr-to: white + image-width: 120 + image-height: 40 + +#PageHelper分页器 +pagehelper: + offset-as-page-num: true + row-bounds-with-count: true + page-size-zero: true + reasonable: false + params: pageNum=pageIndex;pageSize=pageSize; + support-methods-arguments: false +mybatis-plus: + mapper-locations: classpath*:/mappers/**/*.xml + typeEnumsPackage: com.lframework.xingyun.**.enums + +op-logs: + #是否开启 + enabled: true + #操作日志保留天数 + retain-days: 7 + +# 是否移除内置权限,针对admin等内置权限,因为内置权限等同于通配符权限,设置为true时会用具体的权限将内置权限替换掉,生产环境建议设置为true +remove-fixed-permissions: false + +feign: + # feign使用HttpClient + httpclient: + enabled: true + client: + config: + default: + connect-timeout: 500 + read-time-out: 60000 + diff --git a/cloud/conf/db.yaml b/cloud/conf/db.yaml new file mode 100644 index 0000000..4fcb4b6 --- /dev/null +++ b/cloud/conf/db.yaml @@ -0,0 +1,27 @@ +spring: + datasource: + dynamic: + # 设置默认数据源 + primary: master + # 是否严格匹配数据源 未匹配到指定数据源时true抛异常,false使用默认数据源 + strict: true + datasource: + master: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/xingyun?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 + username: root + password: password + druid: + initial-size: 10 + min-idle: 10 + max-active: 200 + max-wait: 60000 + time-between-eviction-runs-millis: 300000 + validation-query: SELECT 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + filters: stat \ No newline at end of file diff --git a/cloud/conf/mq.yaml b/cloud/conf/mq.yaml new file mode 100644 index 0000000..403de83 --- /dev/null +++ b/cloud/conf/mq.yaml @@ -0,0 +1,11 @@ +spring: + activemq: + broker-url: tcp://127.0.0.1:61616 + user: user + password: password + pool: + enabled: true + max-connections: 5 + in-memory: false + packages: + trust-all: true \ No newline at end of file diff --git a/cloud/conf/redis.yaml b/cloud/conf/redis.yaml new file mode 100644 index 0000000..ae4c6ef --- /dev/null +++ b/cloud/conf/redis.yaml @@ -0,0 +1,37 @@ +spring: + #redis配置,这个redis用来缓存业务数据 + redis: + #地址 + host: 127.0.0.1 + #端口,默认为6379 + port: 6379 + #数据库 + database: 0 + #密码 + password: password + #连接超时时间 + timeout: 10s + lettuce: + pool: + #连接池中的最小空闲连接 + min-idle: 0 + #连接池中的最大空闲连接 + max-idle: 8 + #连接池的最大数据库连接数 + max-active: 8 + #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + +sa-token: + # 配置 Sa-Token 单独使用的 Redis 连接,将业务和鉴权独立 + alone-redis: + # Redis数据库索引(默认为0),最好与业务数据的redis隔离 + database: 1 + # Redis服务器地址 + host: ${spring.redis.host} + # Redis服务器连接端口 + port: ${spring.redis.port} + # Redis服务器连接密码(默认为空) + password: ${spring.redis.password} + # 连接超时时间 + timeout: ${spring.redis.timeout} \ No newline at end of file diff --git a/cloud/conf/zipkin.yaml b/cloud/conf/zipkin.yaml new file mode 100644 index 0000000..36532f5 --- /dev/null +++ b/cloud/conf/zipkin.yaml @@ -0,0 +1,9 @@ +spring: + zipkin: + # zipkin-server地址 + base-url: http://127.0.0.1:9411 + discovery-client-enabled: false + sleuth: + sampler: + # 每秒跟踪请求的最大数量 可设置0-2147483647 + rate: 2147483647 \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/Dockerfile b/cloud/xingyun-cloud-api/Dockerfile new file mode 100644 index 0000000..f0b9761 --- /dev/null +++ b/cloud/xingyun-cloud-api/Dockerfile @@ -0,0 +1,12 @@ +FROM openjdk:8-jre-slim + +WORKDIR /opt + +ARG JAR_FILE=@build.finalName@.jar +COPY ${JAR_FILE} /opt/app.jar + +EXPOSE 15020 + +ENV JAVA_OPTS="-Dspring.profiles.active=prod" + +CMD ["sh", "-c", "java $JAVA_OPTS -jar -server app.jar"] diff --git a/cloud/xingyun-cloud-api/pom.xml b/cloud/xingyun-cloud-api/pom.xml new file mode 100644 index 0000000..80b9e24 --- /dev/null +++ b/cloud/xingyun-cloud-api/pom.xml @@ -0,0 +1,114 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + xingyun-cloud-api + 【${project.artifactId}】SpringCloud架构的Api接口层 + + + + com.lframework + xingyun-common + + + com.lframework + xingyun-basedata + + + + com.lframework + xingyun-sc + + + + com.lframework + xingyun-settle + + + + com.lframework + xingyun-chart + + + + com.lframework + xingyun-template + + + + com.lframework + cloud-starter + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + + copy-resources-to-target + package + + copy-resources + + + ${project.build.directory} + + + ${project.basedir} + true + + Dockerfile + + + + ${project.basedir}/src/main/resources + true + + scripts/* + + + + + + + + + + + src/main/resources + true + + bootstrap.yml + + + + src/main/resources + false + + ** + + + scripts/* + project.yaml + + + + + diff --git a/cloud/xingyun-cloud-api/src/main/java/com/lframework/xingyun/api/XingYunCloudApiApplication.java b/cloud/xingyun-cloud-api/src/main/java/com/lframework/xingyun/api/XingYunCloudApiApplication.java new file mode 100644 index 0000000..74d9b95 --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/java/com/lframework/xingyun/api/XingYunCloudApiApplication.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.api; + +import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver; +import com.lframework.starter.web.annotations.locker.EnableLock; +import com.lframework.starter.web.annotations.locker.LockType; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +@EnableLock(type = LockType.REDIS) +@EnableDiscoveryClient +@EnableFeignClients(basePackages = "com.lframework.xingyun") +@ServletComponentScan(basePackages = "com.lframework.xingyun") +@SpringBootApplication(scanBasePackages = "com.lframework.xingyun") +@MapperScan("com.lframework.xingyun.**.mappers") +public class XingYunCloudApiApplication { + + public static void main(String[] args) { + + SpringApplication.run(XingYunCloudApiApplication.class, args); + } + + /** + * Swagger 自定义配置信息 请自行修改 + */ + @Configuration + public static class SwaggerApiConfiguration { + + @Bean(value = "defaultApi") + public Docket defaultApi(OpenApiExtensionResolver openApiExtensionResolver) { + + Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName("星云ERP") + .select() + .apis(RequestHandlerSelectors.basePackage("com.lframework.xingyun.api") + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.basedata")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.chart")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.core")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.sc")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.settle"))) + .paths(PathSelectors.any()) + .build().extensions(openApiExtensionResolver.buildSettingExtensions()); + return docket; + } + + // 可以修改内容 但是不要删除这个Bean + @Bean + public ApiInfo apiInfo() { + + return new ApiInfoBuilder().title("星云ERP接口文档").description("# 星云ERP接口文档") + .contact("lframework@163.com") + .build(); + } + } +} diff --git a/cloud/xingyun-cloud-api/src/main/java/lombok.config b/cloud/xingyun-cloud-api/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/src/main/resources/banner.txt b/cloud/xingyun-cloud-api/src/main/resources/banner.txt new file mode 100644 index 0000000..15182bc --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + ▄ ▄ ▀ + █ █ ▄▄▄ ▄ ▄▄ ▄▄▄▄ ▄ ▄ ▄ ▄ ▄ ▄▄ + ██ █ █▀ █ █▀ ▀█ ▀▄ ▄▀ █ █ █▀ █ + ▄▀▀▄ █ █ █ █ █ █▄█ █ █ █ █ + ▄▀ ▀▄ ▄▄█▄▄ █ █ ▀█▄▀█ ▀█ ▀▄▄▀█ █ █ + ▄ █ ▄▀ + ▀▀ ▀▀ \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/src/main/resources/bootstrap.yml b/cloud/xingyun-cloud-api/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..5cd7c40 --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/resources/bootstrap.yml @@ -0,0 +1,36 @@ +server: + #端口 + port: 15020 + +spring: + application: + name: @project.artifactId@ + profiles: + active: @profiles-active@ + cloud: + nacos: + config: + server-addr: ${nacos-server-addr} + file-extension: yaml + namespace: ${spring.profiles.active} + extension-configs[0]: + data-id: common.yaml + refresh: true + extension-configs[1]: + data-id: db.yaml + refresh: true + extension-configs[2]: + data-id: redis.yaml + refresh: true + extension-configs[3]: + data-id: zipkin.yaml + refresh: true + #extension-configs[4]: + # data-id: mq.yaml + # refresh: true + discovery: + server-addr: ${nacos-server-addr} + namespace: ${spring.profiles.active} + +# nacos-server地址 +nacos-server-addr: @discovery-server@ \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/src/main/resources/magic-editor-config.js b/cloud/xingyun-cloud-api/src/main/resources/magic-editor-config.js new file mode 100644 index 0000000..f582920 --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/resources/magic-editor-config.js @@ -0,0 +1,21 @@ +var MAGIC_EDITOR_CONFIG = { + title: '在线开发平台', + header: { + skin: false, // 屏蔽皮肤按钮 + document: false, // 屏蔽文档按钮 + repo: false, // 屏蔽gitee和github + qqGroup: false // 屏蔽加入QQ群 + }, + getMagicTokenValue: function(){ + return this.getCookie('X-Auth-Token'); + }, + getCookie: function(name) { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i].trim().split('='); + if (cookie[0] === name) { + return decodeURIComponent(cookie[1]); + } + } + } +} \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/src/main/resources/project.yaml b/cloud/xingyun-cloud-api/src/main/resources/project.yaml new file mode 100644 index 0000000..57616c2 --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/resources/project.yaml @@ -0,0 +1,71 @@ +logging: + pattern: + console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint}|%clr(%5p)|%clr(${PID:- }){magenta}|%clr(%15.15t){faint}|%clr(${spring.application.name}){cyan}|%clr(%X{X-B3-TraceId:-N/A}){blue}|%X{X-B3-SpanId:-N/A}|%clr(%-40.40logger{39}){cyan}|%m%n%wEx" + file: ${logging.pattern.console} + file: + name: logs/${spring.application.name}.log + max-history: 14 + +jugg: + web: + #不需要认证的Url + filter-url: ${magic-api.push_path} + #终端ID + worker-id: 1 + #数据中心ID + center-id: 1 + #开启多租户 + tenant: + enabled: true + #开启websocket + ws: + enabled: true + #通信topic + #topic: xingyun:ws:topic + #是否支持跨域 + #support-cross-domain: false +magic-api: + # 编辑器配置项 + editor-config: classpath:magic-editor-config.js + # 这里改为项目运行时的域名,菜单中嵌入的页面为base-url + web,这里示例即为http://localhost:8080/dynamic/web + base-url: http://localhost:15000 + # 编辑器页面的访问路径url + web: /dynamic/web + resource: + type: database + tableName: magic_api_file + prefix: /magic-api + readonly: false + # 接口前缀 + prefix: /dynamic-api + # 禁止覆盖应用接口 + allow-override: true + # 是否支持跨域 + support-cross-domain: true + # 推送路径 + push_path: /_magic-api-sync + # 推送秘钥,自行修改 + secret-key: 123456789 + throw-exception: true + response: |- #配置JSON格式,格式为magic-script中的表达式 + { + code: code, + msg: message, + data, + timestamp, + requestTime, + executeTime, + } + response-code: + success: 200 + invalid: 400 + exception: 500 + page: + size: pageSize # 页大小的参数名称 + page: pageIndex # 页码的参数名称 + default-page: 1 # 未传页码时的默认首页 + default-size: 20 # 未传页大小时的默认页大小 + backup: + enable: true + max-history: 14 #备份保留天数,-1为永久保留 + table-name: magic_api_file_backup \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/src/main/resources/scripts/start.sh b/cloud/xingyun-cloud-api/src/main/resources/scripts/start.sh new file mode 100644 index 0000000..b38807f --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/resources/scripts/start.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +export BUILD_ID=dontkillme +if [ -z $JAVA_HOME ] ; +then +echo "JAVA_HOME is not exist, please check" +exit 1 +fi +export APP_HOME_BIN_PATH=$(cd `dirname $0`; pwd) +export APP_HOME=${APP_HOME_BIN_PATH%/bin} + +$JAVA_HOME/bin/java -jar -server -Xmx256m -XX:MaxPermSize=32m -XX:MaxNewSize=32m $APP_HOME/@build.finalName@.jar >/dev/null 2>&1 & \ No newline at end of file diff --git a/cloud/xingyun-cloud-api/src/main/resources/scripts/stop.sh b/cloud/xingyun-cloud-api/src/main/resources/scripts/stop.sh new file mode 100644 index 0000000..260e4e2 --- /dev/null +++ b/cloud/xingyun-cloud-api/src/main/resources/scripts/stop.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +export APP_HOME_BIN_PATH=$(cd `dirname $0`; pwd) +export APP_HOME=${APP_HOME_BIN_PATH%/bin} + +export C_PID=`ps -ef | grep java | grep $APP_HOME | grep -v grep | awk '{print $2}'` + +if [ ! -z "$C_PID" ]; then + kill -15 $C_PID; +fi \ No newline at end of file diff --git a/cloud/xingyun-cloud-gateway/Dockerfile b/cloud/xingyun-cloud-gateway/Dockerfile new file mode 100644 index 0000000..56ea9fc --- /dev/null +++ b/cloud/xingyun-cloud-gateway/Dockerfile @@ -0,0 +1,12 @@ +FROM openjdk:8-jre-slim + +WORKDIR /opt + +ARG JAR_FILE=@build.finalName@.jar +COPY ${JAR_FILE} /opt/app.jar + +EXPOSE 15000 + +ENV JAVA_OPTS="-Dspring.profiles.active=prod" + +CMD ["sh", "-c", "java $JAVA_OPTS -jar -server app.jar"] diff --git a/cloud/xingyun-cloud-gateway/pom.xml b/cloud/xingyun-cloud-gateway/pom.xml new file mode 100644 index 0000000..3ea3954 --- /dev/null +++ b/cloud/xingyun-cloud-gateway/pom.xml @@ -0,0 +1,110 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + xingyun-cloud-gateway + + 【${project.artifactId}】GateWay网关 + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + spring-cloud-starter-alibaba-nacos-config + com.alibaba.cloud + + + + nacos-client + com.alibaba.nacos + + + + spring-cloud-starter-zipkin + org.springframework.cloud + + + + + true + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + + copy-resources-to-target + package + + copy-resources + + + ${project.build.directory} + + + ${project.basedir} + true + + Dockerfile + + + + ${project.basedir}/src/main/resources + true + + scripts/* + + + + + + + + + + + src/main/resources + true + + bootstrap.yml + + + + src/main/resources + false + + ** + + + scripts/* + project.yaml + + + + + \ No newline at end of file diff --git a/cloud/xingyun-cloud-gateway/src/main/java/com/lframework/xingyun/gateway/GateWayApplication.java b/cloud/xingyun-cloud-gateway/src/main/java/com/lframework/xingyun/gateway/GateWayApplication.java new file mode 100644 index 0000000..ca7ffa2 --- /dev/null +++ b/cloud/xingyun-cloud-gateway/src/main/java/com/lframework/xingyun/gateway/GateWayApplication.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@EnableDiscoveryClient +@SpringBootApplication +public class GateWayApplication { + + public static void main(String[] args) { + SpringApplication.run(GateWayApplication.class, args); + } +} diff --git a/cloud/xingyun-cloud-gateway/src/main/resources/banner.txt b/cloud/xingyun-cloud-gateway/src/main/resources/banner.txt new file mode 100644 index 0000000..15182bc --- /dev/null +++ b/cloud/xingyun-cloud-gateway/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + ▄ ▄ ▀ + █ █ ▄▄▄ ▄ ▄▄ ▄▄▄▄ ▄ ▄ ▄ ▄ ▄ ▄▄ + ██ █ █▀ █ █▀ ▀█ ▀▄ ▄▀ █ █ █▀ █ + ▄▀▀▄ █ █ █ █ █ █▄█ █ █ █ █ + ▄▀ ▀▄ ▄▄█▄▄ █ █ ▀█▄▀█ ▀█ ▀▄▄▀█ █ █ + ▄ █ ▄▀ + ▀▀ ▀▀ \ No newline at end of file diff --git a/cloud/xingyun-cloud-gateway/src/main/resources/bootstrap.yml b/cloud/xingyun-cloud-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..697abc8 --- /dev/null +++ b/cloud/xingyun-cloud-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,24 @@ +server: + #端口 + port: 15000 + +spring: + application: + name: @project.artifactId@ + profiles: + active: @profiles-active@ + cloud: + nacos: + config: + server-addr: ${nacos-server-addr} + file-extension: yaml + namespace: ${spring.profiles.active} + extension-configs[0]: + data-id: zipkin.yaml + refresh: true + discovery: + server-addr: ${nacos-server-addr} + namespace: ${spring.profiles.active} + +# nacos-server地址 +nacos-server-addr: @discovery-server@ \ No newline at end of file diff --git a/cloud/xingyun-cloud-gateway/src/main/resources/project.yaml b/cloud/xingyun-cloud-gateway/src/main/resources/project.yaml new file mode 100644 index 0000000..1bb61f7 --- /dev/null +++ b/cloud/xingyun-cloud-gateway/src/main/resources/project.yaml @@ -0,0 +1,29 @@ +logging: + pattern: + console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint}|%clr(%5p)|%clr(${PID:- }){magenta}|%clr(%15.15t){faint}|%clr(${spring.application.name}){cyan}|%clr(%X{X-B3-TraceId:-N/A}){blue}|%X{X-B3-SpanId:-N/A}|%clr(%-40.40logger{39}){cyan}|%m%n%wEx" + file: ${logging.pattern.console} + file: + name: logs/${spring.application.name}.log + max-history: 14 + +spring: + cloud: + gateway: + discovery: + locator: + enabled: true + routes: + - id: xingyun-cloud-api + uri: lb://xingyun-cloud-api + predicates: + - Path=/cloud-api/** + filters: + - StripPrefix=1 + - id: xingyun-dynamic-api + uri: lb://xingyun-cloud-api + predicates: + - Path=/dynamic/web/**,/dynamic-api/** + - id: xingyun-oss + uri: lb://xingyun-cloud-api + predicates: + - Path=/oss/** \ No newline at end of file diff --git a/cloud/xingyun-cloud-gateway/src/main/resources/scripts/start.sh b/cloud/xingyun-cloud-gateway/src/main/resources/scripts/start.sh new file mode 100644 index 0000000..b38807f --- /dev/null +++ b/cloud/xingyun-cloud-gateway/src/main/resources/scripts/start.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +export BUILD_ID=dontkillme +if [ -z $JAVA_HOME ] ; +then +echo "JAVA_HOME is not exist, please check" +exit 1 +fi +export APP_HOME_BIN_PATH=$(cd `dirname $0`; pwd) +export APP_HOME=${APP_HOME_BIN_PATH%/bin} + +$JAVA_HOME/bin/java -jar -server -Xmx256m -XX:MaxPermSize=32m -XX:MaxNewSize=32m $APP_HOME/@build.finalName@.jar >/dev/null 2>&1 & \ No newline at end of file diff --git a/cloud/xingyun-cloud-gateway/src/main/resources/scripts/stop.sh b/cloud/xingyun-cloud-gateway/src/main/resources/scripts/stop.sh new file mode 100644 index 0000000..260e4e2 --- /dev/null +++ b/cloud/xingyun-cloud-gateway/src/main/resources/scripts/stop.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +export APP_HOME_BIN_PATH=$(cd `dirname $0`; pwd) +export APP_HOME=${APP_HOME_BIN_PATH%/bin} + +export C_PID=`ps -ef | grep java | grep $APP_HOME | grep -v grep | awk '{print $2}'` + +if [ ! -z "$C_PID" ]; then + kill -15 $C_PID; +fi \ No newline at end of file diff --git a/codestyles/eclipse-java-google-style.xml b/codestyles/eclipse-java-google-style.xml new file mode 100644 index 0000000..7bb6804 --- /dev/null +++ b/codestyles/eclipse-java-google-style.xml @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/codestyles/intellij-java-google-style.xml b/codestyles/intellij-java-google-style.xml new file mode 100644 index 0000000..f3a6743 --- /dev/null +++ b/codestyles/intellij-java-google-style.xml @@ -0,0 +1,598 @@ + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0bab112 --- /dev/null +++ b/pom.xml @@ -0,0 +1,156 @@ + + + + org.springframework.boot + spring-boot-starter-parent + 2.2.2.RELEASE + + + + com.lframework + xingyun + 【${project.artifactId}】星云ERP + 1.0.0-SNAPSHOT + + 4.0.0 + pom + + + xingyun-core + xingyun-api + xingyun-basedata + xingyun-sc + xingyun-chart + xingyun-settle + xingyun-template + xingyun-template-core + cloud/xingyun-cloud-api + xingyun-common + cloud/xingyun-cloud-gateway + + + + 8 + 8 + 1.0.0-SNAPSHOT + 3.1.3 + + + + + + com.lframework + parent + ${jugg.version} + pom + import + + + com.lframework + xingyun-basedata + ${xingyun.version} + + + + com.lframework + xingyun-common + ${xingyun.version} + + + com.lframework + xingyun-sc + ${xingyun.version} + + + + com.lframework + xingyun-chart + ${xingyun.version} + + + + com.lframework + xingyun-template + ${xingyun.version} + + + + com.lframework + xingyun-template-core + ${xingyun.version} + + + + com.lframework + xingyun-settle + ${xingyun.version} + + + + com.lframework + xingyun-core + ${xingyun.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + + ali-public + 阿里云public库 + https://maven.aliyun.com/repository/public + default + + + + ali-central + 阿里云central库 + https://maven.aliyun.com/repository/central + + + + ali-central-old + 阿里云central库old + https://maven.aliyun.com/nexus/content/groups/public + + + + + + dev + + true + + + dev + 127.0.0.1:10000 + + + + test + + test + 127.0.0.1:10000 + + + + prod + + prod + 127.0.0.1:10000 + + + + diff --git a/screenshots/1.jpg b/screenshots/1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a31e9a5e5974efa513bbd30d5d8d191ad9f2f891 GIT binary patch literal 128648 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 B*^vMM literal 0 HcmV?d00001 diff --git a/screenshots/10.jpg b/screenshots/10.jpg new file mode 100644 index 0000000000000000000000000000000000000000..196eaf475d5080109524a084fded97322ac8b8e4 GIT binary patch literal 181302 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

i_yKo_5gp2-2K;S$`KvC)7Joh{tc18p5` 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 Q{`p^Y4FI+*<@bsI1B*6gKmY&$ literal 0 HcmV?d00001 diff --git a/screenshots/11.jpg b/screenshots/11.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bd4b7edd0e0040f87c27cc85c1c0b7138b2e5b7d GIT binary patch literal 133135 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 DuntxG literal 0 HcmV?d00001 diff --git a/screenshots/12.jpg b/screenshots/12.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b377a9d22b3044358bb8e41c28b37bd0a1cf5083 GIT binary patch literal 148287 zcmeEv1y~%*mj7VELm)s19w31rL4w;r2n-TDxFxu|ONN9X!6iU~yGxM4-6gmNcMa|~ z{F~hS-o4NE-QBml-|l}i`6|_PSD&t`t~zzqDBIRfnA!Xy0-7oF$nJw-6wwdh?ed#Jv#>{7dH>D z$a7IKh`5BL;!7oE6;(BLJ$(a1BV!X&J9`I5CubK|ulL?QzJ4G4!y`UMMn!-69Fvlo zmY$KBm7P;uQVJ_8uc)kQYHn$5Ywzgn8XOuP866w{HZi}jxU{^oy0*Ttw|{VWbbNAp zc7D??1Q60M%>w@arD1>7E?l5ph{(uD$f!5%LO^r^5)v*l$^+J0c*63iuWjy9vAspZ ze-@Tp)QC>~RAHAu*LDDdkcNH!;oeQtezfe5HSFDgsAYd{*l+Ec0AV2^051;-7X$|F zb9A{%&^q|gTxm6O4U7t2vaPxXeX+X+t&QiGySjW13|JBe})0>CV#plME?zTCT6J-Mkjuz z)%N`kn(Z0EtT#PVkP>&@__U`ujRl$a8Hl*`JRvOzDT(QQGZSL4l%lMk_Z|t@(@=ag0 z5fH4|o+?6~FMQi~eREXbmNmUbED)a;jn_1PM<0GvdAzArA$hk|!Qpkv0sM1!aQYE% z&c_L>?sEu%D8n5s|AG;k(5L;b3d)a!Me*fWQvB&a|4J$pKIORvQAdtld8J*028vV? zRgx}AuR&p5oAAa#=%0uEz%hljvfsMe=#Na3af9$j|K0TAP0EM5-Hv@N@crU4ORm~n zGY&^sGxL)13JLCFN^y!|j8vLZ(RZqLj(WL24Bo{bgf{i{gIA-HuR)#}o_vz@wcg*= zgWlf@Ma6ybc9?gITQC)-`YYu>J>h5mOHco2_QNwFO1xXn@my(`;I$8Gt#GD^ zL&j{|3v5h3iCVa&M{yM@$7CS>uQMtb40 zb~+*-vWeN1$rEPBR@}`W@{6jeWLN9TixRAmJ>zL&B@-%4wt92_lv%p8$Z7Yu+3+te?s^jEVkXXA?{~Jgq@m(-qG6$FaDwJbnZ0_SOW}C|W~qTA zxAi#{0TIU85A{CmdL;Vnz&=pz$s}_G`Mocey2Ha9_O_|q z{CG>N{gS#K6})CK41RPCT2u;~*TFo!r`Z3XYK&ib^xpPY@+r2UB+}cd6)RO+T=Nuf zkK9ONx4^AjDuiX<4lxNrG2sBY*Q^dZlRz*(cg)ymh>vQ(Ck z(bt^(pW$F@LMYP3!m*J`a103xpVBcmirDQEIjm)KA&w8u{FJ4&lb^lk7a@$vCZ>Yzts&t;@Db_tVt!$S1?CI1|DdDSx%s`*f1su3N>! zE7Ca6`pw;4!_~@ZfRAkK2`vA@CXRxmRfm|Kg5vSa8<~|M82M)>x8ug#DL?A+umH=0 zSYsuMu0;0O;(PQ`id-#%BqQ!j+3{c%7>jgJm+(|Lb58j)aHN4s<)s7YRIyps9rZXn z)VDn|ioZ9`V=Hn#(mI;m@g^s%@^L(jk8AwX!OeL+0sf%Vk3QRj-md+n!FH zk9v=kIz@#~N>_JBVsMVqTYI1_sXUwqqkz5ng`td3(e2OXmEISf4SR(X=~4Jy(IIHG zMR&D8o9^e6lIlO>0T$f%qt_t#`&ujbr9X-4-nb#=d@NNZH`t6cq&N1eWO4SKkg561Ws(rir3{~A&3 ze}&k*sBIzJI?;0#pME)E8S?sZd6b#nhk}O`&bQ#8S~l>NR;2Z@>pN#Ioe?Gni~jZU z6DAi6*OzCn6QhGd^b!(EK{4?OxpUQ4TV`Ym7xG`;hrlLuq*f@HllApFsE5)W2P7ka z6=^axOoYMJtD_LSR~Td;n~$;hV#o?_!7P+IN_DtOqfH!T>g`a%3~btDp!xP^6N1tJ z8gvXs%ghHKK?s*wh&}l7LMS&$am0a+-GhEru9Dkl8ne7U=~9-!w$jQkai4l7M9rcd z4hi;r3jN|Pv7l3AdNPq>qWBE%k)Gz*BufjPedx0QL57~^8Z}q7UXDe(a>7VWvL{fW zY)|kO9<6Qg*|I?L?a@!}t!q|-+*O|OtraF-Tz*6t`IGdZj2ZyT7_isvkJId((S%&o z*v@)hiRYgm)PHy~Yd$n|ifjoPqpI4)PgTJs>efpnkZ+0zpITyi9lWuW-@2fYjS^Vw zW1i@)zcf0(+Zw2hJ2Pdr2SLs>H)qm}27iAi3|4O+OpaMpDhr-|;8MP=lt^-$=d5HB zu@-N>p!JJ^G}Wd;u)xe4CF(Nyqldu))~Nf1(0l6kD<2Ka&fjETgS2oMa3r4w*y<#n z#R(RrkFSTe6U(}u1o^a#!qxG4mJsa{67$VY?`pb9KQ{?4;yj@_a{=4zO>Tzt5va8A z3Y#g7ysnWNBa#}7aH*!a_y%&%93r(*b+s#XO^?l-xtmOJ(x0;&OpUcj3q7FyJeU`w z3<%d#IT`5=Hb$>$j>}}-*cR`I&8tp-jKeaIu+OYLv`c2{Odil@Qr z4rUgaCd6Jcn*9BJ#*Gu?wjBt^{EGxVr&WAtmlk%|V}3*$)AO)9LWtZdD7wh{;U2g6 z?kYbDKAu${V}3A-$NZ$#lIT%FfkOX&7@Z@CtfGT@FX{G<^qxahYUYeitj4B>hU)vC zhhI^U{e^jCcRXfhQb#MRDg0tmEBsfRi%UzWH7B>ibg@wlAND@I25sghkoG%p*W87^ zzMT|4sXY-jq%I^se?U!(6X?l>+tAB%u7Z-S(W;lLWpc0FIxniIouszs@HE1ffkiIs zjb?%`Sr$@>?*h~2Oi_qP%tqVFTytj6{ckIa1yVMBmXW#n&P~@K(V?wE!`DWv1jp5O;;$+?hO*dscImM*Qe>@j3Sqgg67apo;T(^= z7cE3yj@ajF3Buqk(5D{+8m9}RV|Mst^_r4>~b)3ziU6L(E=1t+qfz?T2Ifw z%8qF_`j%VBW0hBmW2gm-XUd$Ji#m5qcBiR+GZH@s1|rL?-nDeC=E;f7JDviy(k?sA@%F-w69UZ(Je|hq0u-bn?G%Zl zRm|jOUgCp-otO*T-wBBLbDY2h3`0T26&H{y{z}C-qwk6X*C3s@jn2*L@Uc-fD)WiS z%do}M5XXWy{tUfwacN6^GPv^o{=m|dmRfYGle~U@5^V8cxFFSMW{M<{Y4VnBoHuF) z*zW@AhC$j$&w^HsSZ2NB zE#Y;h$%$)Ox>e?QlVMe5Cad#AL$`e0GXM?CUH*c}-mMlmF$UT_sdPVH&?e5C_wUBLWR zeCx0;vyJTlV^ABBr-pb$+RD8AM ziYR8?UeU0r*%wg5e;wv1`JyY*e~ z1#i2HSnPH;ZOxC>YrK1aM?%?J=0aP*XGE}6m3|VkUE1vjQ{x!>!tgoD9?ERY)2(lh zjHIp%z0VKKB9ydyoVrBRs{JIdWJZX{u5y@U7j^<*9`rlX)fJ^?W?3=!pG|@!zce=X zktzi0SKU^S&0d=ztn`@g`?f%)C~YrQVOJE-h48t9-ve7~mm<&#PVEd)9oUB96m1rz zB3G1?tBub(vc+eT(cJb?1!L7HfeNQxz6JgV&av zUl!x*>giT0yEi*wWMUieB`<;DKK^tu1Sj2gq;i^}W2eZaCvFVXA}w`vBkmeG@et)W zi6@*XloMghCok>Zo+Y}rr}z&rn2T=X%Zsx7Q=#yX!Ygr~M+-X6D|QFyU9VjvwVvEcmsbB!Y&CX{*urNBv$) zIkm&oenJT7lNbv zeEKc~>CEI;jjAl|{O%3PTlfg8>af*d``r4Hfb^;Z>RZ!Whr8X>t0*Li5u~IEtm@}b z-x{F=>ax+oBQptoRqPtSs7br~5ByLCY*9JJeigiLgl}7I@ZijWc}<8h#xCwzVb ziiLDGrXeo$N*LtTcng-SHjtI`#K*xTC)CfM zY?olzCT#o~bRKX?mR^^>fJR}m&*T>+c0ytQhW7AQ+K@YL?kw-;#S2n_8EuVS?fL|U zLG~c3A<<&OvJY?LsuOEghsOk&?@0#nD5h=CPSqE*Rk#aCmMCWBMK9>&h2RQSl%d5S zD{nc_yd{>HM8v0D-kT-0IVT=Vsk1-E;i@0tFxDF?MYFKl>6#Vw5X@vxO6K1tjVllU zXXj^^k||2=v8xA%E^KsdFV!yR53P1GHAbk-Y;ZF0!)l9})2M^`RPVoS&lpG7W_6%9qLkv2kpxr>h z2O3N8!Q!a4wn-WPkq0i3E#U=hbC0>_-lXQg-f-otftp*3 zQ=C+yu4~7Of?PD#6CV5TH%7>gCJ8%G#PsFGMt(~W7IJkPGg^?vtpA|RoiSo*@f{Jq zKS7`~!@`4VgGv!;&n}1h$xQo>LAVAVGfM2CKQ&oh@}somPV=&byl)*&mURgqofVs- zCq&_~j58Rj+sPKirr-%Q@ecaFFRXApXM*)ZIaDO)^G)ZJ^9%9aqy8G>pidRm2^{5U zBveB6E>%clyD1cy&Jkk$*un7*dX6RSw3Dyn)m{_}IuTeqFM{+PI}6VJLCw3N31FN? z3!4n-OcJZ9yr+`Ic=sqc=NrkO^bEHCpi@VGy29s+e`3cJ_=Q;6j4za*zv^nvqAD;W zt{tt+;@Fx*dLWl{+aEPuE+u|CkAYzdnA0MEy60cc|8-XXk66sl^Z%R;|9ABfFw#PL zbwnU>bw0JX^=-a|%gdj2uNfai_YZu1_ci>_7lZW)^*_FRV|z}_zkJAUM_EFXl6q5U zl{q=}Gs@?O1QY;;5FQU~(hkN>x~xl}kPAR(Mc7b66mnDO<{@mDY?Aa~pb$AghbL6+ zfBVC{*35Qf4FREcX)s%{}K&?93>?&KAsdqD#a>X*o`z?*qWcg-RrQFbUKRXrNj zsncJ7Gi9a63774F2I&x|abJT}n3uq972k%nQ?jl>rXtrM{^d*G(}AmOoXdmgeTqeK z%wZ*pEpg~-Tz%*@h!_lea1BbZg^OGoBOVbzE)*!vR&OYT{8j{1D=H5k_JzB2pW*DK z{<(xFv;0fwZ+HK>MAFX({HYUvcG1sK^mC$t+kVc2pY!17Joq^eeo7U;@qzzwf>(;C zASD2&%Uk)Ew|f5wL3xPd)hx(T4WKaHZcv!HeVhGtfK`9d39#y~-XPXqcI&2A9x}zL z39G#4e@RHaM396^@U}>&Gqp39`#6<+7(wIa(1hr9gzUabKis|mh2l}jqe2&kH7GBC z{*ioj?tr+;Rdcrw%rh1s-y&e^Xr~ zKA?8_6hBD(pce2p9;n`E$PW@8H`GKMdV%_xL4J@ByrGsdXXFA@F!cusiXYUhpVs_) zE3^YN^v7Mrie|X$VglK3e{}Be`uXSKFXQcJKm6>6-}9gUN#h|UZ*c-p@BtvIf{3{P zDlHE~e;xKUsAKuhj9MjOEZLpp23ouWZ|u8KR%A!DLhRNiDJmF*?DH;u$*^zGSBR>0 ztBbN3q9%}$Qz zob~xwRr#~^93tif*$%UPNUbQx62fMG{`k^#ga>Bt=Rg@B%f6O$$Ca2K6NBC-H&JGNJz~o_ zd?nic858N@CPoTe80Jkb38wGFW|LM*?zYuYgq5YA8MawdMu5+;x%+b&_FJo6kaL>& zI!O+dk(`HwMH$Czv&bZ1(Ev&^->tgCJkOx!a}k!fR){;o(DNoH7SyO<7xMcb zSs5yxfcmuUWbS;NPI;#wuVM%zz)qjKHySprAx`5XTuJ0az#%2g$C~M2510cVcmswN z0ve!8XVoouWsic6GKTH|9o_I>HEjQH(v77y5BlVY+>ex%cVVVes*yG*D|oWB<&GeG z!5=kt=Tm}_7!9{x1;VB}H^apF=j>`)3(Qh^QA1;QuqeKYL@)5BK=|@9tl~u<)VXlW zA@tTzVvxlTP}<8ND_)KCW)Z4JY61z2&^(A7j))NMfC8*^(=?h1>)rHtO4rLRMqW=> z!;~I?NSK)MpTUi>s}-V34Xpeb!l=$eIwHn?TS438YZ@yp(b2l1}XPE z9c$@&<>yUU0r-q<_h{DaiPlCgmGxw7?6X^x)^I*qn-wDyePuFnK5-hYULPSoS`*Mm z-PM-(08DkqmbIN7VRS>W?sMAIl$vVnhXFgX8mXXdaimQ1u!wbSrxcU(f@;$VgJGJ7 zGpURdwG#=XVlUC&o`93i$DnDOVWvakVc$#%S6GN*bCvx_6IzZqV&_86P&dHG_?6e7 z{w$=xfzm6I?N}i!W@K8@t z{umO1U1DrFo2y=}{;A%Jk?rqR2E}{$qb%`aYiJ6ik3oWF`pX{^%%s|LOBx3Ao6jb- z5vU0$1j%fzxmWw;P^9TC^dyHCi@pq%@)<|avTYcO849QYSZG;SD<7&6b^+sYDYCo? ziwpiN_WeGxxKEv^UnY(5tK@0iL>xA7FM#~yofkLkV zv_zLs((M`Gy&wx zC{{*U5|9YiYaht6YX6MZ`WW+7E(4|u(HXO+k_$iHE#Wr$?-M0iwH7!BrOZIBDWQokm_C#yA9vvK^ zpLt$olegf&^5jW)DIP2s4}Ksw%x_}(!5GX0V5q!0g*& zMxxP~=l=wW-~8coXru;j!rbjfX?e)IioSK6LH>E2a{bqFDUUv03)3`_KsI80fA>LWHmBS~ki_n7_P!@=97@^D-<=D45N; zlg8Sk);TqMT60~{U8U|(dCc>`?NUOzyff`v5Si4NA!%8OL4L0EaWiUii!_6jaH_dE ztR=nCxIvkx@2zr8$2Lc_m`eBY9aaM4OQp8YYQK`nj7fzk4l3Z_YD(iqdUaSeyI{V3 zhqLQySQSJ#DI0v0Fw}C7*XuoH>%)^cP{*nzRL6DcNIbeGLUnQytfwO1#XG`v3X z7Nq^N;BS!$TCqyF(as%9`iFVdEzxR&j0#;n+vbN^N`~>abx@4^ij_oU(DQE-@gu2j zYBWcaGSg&VS1k<8W|cA%&&Z(f8Rxx3{8#v7i);ID?|r!M!_)S3C>TmSn+LwVDWc95 zf-D)uQq^wRXcJb7$GX+Nsu8)U>r$Inc_Ki}U)N*%-R?lAbH4lYn^~F?lOeqRF54ZF zqy0Wx9B#0;)}U^!73YbZlbR8al*KIL<8i%Y%OyBjPVTx@fmZjE+`CNScu~hKivoc` zUSkCUDC&dC=i}W5&guq!@Rg;-lMmxu7b2OpuS`t_MDY<6ep$Ey!28WI&I%xvUm*S) z{ysmi{iXlYKkbifQ!XZ}I~Ykj9XwkqX3T0AVII;ZqO|OvBMpa1M2#JIlD(-^7axe- zvP)c5fSSt!2EK(WXj}HA?6J$}3(Gd=9?`hCh#sd4I<6dUkJ3S9BPol=3DY!`h|M$@ z^a5ZwzwWubw*5%jpa2nHE2ldkfGMv$0AQP_Mk$T2=dT32;9Fa5nOS1{>akhftrkQb zw}m#oHt2oXJhCVZsu6a=VuiTzR6q=?qJ--ZP`hreH8dctbhh&l-195=Izv1_E9GXw zv|JoK{8f<|D|ELD$9##x{X&^?%up7M-f0;;i;yO2iEw3z+fV&+oDJ(5|F%aE z6%WmnC@{gqW8|VRs_`daAfky6r{wp3#p}q?HKswUQ1jW=oq9v( z@j~RsNQGoqo9&6)T!Xb{EsEpqdAxlt$q?E|a^)R}*$31P-U`J;E8*4`{vQaA+Xg<% z1SDyxnH1G@Bl89niEgwbxL%pX?)s!>YnkO|n4AYrNJlnHfuk*v-Zw=x^l5_#>aj*` z*R&}KPt^JI*uU8_+LxF&*o^oGhFGQB%wX4-54lTYw+ zzpcCXQg%LjSqFFXMYe7A4!k2af}zFD$)1~*qu06n<%nK+35@q>`pPHSG@3hsL*!jM z=ewe zEXckHx)<+e2hSYEOM-(`s&rl zzY53)8I=Ed5+Bw;#3rzjQ`8IQev6xuL{o$T>J*S21pq&s+>0M1+x$JlTj<}0yT;J? z^F-(u9UH(% zTn;4%kSy(aDi8OtiyOPDF#`;3fD&@lxD%j8I zQs&sWQ~g+iIfPn@CRoE=6Y~MDNkl?exl7BI74Ap-(4;9aag6`tvYGi;DgKW^{{Eic za!KLhNTdnUXaU5?q8K?WAR@#l|0jqj7%WK$aeGp~xqSZQ&;L$-`|n-5!ooCPN2F(f$0**U_mqL4tA(d964;v7u-|=H%IU&PgUk5~e?UJM0;FJ|5m8F%nYV(yJ zQXHJ+UXiB}AjPDoodziOFMMWS55M~uxpSF;cdgi{{PYRmpizc<66wQ z*~?%R=<#hR00VweM$eZhHh$Hpj+AcnOZLi~3D_gtrQ#M2s^CA$G>^Cn=}k!77+a$Y z^M4zhHuo~nuoFCfx%Q3rf+C(d%B|zj1p;>kuL_|T%N~PyIVIrjt5VApXKUA>cyi!{ zC4`*yBmSTg6b>yq8$A0_8uAgknhLiE#R57Cy@OQ!#P4tH>wYOc@axT>N56Z{FU9}) zlaL%GLgp^l{0SkQ)S0GEe{mZg0Fe6q!w~@J)BpGapmy(oaJ0swj5C}K81r9L7uN-6 zqZCMgd0Mm~paZIu3Z!gzV6+QR9He%E4*>TK-Y3Y~BIo(!K>DlqGhj`%PcdQ)BvT!_ zYfvBLa&154@(>DGbnb=1b0I)d_=}#?M62;VQs)O!^slt}e|c2OoahobX8=gUfAu!+ zAu>O>QVs!9`Y*IYetlBK&u0APZ29>%eh#XibK@tc`u$S%li~hcH~tG(@h~s3bgzhD zanp~afdkg`{N`S?6y5|(?b8(MkCQ2|fN(3rb~hHKAHMSc*}3bz#(KaJ?HcqQun+>_ zB@QMInZ2NZtJ*ba9B|(Of{L+?XKj0s=mD;2w<8mO$=-ee>?j}&*(0+<{BOMN@RLLK zrE8FKy|8pd9&`sPqQEBkkDxI>&;O5zba9{gJo6f4KNP(klFq4fBnw~9WS*vw1o;>&A6xPjf>Z*i9X6OUE?%CcT4@Yf0vMJE5?)qygwwX)~B+VPJ} zl>`&mjG>hNez?i}ZXj|{)1>?Z<6F)($i$Gg(>qPhrkWC`S-{i;JOb_?c1+w`MZL1q zSr)=RC;+bx)bGGjdjUt?L@^-l&S)NB$-UeRIXkqv*fRdp^<1C^P~Jtj2MPQ_o&VRX zrmgr0I=|f*@~7)Xq9Bz&-T41GVSBqBDAPb{#C?S75IsdDw~(Xb_PTxW-jERCA2m_? ztF@TldF(=xQh2uTc~ukImkOOVdk)>Z0vBf<<^G@V;eTPU!3Vn_@t9(1i;lt+!MsZT zK09!J0E}2*ahW524H}{CmqW_>13tlz!^MjpIPpVyJya@IG+tkWq`}9ELa2#6OX`9G zQyBk31^-V^v%bXIRK0IE>;}tU=`+_8n|`lh3P}$YFSwwkuSNGYD9OL*k4XS3T#R3z zvy^(05+Wlcwq;sXy@|w5ymS$P&#{9N9NI6>xvq{&UB)O5)@Dy8MgWCueZ0*zNHFLc zvfo}KdA6evk&syb=4G4hO=L99r)9AWx6B``2P*Uvi>&I9}VK4KeLV5|#+tlnoa1e;&qKNyN5f6xJuA zU7n;ht8HS*1oNQUQI28RByI>x&j}0H(AEEP$W5V6@@24cX-|DhmNZ<%ianb+%2B)< z87W+X429;7v;$kS6;_1gC8JHYp;Z#Wv~#A~aOyy+xP!;D(+|WXx#OQ67Ma`OWsxq9 zogMo&s7nuN=$MvCBh*h=Fh(w8!p5=tHk%I5V^jtg%gVUB%`^fg)5>5z5}CHo+5)1u z@AG>gWQ8DmHIm|Lm!z2#>Y2E4hNY>SV(K#sdlBJRdVSpE4^fxH^yruESMjKB;hfiNe@R0 zsD*uWldfhlU$i2ns0|!@b`ld`m%U(BJ|&f*CW6lC#5(Dz0DejmZH#i^&?ES2ncr6r zYEw@wp*?2zh9sFHoZWDVmtL4}zz&tc~n=J9&hAh&a3TWGFMQby+}_@q8L`~Jh5 zy^D4C;&8bv?nZgI$W^2PL-T9A(Bf(K$5p!T<5+ry+D~ND9izpI)ul-!_ZY+)I)Y%K zxWnWvu48?i_2VJ)*C5=^%;^m-$6eJ6jYzR#^?hg0zmp-tGJ} z)6VprVjpy6EnbMd6-zyG8L!2aS=aX`hp~k)%-mVuC}xzeQ5zBKnfCs^Bzr5n=)D5I zwGMC`jcn$JvRIo5=vEbDQkf>(L`edB%$4nU2U+H& zOXD?2bL>nGdH4rR?glFN?@I(I?dO|T=WEczyNbj2C^qx!HQq8TUvBq6{CV^a3lydHRD$joY!}v0^G$r6-=daC32Y|ho>41SJrZD5 zbS`Y+y%km<<-p~$;~=2kJG@=t(-DTR%Jeng6P0O*yYr*~Q>tWiyS0Tm>C~sMsocOY zL~>{eqK3b(^3@Q_@7uCUu$vre&Z$bP>_YwRo?H!+@Wu}`!9>fUy1F&`EQ=(?PrsW{ zNbYe3I6(2HOa@JOwPSB5=(^2w3`t&);vo{qRW|IX6BAaZZ=7rAW=N#>rA?ZI1-Qk! zg%+VL8lTv}DoAeI#q5V*tF8~7<|AvWh?L=q!G_X?>|L?$(&QAstyOf7$#7tWG6 zo+&Gb+(NML2*q7LaqYj=nm1VOR{8gvQ6(}Jm7zloFw9iti&~Q^Ww>F}Hc!J9wswJ2TTIp&#My913yP&zIxWWrNvcC($3Gjk@}LGkB4}pRIx&HwXHb zbUV70cjtqByp?q65aVHX{t>!pjjSEJ|K_7ny$br!dzh276UAFK4u#G0S4JAchtuqn zCSy1z%afWCwaXIkU%WABn~^{*{E~U<)e!aO!Ktr-lSA?(884l>S$8&(;r6q1JVvCr zCrJ8>u-7Kq7y~Mjd)goEXBkw27gTU3ybtO+44DzLX)TGwK*)Qu_z1JcRXwB03n6&x zLuf6;=DQFCrRF=k4Ds#tjAptFn-bd@FrSV4Pbk~t@x(FP6JmYk6J1yM$t<$!Di^eL zFQj8-Lli2#lYAT%F7&+hXtro>E5l0HE(Pl-M<`@3D2_|aFQ6YGpNE!b1V18_+%N(; zO=v+GunqCO1_^Tr2;0D`CgD{SSIGUyhw|dhwqbqLq;e=y)kkmNvlPbKPcfQJPMu@; z@U3q>#5EPh2Ty$#oEP-%A5qgCVocwMPjb|Fx?hk)?Sxy~n!;eMAIs)uOrLH~If?Z| zQj)W=uKRf@*n?(xriHXL>4uxxM{Z<4jfZijUQZp-fj?9rQPInOahFHMoi zqVud#=c&&k$T5c{ic7h9tJq3-xxH@uZHSE9oI?_(&4yEO)V_V3K^)s4IlO*j_*o~-~AsexYA!$uwOV@Ny|`+j8156e0!kn#rb8;N zs4FdrLff`X_L1`4pI4*7(6`#o5|I6pOAwMTnk3 z5hg#|lHrXU4)II=0P^j%;s`;a9U3<*QT37XzA*QGXx?2mJQp^0rWENTRr%N$LTG7{ejY(D#$Sf3qc4c=K$KiTz-jprsQA9b@@gE2$&rSQvEvuG(z|_CQQO0nxuv(36oz~5rU0NiUL5sm^r9UgajG`Cy^?VmT|bdzQ>=SZ!C@w_l`}LpVRerZB1L-`KolS|9-C? zb_;}V4$13~U)d*m!9z--GGT?#$Lz!SQz<*5$Y!j$cP^+g(wZjY+muxj-;V+qw4O@G z^xil0-;plyYqu$qK&KCv*=L>1TvvUA96m8^xf~)j!t8J#!RM)Q-1GOgBG(`!$G*&T z+p>xHt&9u~2Dj+oU2**bh(gQKYEhrHGY8eCdWuF5qUpWI`1|)CJ`c@u6p&~o#EdsA z%zX5D-ojO_bS>|F_@uA_M$f8?Im(Z~c_XHda-$O%M+*;|GpDps%MD&ar|FE8 zE|NcC#pwpHRPpwq%@Xd$U!IH=;7sc2aB6hw@AK*V|!c;~RwgT4~DByHYls zy3eDPs>38+scaX&I@-~;OFvCi9xyj39V#G1juNJ334E%Lr56|YhQN`T!a3owf=G7s zgz&^}yVrN?q(K{EUE@*LJUIP+)Zxz15+?tk=66hdOMFj>iyCW&lgva$<`GEFZIb?%x5kSgy{;P+Upnsm%4tWREE`kZz4bysKb>DGL*Cjj6nO>PUe z!n{c|_C0yvOHsSDDBbpO8EJG?l8TS=qVhMW**}7TLd<3RV(?Iv^xbVVj{NLXp97`h z^0H`*qL3K^@TNwv#{QKVmA??Mkzm32Yb(<#Y)$9ZHE78eko$i9c8x)i{M0#T`!+^D z8H3<28Pe;U#jflI5cRm&A>?Xj&7>2a|K?pRt?D&s2JVxl4^$V#DGgUV6Mg=P&&j^e z{6Zyh`c$@6J#r?3yf9D1;gzL=#-xU^G7+^n++OasTBn12xEQMGAw3;Zn?)Uw7L#|{ zfw6M2W?NJtyEK($SordceB9znfbpi+U@c~Yy1=N{+@yfuK1z8!O@au`NN%nrVU))h1SdZ%jgAV{6exYCO8gQ_54!Wjl^FJ`)#V#tu(-%b z1&kjd+~CcaYY=_7?2YXvYYV*Ci*vqG-{tw}?{Km|&M;P8ptdITmr6-#+LC<;=6xaMPmcbypS^U9UYD^l% zC?Yu)ar3+FmJC%Xp4^Gp&Q3~Zvjo7XleaRW-xz$3^XgOy_B1a!LpeYuo=a?aX>UWjJFPu)o%c<`xkvfV z$mQ}3XK3nnP?EK)ef}0^bJ+xi?_H7GW6A+5PreP`k^dI_)qVm=kNjO3T@o7O_x#dL z?!51F!7~#Clce%lO7d$c!0zL2BR50-g899;#5LR*A}j?8W;i@FA+7?Z=QMlL~WS5U8` zRj^xn59+f`S?XoKRt=Kq3_YPa zcN?w6M@V!b7#aQ8p(kvuCNp9lOhjHUEZ=!6nW;5bdWj7}r?+jx{ONr&`kNYb$M zt)+hCGuB6UnoamVAj5TGS-%Us`EQu0?|63I1jR(HrLjqq&$G#TDenntz~A_FPfW3Q zreP*Q>{dc-H3#`>A}t z;cmibi)9nXdtX{fxSy-h;3D_gh384^1dI2Y)uedxpt+-%T!YXU>&U7q!X>uR6Wj*i zU#23ed&u8&vVI3;8TPx2EHK>_D;`@a{g7X%tg(mA_+*eu5_i4wT{w>HV6{3OQV%mf zPhlgMpZ(taCYh1sh*i)+^@iBD{?HmdJzI>UTZO8pirT}LDWeW%twkf0!>v6v@*S3V zBp&ZLy=>ZV-;&`wm>P2v1u0bzFAizoI7r zpYD5IHD2ZzUSzJzeFFylNANbzve4ZTjp$l6Q29IB7q(g*JeN5m_z1yN!>wo47Xo!J z-e}LVEEd=e7HSAA^4z=AO1$_kBmqhf69wrBn`E~eFw!$M6+t75HR4WC@ypIV+CROG z5eJn8VYW5%z2zY&0%n|<1zCDkGr41-t*x~5AGBMy__I6Niz?eiQQDdu0*z3Kg@c*u z=XARAlw9f;_b1^fz=sO}v-sbbVz8pG6t6*5Cfz5H!Pws!*FmB-Cy-J9CpQwKG}Zdmy5wJyIuR(g#!VDLK3(NRTnalJvuvZbQbl} zcoJZF0+fIe9q07M%v3j7f3}W#wF_+vDu*5n;#>ee=Rr3HrJuL_$9v2~;oiaX5^hH% z3{Zo5!XH<_`KYSJNsxRG#j<5XJ7k~!`9l8N$0LzpG$wmMNma@sSlhJckIB~v@;!Gx zbA}6}QU)iT4+C+%J<9b$IPY%Dt)2~(?Z91y0ly52y&H6j$8T?x#PS-nnnrN~=<|sI zwy5&EY5DV}U-{F2up_<$UyBomREWSi0DE~b(fh}NQ8de+jvl1}o0NZ~$@u+w`ighP zAMS`Jqj&t^pFf%5fBRZsGSJi{!dO`M;?=8H2wRGOyRP4WF8_aA+a>Tr(U!7%>BR(r zP{rC8zL&@YtF#w7C!I;?KonvC&1nV)VuN+U$FBB`5pRMIgC~HMT$lbNu|A7eD#NPk#7+aJ?Y>4NV`E_*KCV zoi;Em@MY2~1fe@qH?aD@Mg3tsW<#|Ro8O>AFiz_bz-9vMfC>UN1CyfGd%TU0sdz9h z3m~Ydb##cl^deR)uzOXOS$9F?gx7_zQqnavd|~0slwtXcuL|iDlqA;Bw_>nM7lyTnXb6{&(H-Nxi{gwj zJhBk!>9Q@hET3G?mNe4Ty)cyEeBwyC(cW)Mhe-dJ4aYTxLF2^_Ysq z898AXfq;Oiw)Dh&(*i4k?LpXkQ`MZ{w8bx3wgSco#!0r;2(_6^P@UQy`$YlJ0r8)c>mhZpVasKaU%MpK``$G_jn|?yG{QK5bk{Bm{=EECU z?3nBiSZs{=RNQ`x9RQ2v9D%MjOJ0K-ZK2*zB}U!Vj4~m&qs9{T6&zh0FUAV_=WcAU zVW&G66TWan=rPAbqKQI3W(PNYpOuL&8psqDVJ>bjU)V%3gOkRHy9CsP)U~sUg<;u! zjT3wPs3DKu_(jaAh-mAYe<5H;K4081p$IvppXO$uEE{iT@u{g3U`;nrKr4< z+>-)ad+Shg@|BiuB$YmqR%#b(KDOtI3 z7|vqORh|-d@G3&6G9Olw6y}v!cUn;Fd+xF_y<^|e@@;+bi_vFEfk%Sg>(rEr0+u??Ck5I#M`zbkFz!$9!nBH~*Ap=^B%bnx zb6q~$3tU8+j}bj(Yt7oZ8qb^>v-k*YZ^|??d~Bd1>Gg2ztwGpGMEljti8|S8YoRoM z%hO_x>BGz^f9oLI z?}NaZc;qYnW0RQ%bj#~TYqfxo+^r@wf``59a`x{BpI9Y3Cduw59LEjS!8B%c1}%+Y z(qA%7dzr+%y#qrcGLd=b+%=`R+5<*li{6G$G^lg>)yxIGE~L%*WNP0?zpqTnnipO9IV$s1=V+y+Opcn4 z8L|C9DL8F^e90MqtuW(T7m2>5u+)vA`36HZW-x|f|jATcc)XXSDFGh2Ca_VPo}}#VpDT7 zFANE9%6lGbq#quw>+aR+hdbYHP*ExokBU;Fw4^32mX#!04)z?|OEe51 zS}$*|))rS`FDRQz4EtK|(2`F$mjIGF0bp@B+s|DE8iie@D9wkW&xW9^7wgJsD3P~o zg)m(LhKPd`C$D8h4lP{2gW6QtmN)I0Lhv)FmWYb`9OWf&`>0i{Jw)HVg{LQAjzuq? z35X@PG2~rn$ys)z6;zFX?@QD4%Ut1{#8gKs~? zb<+MeJo?stOg49}okh6Qa%3(&#l_&cM5EjfIUkw#;mc5gw;wKz7HI`sC-h5I&@+5~ z1luNxvX@DIs`ipI;aELQU^w)cS z{N?0c#Xs*_tL^}xw+nR=(M<3i^vq@EzRa6KLTTf^o&Im};j>?@{NldqtIW5nme6ld z1aHe-sJTqSVI|)|&46N7`y`#1o5d zA!LvQ>-yw72(E2or*KLta`ec}torzA!C$;daaeL%e7U0c9pnxORDLd!4G>QEMZBcY zD1`Uzh%D*t=pJ{pB5p*!g9s%4@GUzLX(2gFfQT;IL_Xvx|KJ~+2%rz{V`%_c18$1* zt?!_Vy49~;UH`cc90$-}1yfu;_)j-`zoOVr6-TENKO5y1+M^F$qPL&UddZ5pU^w9> zZ_jL+FPL}qzaQJIsWY2wUNRVIQAreg%;QSfL<2){rzll_?f&j4yi_9LmV~0)Cu@mi z+VUjIQe;GJGtdPZ6gb~O6JTAb=Cj22_R}$on*&}6D-H*jQycBeX5#sQ+Ts6kPiz(~ z{OmZ==6`x8Z>DeaLRLjj^A`FB$`SbFKv+lcoyfuHcM!}D@~w5Ec_Ya8<_dyft)&#* zbWt4sVHcEF<5ue?>VG+4e;j+QL|iusEV!R=rRHVq#2+pd^2d>%qziQ&miTF%-hah7 zcMMwR`J=ys6oPvdd}zSIQ>z~z@Hn90xJ)LF&ygTrKuvDk0k}eHz(5r;=2pFUMCnNNzpJTTr@uCq?Vs6L`hP}KRe_nw^Xtqc5ct!~d_Oh`Fn} z`J3KzI=bl&GZ*?>cnLmtId%<(PSIewxkaC;@bp5>=+(peSfwb9)Xs5{gno3E1kE=N z+*<=K^gAy{2uIh59C#JBO#>c1;1ftV>T?}J=GGEnp$v4P?1uMKn1~$Dzq^sRcyl6; zLRb?L+Dm^zjhYdx97$^UWIH=2drax2CXPf~{?OGmF(^8~Q1Pw-Chwrt3%QhAVPB}C z^+9A(nR(m7qqJx1k45Mau+x;=$B$!f6hFxw@a~-8I%B$@w#9x2ncT`w^PoI3(ybMs zFaZtG8NMxN9dUVboegJn5trXq_MkjP^}rACqSBA()_)ZiNjEx@{WrHr#Q1e*b^oev5;XCS_o7{b0BjXbmqdp~txS1!lf;Igs)Yg<;Kzpz`fICe zD$zUvGW_Z7T_T6Xon>RJC#N-+q5H*9=3Yadq;c8Ju8CU)G zbS{=3+hT}x5W1#ar(<=Gqw%bx%aPg4#X{R4waD2xbf0EVrG>o3MdkL-vu&5jWH%HV znt4ze4yc|C=##ui1!0H0XYBX=d>X|6jfv36b8o3D$hcZ!>Mo6kAlB8uFy&tN~vRXQJ`>%SP9F0_DVX)AO?Z7R&6U)8_%q1pE{i zvJHT%CF(44Fb09k81E4G@7FuUsO}eYw3S*a&xAgmT!?r>pVr0N>tdPhoT2TO_05Xb zBGd7m%HrvgCtfiiinrlk8UmoJS9XV103WZ&A%NLyw=&0!z@>0yZoYSYU=h_VpceG@ zeF|ojN&ti3?{kR%-tj+F&fq5=q)1{}1nyx0*?~b$(28nB#*2qksbLg|XWY%F7tL45 zld{M+>*QI4#fx3XfaXV2!{u`Sr^vViGCgBd_Dl!;7!^`qjogo|?ZF?1LCSM~gkL6}s6rP&7+FPulqo0$_UV zHDX`EH|7Y5+kmcqg>$;$&s((4wa#t2tEwyFbLe4tVJ`eT=*3vC@Ivn?FP1-KhqE|i z;aawa|3DaENf(SXML_oW7k8Rj0K}#5;IRoS&&AQDyCi*DW>q+S5%z|M)=R8@Y@7I+ zQ__Gv7wTAiyL`!FHgX0>iwDw_Q0tyl>QlUzc16iz%_H*&QG8!gnKQ7zo+Fdtof&GB zb5a$p$t$hs{V-F7R%(X(l=V?n6j~3xwP5*l3Pq};)yc8>ADthrYr9@L6GfTG1<#vb z7}N!ue40Uj#H)8ObjY7@!_-T4`F0u^&ddTBSx68YJ?C=k~j9WsXg zq8)8kc=Hm%Bv+ALZhtdS1Oxm~w>$Usl}RktG_6`S4?CYA^8JwtUf0Ij8*+2fykCD*cZ{{ z1_lX<88^a}JwP>S{o&1fu+CfUg53}G2P7$06;%(aMMpEOqh>rK?1~n2cVK*_QVd&D zjQc^~L67#HBAOooXvv9O<=^}Eg?3{X6saGDXpk* zLxHK52HCXIMfSVEYUl=F;O?(ifgSmxa7kn4mW|oDIF!WiQDiRD20Kap;#=~TxUDQ1 za=up@SXd4BKq@uPJV|^5Xhr7tzZDR)6T7<*FkR+SOq6NqO}RYO5X-Tb<*8|HZCPR)I4wC`W_@MG#oh|(n&i>s_|SCU!{lHa-TEX1Xs6m( zw)yNRdPdsv+%EL`GgK^Xep|ldc;;p5SaJmpa!@Pd6HKY1&+^0iYJ$%!7OU$LWPMO7 z{Tf1V!HYnPD>-EO$S(s%v{kSwXB+O7QPXyv$5^!9-%Hlm=DJ_ASJ)uUnozDO8-wj{ zbS%Z%@giIZmA73BXKnIoXr;Z!eVV>{baYvF!bf@C)6q72D_mX8V#Ziw`8mqlCkBaa zE9)yeQcKbTU<7p10Ze~1+5Pl+LG9eY+yX0@%crriWN1(S>Aqo8q- zleB{AZt-&5uJ@ggU6^3%vu=y2+e0pn*|@cnr$YhZIVENFn()2;n-4)EyE7D5sK8cn zk)`@#l508Nl;u?Hnyjo9Ei^t*!9oVUk=>h|=}@N2u~jmASJk$jLDYN^@p`%D`fIp70_0Z3REoP?nBdZyAd(geb|I@-r<|P`~z9VQQvX zmbjekI_BFLLqx@Jhh+C6)dwu>F1;(XL{TVZ)R1^oo)G?osUUcrI!8x;V9HswAoE*7 zILlXN=N-7ntFAb^WQho)j0cdmCcuR3GTstl65I?23uh&yQ}hi)nN@2vmrvH;yzb__ z5i}R3;s6iJMh6hzL84CyM@5}=8SfUPv!Klz=`^M;sSI?EKCCsVjYKail0y!?+l4TW z_yF5UVho2qrP<8u@^r*`aSK&oI7fZDHFs{VDbcA9k2TY38zr07{9}dg zI?zlyR|de!Av=(B-7A0@#Ri9H0&v#vppiy{B~Y9QV&#xA(N=VK>}R7paTP zM6O-!BGtI3y(yB77D!~{mt_jHja@{2~k#EkYMfKl^2a1bW#`~9{WI~!o6^G(m8!P#s zHh7b7BgpQgGn#iAZ|+SkG&PuqLUczikGLZWzcjnDAb7ZjO43-a5!XA){v6eVEy6Qm zBrZ6ds^MKxAP14GC|=i1u{;ca0c-Zzp%ejeMd}?1*VLb>=UDn5Ie2@m zvTZ26At2Ke`sjU04Eh2}0X;#x6|VcV2SU#f0iGgUG^ujS9lzbaSD3X>G24o{yLU`; zKf%7kJ7#`Qp@Nb&_=Nx`iFc`+et zmIa@R{MgxU&WZQkK#>)FkBH0h`s7HO^t>k`o{M8S{Z`&&+lRX!F_ zwUVhJ?98+;7uyh}5u4-5)$W>6x8e7m8r=kF@!H%nByCr>TJy{zI&C?-nH_m7s7fBx zV`9~y)?ERqIqFMRL)kv$kX17m4*sfO)mk)A`1oN!XqDP!(CvPZs) zZ8MY_iS6BNI!IRAPf1fp__>eF;F0g?4dYvzrwRb6wzHslpJGi;7Tev+gSzHAeMgLd z!p_Y!>*EJ@z$;exwc6BwPD11FAsXTRC2uZ&(EKl}*!@y&)FNaSFNI&l?UyIiZ^Hn~ z$>QJc=(K*Y>zKkX0s`kLs^8wd>yR0eGPQCUrp-%n{>9~sezP}qAK+hI9dCFAV!fhI z!N6crj*yNPT`M>%$B4l{I5*VYbizh9~h%?KypYdOhC%M@kcW0{tf$;W)2PZcAx zd55{SV`(dCeCWlp0F%>4d9Y(i2S1HVLr?nQty(A}qrxZMkYn>BM!d&Zz9;+=Frfm! zZrWt`%~tfnf<965kNRbAn*#>b0}vDaio6+^(R+{HvLhyS8peqk^?b8Y##9hi@J`0j zsCZXrYT1o8jmG}57&Q5spj8B627L;q2gn6|yf?^wuA=t~Wp%B2eTC#cE2|~Cui5dZ z!6pcQOIm#EsKe-6<*eeOC7^6b$BRF0Y3?XwkUYTYKguENE_N-x&;K110}&ZI8z& z8ngObw~>G}ajpSLr_Yv;V)hA_P5^_t&PsiyR}t9pJ80S^P_^l~?66@PAEjj{+TqTd z%}n}SI)ZYPS?%EwEZoNxb>Ipgi|CFQA_+@zR!`PCU%yR2L@5f{RpsaEYKiwvhW0+V zC(&J_2LU}{A`WQR%VmiZ}SHgoIO!jg9C=4n-%zF$e2&vPbC?_+ zbVVtbAVSY4*%RN=FP+VbGh)!SJpiltJg%(e;G3h)oEX}eB$4GU zAZEChB5EMRk29B82g1>PyI8@vEv0V3o40B936j|dbEnlOlPD`28_H|LI~-h{m785{ z8}QH`TUXex!~qtY&r?rJc<+H@pv5s{-LCW^ZJvpwCVIrc+Ucm5GfTH_{~kQyJt*&J zyH2Jf6+J>-JKo%h+6PzN!zwf)`gG^VfHh_WsPRix6`z+|e|Ro7QEEpW&QKhAr_ah8 z8;x?qd!|y%s_>v%T1K3YuJRbYjBu5SxwvDbPmZ_qvfWTYI!WwCBdXA9i;0A1o~ov< zX`EJa_|X`i@-igeatK6yQzW9%krp6RU2C`XEv`bjdC~MYH#8+(>WK1j{F=N#gyhh9 z-0$2^fOqB8SWTBj>MjWRpLDNXMM+By@9EH}xa2~+{JJbNS-g@j!Xs?7;_hzo~753MWZJ#0|hK@WtEwH5Qy zKFQzm^Z+g1)A)nL#vg=n*3TA$zldHO16hUt7NW2B{vBrHKm1;>9mn&p?&r!^Kw%Kj zk7&3mS?8J-BnZxAyPT*b9>9&Q`Mf-Komv3t=n%9oi?yb$iR#(scQ>fkh)nbpkAuI? zNAZqOJILlre}|m3Bt$0US@1rgIF32dh!A2o9NWwF$hnXSZPN1K<9Vs5fpOlmN|j?n z8`tt+0&;H=jVXY@>18!9P5NTe)eY@CNGFl`E9N*!h7c}9S5z8Z49Qp^!xA8gzXFi! zfFnb3?#Q^YUo++2*jy+l6NdkizSUcSrjX=LmLQP)JF`MGf^1!=&91cD=Q83j`a%bD z<>+hGm!Q<)iZ9+a?IR7aC!1~4ItJe*qXuigi3*au9n62rX=6TF3}jOTZOUI}!Ev@@ zil=8@i&_g;U()mWH1@toPEkNrSxnW0ho+P0W&ze*T#|Cz`#gkZ?#q(9H#{yW^rufM zD*X&SPK294cGdbc!$*#ra_$Oy({(HgIse6@=qKu$2Pp`B5B3KAx*gLlL6LR0@&T<~ zddxo3n|=P}(n><$@S0tlz2obPb(=<01UYJhzHM~Me3%xSbbzdJkbD0{hrUck#m z^@IPIttgXiC!n>mu(Thk7CIRqgsgGCgnVll0r**&2RAoz2-8PPaG+35hv%#`FX?~*R^>SY0pL0wO2C==*$^%|0N`>AfO(jgriB#iizNP+HaB4e zPLc(VF}Lw&4rgODem~>Z0z#jZ5W@?4Ri1O1wcr2f&Q}e_b{T2es&Qs0bo&vF#T3kY z8_Pgz_`)@F6>)Up_E;C_f_sd)%Zwu`ALE`U65Be4*LMD~i$ea`*OLZf;L}}+<1*oV ziA#n5@LUR=Hi!UL-Z0{g^}-*!GyMIJezQdY z_W>AV({IN3%SZ@C3XtjQwtWW)@B+vjRp_rq4gec|8u|5aMh*dtoIZW}MTr~aA$%9e zVJ+$YYK=g4>xVV&{c4TlKdiANEyM`(>nU9BxEu(RescTG#+!fIc*U<1P4&k_`xXE+ z0c{c{GVmWZmi|nBm*RhZTgT_vzCw-T?W*a+yQz+{Ofaf9LAUDo8S>;cGG3R~__M0Z zOfiJFmD5fT;a)KgC{|BvB3uUn@!pWb^j!e}5&TI3X?& zTKIwd{a^o=YHrW0em5vYu@RA$1*H9_-}Arny#a2e$P!Uc-7dSx{c3VIQ&1&vUShU) zxFoG7|EgM`$dR9`0`i^$O0hj~Mo-?(G@_Ujd6GE;=!pnX|0LLtjme`>m@FXb#3N=> z;GbTDkU?)T$147$+Jhoz88|Z*2{~Zs0N1mkNrg4f%N=qF;Ub~^_~Jv6DXlkQ-@;5x zS5N7}!6!dIhQjkBev$U`o<0=f1LT>v`Mv?8gwjRUPU4$WI496f>=UmaU3E5rMf}hw zx}U~U)>)r%5>5-PhF^jq7px(01~VZ{1IiQ5%Hq5WpKH}BNlS~}m6vWUU(HHMS88vS z(Lb=uEo8A|+Yg715F|McOsxl3%ZhFanX?5wo8bCM?buFCBs9K4#gqGb~HKDl?5sZDc?=0 z9~xDP=8l#Vko^wQ4XeQ=TtrHkOt>(4Cw!^3!Ml6=uD3X52V%ut zJQPqdqTbPou;vMvcaEbV*)qp=pvO2DO+uSJDYEUHRG7Pn?~~3clC1osqc+PCeSc6y z;~{FWaaL_bO?jl4ElOzD8(vi{oD4&Xj=IF>ldZ&DO-V5>MmK$v_zJTEoemF-Ji9tZ zw={Iv>JMjK`kr4)HN`1`kudP4o)K8}uvZ+Rxv=63US+7!h7-|B8k(kc#!{s+#%@In z8CToSAw7bH4cq0+UIr0AFB6tk7hS!w)!;U2c$5u}IjCD^5i4Rjy-)in-7ffff-5Wm z$iB)hmv#(m61WK3YM5yhMbX}{PORzQXMNdIc&-*4Z`)y;Y}T0~Du%1{_eXGxwp^^o zS%b>tNEM@Kp8z5>kUBMpbWFz1GdB{9uPzC;p1s9au0QhHxm-j@RfjOjkgj*qh>t7f7SD*aLPX0A_ z{y$s_cz#(Z6$A$wjYL9o<1>wCOHqbU{f_UT^;>l*`2SoyKVE-6!QBQ~()_Y=veW%o zY?X3SP?zO?F19#7*H-?3f1UCFv_F2kqixgQqBCBo{8G~4j4KZWz#)sAO4x^|zm;@C z0+h@LKU;8aE{#A>)V&;>_Ey>$k zFU{R%FK~oLt&N#EG7bvxqK(}$i{eC$@oio;0=Anw`)oINRMQC%^CPF`DkH+fWJNhJ zx9E{Y&C5oqux=6d0TH=ZN4=V{%==4qA3d2_X`YLVi*{w!)WxlDo5zy+(}rcZHQZ`j zg-PXmIS3ig8)TW0laJgEiHx8bxm11Ve54VjLMVX-!iLtep%YOa`jk7GXV1*dOW5A) zcwF`H0hZP+41KWsmoZPGOq=|1wnx^YUCZ_S` zt9GrJVoaDDsWUC*+TfU{U=?$xE3Upltf?_%O8X8aGDt^BB_AtW1CqUc4%ne8M#_!& zQE>lTfqNSzWIGR>nzbLc@{Q4emp%7JjMvWCQQ)27HfTaldFMJ*6KoahB@JVAb)FeG z?l*mbceZ>4J@>@Ea0lf#QZ~A}zWkI~6BfB9AzEF1F;V>4zL8^8Er1Ws zW8$zrLVzR1AOO%%IM~;Z1*4}O-c&>0Ho(FMQL`tfG?*vfZdS=l=ioBz0 zFJquEku7yfQe6{9pdSsoP3{2#<#CQY)B_yO2fx=8`}dAhqTcpM0`=9mnN*cv80+~) zRu;|xf^I{(M+!woJH1IUe z;kxh$T^ig=V)g_NCy0wqF_SD-!m0xKLR&kq7%E53^Gt?YznVI3`GZ8-cl zOzaKX`Bc$XXxpC8x*z)@AEjWH1@sMZMNXcW+S4zYDk`>6b4z}uE?&~G`>VCw+TBL@ z4fa=(wMMt;0rBZ&s|&27TvJe5EOV*oLm5tgTuF|BUA#B05n8W4$c_x;3$mf4wWICt zzrp9AIJa)u88AhzO)EVSc?fQLWd3P%UWI$`&~&Hnxr_k?h5sp%fnJK4BLPt_ zHGSYmwA;Q~AziLRXa-_7E1mp??v!JkGu>2`0b`%k=jBd=W-U6c3a!-4R5UVcYf5XS z{k-w!6Q6E9!_WCUm6d?q>aPk+!6%@u^qKv-<+5#vJW&kBLrsQt8zg z=Z>?*+;T%?n~4gce`$w=4y2oguD(M`l|)F42##=1_M_rh0_2y zR)`5)BvE?a;~pd5M!>|p)W-WT@yxjpG349=wFbG{1I>Eb8fpDj&Zd(LHWZ|{#JN{y zCOmj@iZqpBF=r~J5PiF8OPqmmOZ6q|8m}HKl=rB+8$$Wd&)fOMd}6^lgEk9B_1{5? zo1dz!le{xQ?}oL+7TWr0nPzzRY`Gc&zb&h%C_Pv~LH{tlaa3p_&;iBIh2TYH_5}%M z-^s!U!IH8(_=$g?X8O0S2T6;OZ33~L)zj}F(ytlYp<5H&g*kKhH&@T4*h6HIdR-mb z`PnGIBir0(EP8n_gjzp}#VuGV1uiBmd+_Hm(Y5h!z^Ts|oF;e((^zQMcM-W8ODRs-mvt`EH5tZg%zMbzEmrnug=U?D1KRJ#P{|~mtG5v0W=o8yyGUJIa*M# z#G$D(Be?UvEtf<+hQt~%SO~JSQ)NL5N{!JZeiJ90jk4E}8%@c>=;er%5Nh47WaU>% zo5vC_J{C3B%XYmZuH1z0e8Mq{WgDod;Z(=2)WIjR{L(@Uf~}3wR{a<@C0`& z9#JnTawl4~!IqpHKA2_c;xsENdOB9YL%W|Oi91xl`x!|jP$ps7p@x5*b1Q>itK$(V zn(N?+7N%QXWlV5k@!N(dyF>+<^gO8tAD^!I6GAbaI{8vC^8%JxnrNVakP0U?=;=rmCBH7_(wO)Fs7OxceDMt>D}?=<(jss#thHEkmI=rr7qSaQ{Q?hTzJh`jWytc{&1CglVyzFSOxOKl3bwOBx-`6k?BkCF<3=sc+QPA{G z@{JW7HGtyhqrNctp9+-y!&&0rFAcvP|07c1A9U@$gBrjqg&b^kka13EY(j zKzs}-Lo>4=o#l|`o7>u1Etx=Ot`k_FmUNrV!gC(YtEjulEe6e^6OF2BqXqlB`*c7( zf+FhbQ1JsoV;!v5*OS;w7D`&BhijP?!r0OKoEZLr0iVjGHpRi7)r;}PSofXZak_5Q zHy9lknK;d9s0`f4X&pNhxjOw8^kR2j(3Z!~DvnUnVO%T)tL;X{z^>#D=e5}5CqQ9z`R(1T9gBZ->3g0uTVpH1RW^fjfj z)wIA96aHs4(ETm8?3xM*=Q&)`A{%Qje(dCqddMwJP0fo}vx5dUTHR^uUC}6wGRC3tlZ=Iq(2bJcKLe`dgT%)x{ zP3PgZNmMU}tN5R~o2576I;Pwygse=9P;4lUsWiiOlS7VkO_BS#zJo9%3Y`LuNZhC< z`jeiSjP0`#?ss)F5WX|1V!u=&3-Mm6ALBBts4Yo+M|YGSurHxN*^QuK6kVBB8EDRI z&)Yt)f~tO^i@waH(wy;S!b#fY`+Bx@&%4(O5WFV7*;N^&OO{AvuGbgit5E zab6MJz-_bKj5EZa#~q7i5w;*!Y|q43rFAB;vg;Od!E`QS=OpQZi)83(&CR_y+k3|M z8b_|C zb4%dMF^P@vAz99?PXFEI;kB^>!?DK=4b47tZ&k#>H1`&qs-CzwaBWX)D?)MgeBQ`Q zq_#T?r8as^%n{2GrUrAO@{X>eAOS%9@+nu<{295kc(v@Kc{X3}D>hh@)>q)Djy66M3jR1@aG*N_oL^&)pV`YzrH4RzX8%^3xvTq_+aXF;}~?3}iZc;}L@qdBMXqTY1yFk%}`H#^f} z%fX#`%zj1}r?NVXE@|TE1@F-p=qXC@Dure1&NFiF-_J$x)0W3V*gx)az;77wk3*as=DIN+W8frjL+*Q3~*#BDBT*-IB}d&$=v zXBZ<=CQtJvs7@YrlgIK3+Fk_8;mkX|VschI>p>mQEJF{UY14Sp{-j>b+Czf;TXlo; zO{#5%L>74H)gFYul{qKFZ1jVQI~?0~N$R0=Wq7Yc)!mz|k2i->XpXX9ie-zizFo~{XMr^w!gzeRbVL215c*F@ z3Ghzpl))|SHFRKS{a2UtzqZW(;eUU2i>3d32$I%;tn3I>PTEONSt?Wyl)OOMs^eW1 z=?uPUW<0sK`oS4*Fe+U~6Dng<6|=*fd(YA$#Uy(vq)pzVmD?rpASgRTwc+F3)&vWE z^oUTBev}BcOE4t4Q2Edb?)!o5JLv5eP`=(UiaWdnx;-SCVoDr|JsUx`8xvOA#=FWu z=Y8{@FSmi~melgx(`)`tg@AA01|;L8yUr5(`dm&BjQSjLU|)aMjpk&TW^bkA)M&|h zMg0Kw@N~<2!30?@s+`|J`WDYXQ2jQ&jx`>4`FF{>^MIs4CxmoTk<&u&v|mE2ddPAF zs{Ytt&u39g@a5qM-7?lQcUb4^aa)u3T$%N*x`fR7Sj?sRmQTaqQ&89fJ2inpr0E$A zr&p7^M>I`flkk@dl{3~vNFLN4Xrdz}O*DhTsX{*f+4)j-@x@vUYtM7PUaeTe^VW)r zAz4nE4vCrO1gdg2dO`NI3zWQR>t^$=hka+Y9~eyNIgXL?MED;cNCb{(&B|B4J z+KL8&JAUe)*>=2*-A=>KI`x^!=HiqO;a)l9lr=>cSoFAgq_~)KCLhHw{teB(D#n-{ zWe&Wv@J+R(@yO|Y{9$_mE36l5J)Q<4rr>H!8C-LXBv`W<9=QLY#v zSr>i3J9fFse(ER}O(fdYMFl@T)!c32GAQE7m%&W!+mRn??rbA%b;C`OzxXim z^$j<+e+12bC|Cf~S-Q~T1~nf9%~x&;Q)|X!5pBXYCvus?z(+I+Qjd_0?_9T?kym=_ zfw}T^hzj9vliux7-9!Z%de6%Wo1AiuZO7r47MK%@-Fyt6N>ht;UWbl|ONuZt2u374 zJa|Sr5M+_c8nU!LUSTchm?cSk($l*Zx>qTQworVbe1N&>@=ll?hT1FNJU!aR;%p)uZpp&Pg0*y08C;uPdFblud*;Ub5| z7a~8ORoiv4xo1KlsQJ-|D1Tl8)Q>;b%!? zNz$SwXSNpQ-8fyOCMfo+4?Ah@bwiL|$3@4R*nY`sQrD5A!4IDGJYsddK7K8}i?OWU zaNF4e-GVf2D&c_A&^TrJR27xxkqz(tu*9(Ph77QeZdlPV9&dji^J8u&oHSnu|t zRfVUT09x44r}f1kS-*(p?UM}a1QS@XgkT&Y;1T?YQ~uKdFaP8AZ6{q#z$)!Dx-G84 zEfrBYCy|nIjRPPa)kXL##RNRn)M>>x9LRkNhQ%oF1;|}o_yYAe@_t2Jcb}%yO#tgp zW;Yqei}Ji~J&pV@MSKCtyBiZ&D@E!(GOdtD{qJ~$&xzN^Pi>K=cBi|ZI} z3w^H6#Ik_ee$ri)c@-wo%sZ;oIcTZvw$TvJ|3?~16wUSyu7i5VvY0`e$t6ebdK z_TT69xp{JepbYCo&$;0l++0E^!@|#_^j#Rl@$^S4|MmJu&-|-D{$&sUnh*c;*Mp8N^%!j#v&sfFU{V+K z=1>jJ-N=AUe+p}A;LNkJxa+jmX1gV^?IW@PWom(6mcf6${%_GAl#tWrLt^?cJlb!8 z7%4#3mcj4Bj-SQbLFm1J3I->wFwt67l7JtDVd)b)D{(Z+ z$*j)h{BA+Hw8vG&LKE>hX$RGE%rXx{-*_pAE|tucArz?ZGpYu#4q%819wD!N=1e ziPvAGF!tv1Yo;qQJY^RpUZ2nr?MPuH;tE?-u;^J?n_v{ENLEekn2mB(6r@&1)4wpG z33Y)jaPdM)`|o(IKYYv6>ky$ z0sCpUl?kDeWgj7|Iv8tyM;kXLF0(0n*=mm@wql1cm3CmA9#5V6n7!7)L$g|A(ax3Z zl@*@z^Apt3wOioK+9?!;8bu^J-W5-6vWavPt7VHfmB`Y6)&1n7xua4=+}%h`jtAj^6blchLo%IGuG1RL+ph95xM4g2tb1)x8=lDM z+ijN^#}Ubq)vq1eou6#UQiUpr;TeAVJ3VazyGGva81ZSkV1`!_gb{!MvY4Dv${e77 zT&_RyQ~#Ls5n1ET6PyAfDHKvK0hM3mj|b+VKjn`z5GOy;HZ0zDUJlO$z^H^=+(8%z(EaI1Uzqey8DzE@^SbuP`?s?SAy)Tprj}~$6iz_P zS>Hh)liNg2$j2dv9CEONydN5sI%Zc%>Az@HQYH434~&3*XjBf1u|J%ipWQkK+nWe{ z6?C4VBE=312p?3cFB{h%TZwF(Rdi01a{o}BJE)N>MoAZNwtoMh>Z?Gj4QWj{H&m2P zP`{AOQIX%GBgrzptM*I32(n!uq+w3-tYDiSS+ufIbU_YGheIZ)zu@9sVZzI|E!-3( zT)1qZq){C_f27uiT?NBcU^cHG^BkKH!&P(Ssu+A|2IY#ZinH(XqzRSm%efDf{iYLC zo@#JjHqDe0snk9Tb!adZJrh*r6T=sEkg|O`r`2!GiXI_3B8-YE)qNwQJ1QuaZ#vY# z@3!Q{M`Fts9TYKo;aSi_e?O4`PUlY7B?2uB8+{@M@a`rBrHq+nrT91_72ehWSh==8 zgeU%vkj6hI7$Q`Cm5zYr=8;&PO5Cg{y$MXIj(KR5=7BrFKiY7;aCxo^aM6mzV*#L5 zKLQBA<2ii6B|cgv(`NoAWDv0MR@cB4qFyaAY_?lPctzIP%^@ zQg_zeySS9R!qlMZ7`E&blanF@7N2ZR8#<=cRmysR6Uz1{HFz zJm0*|(icZ6XO4#I#YZiiJ~xlmNr9Cervf_};VUR-fcgEd*CgV1h`uW9?d{1`h&5hh z=5+J>a&s%t5Fs#T!-X!XIRQLuTw!pjDQm@bWD@h$}!>&3t8M) zO@oNUy!lUcSc3sA;Y#Tjy>07#D5@h(Q(fsHT(;h)d|W2aMwr(w^vD|gN$$ss$EoTi z)Zd!%KSjHgM^klmGtXAbOYcNl4y)@)8o)YMyXEVr7$ zm6H_Afxi(fLYFabJFCO(B^ysl+5T$H%-siDO}ITb>fq`ckj)ktsV!lF>YvxoqLK93JfQkJuCo;a+K4r>VG>Dftd$#5Z^AX_CSYpSrcY|wPQDMYRlEVd+N7!=d~ zq)I;Kv16x;%bM!&j*EnWv+-pJ2NQUKR;{bch?hvnhCh&afew`X>WH_vV$P*sym|R^ z)=`mGhW-?CrRLh(uN)a3Sa_RB!-+7ojPf&vmncF+-fTX3*}%DgHr6_0VQP?ug@eT73u6ZIx!TpF$l{HhM)hH1 zfr>l1c@19X%#(&79(P#zQIa^O#FENh(ZN3Aky<6<%R4f=ORwBSqgkG8zW>ACSqHVb zu6sKaFIHM;aVYK-cPTCIP~4$7!QCskhvM!I1rnSB#i2lP8r(HF!C7CrWbbwMoO8at z=X`tSJ2UH#Ox{2ylX>#y$@4z>_Pt zCE_fFTS8irP>$|voJwXNcRlhdpUZg)iKoco#NEj*7>udLUcknpOy?8<|xbqinv^H0sH$ zCRQLRCa70yjF+ggnl?gU%k}Bf;v<4MN`bBMWR>xAh1bWZ_vLU-wtbUeh=+w?iOeyQ z0q|Wn-)ro+=4Z(5-_APDNFDL#+KMVYJ<5S-nXa_B8>fxzg4;q{#k_^49u4qEh861F zbyQBEs%ceUd?Q^{s6xpweSYpPKPG)8N21+kPS}XVa|5d+0L5js`sb#klR?2vFlbtO z#Prkqp;13)SuCD^Vm|vh|G7eABc!tf;IU>mNvjwi>P&TMM@L@ZI=zYVeWQN)l?cc) zR9YF_%73Bs5c2J-Xbn!^upoH{8JRoT4B@Ijw^G|o=79rvkEyT?A7dqs^T&X<1w+s* z^25MNWwxX~)p2(EQ044b;7@(L-54UJ6lU51^Klrn=`GmD(t#|q3iU> zDHhsuS*e|?HRw@~tOo+1ek0??qM(<^<=ihkR9!q`JnkWxD|?0%901a2J)-BeEg-o< zE}Y!B!CsNIIR}75!t(1lDap5N4#FnFvxRo|C@+uyqwa50Dk&%r!DB%Ix5 zdj!(=)=?~Ve$=SO%Gh{nWXg`oxtISt_fOJnG zK$O?vb3R=Nv@1$K(X;c<{UA{!*|CNyxkZyTHDXI4{ux}aOI`aVJ}T^^9FX=E%5p~H zuBh-?If>g0r=Qq(z<>?!WUT1};CoFORddQ0=Dku*K68uYa1M$ur*pwAX@c%3pJYfr z(}k&Z_NjDyN6*v0Y*B7%j#!|YMDAZ9X!{hAldUfEprL#eT%IXC4IkXwhtBUf-xsn& zWK(HTT{By)kh8zGq5T~jAym+AzyCH~+=|)Si}q|11h`Xj5fYC$$K=&9ZE;UxTE}0e zLd6sy>N_8Ho$ApjaedriORsuTGve5{6h6u zTcRTUBT;k<8+I`Y2VGgdkF2rgSJ z%uLFuofn|f7;=t7Q&H0yEw_somSG5MWd%KF9_)OlES*ZJ=ng;@Pnit$QUbajeqdWYO#MSa`b7MI28S$f7~L z1(VoyMXXX{7yXygV+8kl+$aB2I{v>?68@S0Y2s*TDls#z`zp)@!5W?>!8j>Z+tAyL zD;x=o=5)4Qct)q;GV&4jO0H8q(} z)=0>r&x52q7qO@J&)GODDq;C`X+!IL+XajUnN>}l%+5>MdL{(4^N z4;(z-N_XFug0a`D5cuniF30gRDMKSt_f(_dRZHKX>Xdmm^%fue#iknp_Pk>rc(PAh zMmWw4v?yLBVQV3aCelOBgo_K%u``_#Zwo8hby_gCvA#$PYG`hGB`jZeTc|0a3E&ut zk=;W;lk=mine5_tDivJ z!pr8z4?w3XGZ0GbS$%^FyHY97XX#u7j`7B++BAT*&Awj%WsNq0tF{ezY~NyPm2O7G z)#}67tp_w&AAaZ+7_|k!ct$Db7V~JK(xrqG9I5M4_9yYg0^0q^?}gVWHo?3c&-8YD zf@;%MrYN+8%{leBS&JR^pWjoX8~Bi{Rgh{;^2$B!y|$bLu7-C$<2xyrv_ML5Dd`0; z5TBh_Ruc|aa74I02U^)t7aRa1N8a==YB=B^+B}Vld`B&>ChxLmU%&62%)*j+lcrjd zs~bf1NQdmU3u3!N@(Tc7c)su{&3`Jfr#4?mS#_PyIl96hQCC*8a>ke`LR{yV+Z@oi zfu7t)M^Onk5exRCQzTA%Nsf3y7W6hMc?H-uVxE)QGH`Jcj|z$)Y?ET&Rb968@UtO9 z3i!1SjU27D-V1>J+Tn{cUJ|b&xArvzZfp7}3|F7ji93-1Gi!?$rwt8u{#A(!g_^B@_<_ttZc2)&Hm9nU}exN>fIUjlRj&cD$b=gfKTF| z%G=nP+TBpGaIRM+Mg{7P^E7}u;0TulI`S=!QQa5FBbQBtKXUOoA%@EAj0@Se!1FYih2-x)S}mHeLr|nO?%uSzVXrJGm?J{-iiddA_dpc z-AEp*+2pECYCVTx#p1h~_kkp1lMsD!iW!(t@Zd{a$q*g2F@iIs-yh6zaq*jw1)lFwc5S$4lh_K~W%%-( zf7GLG?1LKcDd4GcMqR8{>?#y^$;h^+uGxjVW2RgwBe!)|kD;NfYzzb3N?BbyKwZ=W zq|t-hE<`>bbZ7kSxMi&UNS7yXlS6HfUtik&Uh4E)y`9o!Ki#=Bq7Dl3}ZoWIS_z!d1zSvG8Q>a!(=a z#M+r7iSLRvzK&R6;7VeR5K_Eb4^4@i3lB|>UbI)t^yd=XF))Y;t}5^X`-8#;3w(k! zp7wMwO7!!7w?@`z8WS6%FQ8QjQ6@eQ z6qFw|yna0Il?u!Q>GD**mLa0cHhcGODJhT5<9=HjeodRl(B+u5DsZo{1jt$_4@nzm zS&-YWSgmi2ctD~b$tLKUHFVKLQA|^4;7gRxv^D$cVgDYHH_sa^kdxq&As)IE-O|>* zr2@WMJ4f;rMWU3HJ*W>zqC!2uT!OvZ@=~k|qF}^5mIZp)SAUEHu78$10ela|Bv%{y zuvwPjfIPpBq;9u*1x}@&fLDzBRnkzN+k9yH(nxe`7X^{R*J=N;U-)J`-xc0BM-p&! z+xKA!;<0jcT#C-*dH>}!4PqmyB_m_E#-a^*uP`J$q@7w{mO`FPd)sIaaCzZX$+BQ8 zOqzhKv-{)`(h_QUf9uUV1L<_^;{~XkohRyS)MrSpGJ|`RhmFM{*~G8_`9rMF_!o){TRPOX>$y|zLOlnZ0r*Z}f6Q7BpR)~|zoyEx zrSZ|G)(IRt?wjk*2R$ulQMNZ?g&t@plCn_Clo%uGgyXDGY)hiCld$_)KT~X6GNuWa zn}w|A7l7x+edeBT*Nc~QBc&y;ux&vLT#|!9ei09jVR5#0raRKOYB$%8c{dQ|Og#`t z{T{q@D8$T|*Lqr!TVfk;bE+%ZKT0?Ml~$7`29wowHc(HNS2JC&dE)kS9>&=1Fv6np z@ah%V*)zDWNQ$j&8x0o$f0i(jZHPDbEZsTMg+k7t5m*)=I+K#!g5&K64O@njY6YCE&Utx^9hyYQ+l)OL z#V8p+8-)PgFbML0I}j^hoQGs)BviI0eCj(`qjBCM?tUs*qrZo;=qhHj z6i&l}Rg5w=n@kcwUwTiPBWtqp!u9MTBQ3@b@5fNgq+>6{~)>V&mF9nRq?P7H@(nn%OfDPux0*^+{FdCPuW(P;zjZl+AQS zEV6c~ku7jC3 z0hwRA1TBTn=^Sq&LnI+jwAj9G-Kh6-EFkGqlQLOLB4Pn#QQ@gE)i*|h`>xLtNG6{>2I=} zm(muh^p2x!1^RN^=r>T7R4aTdy8E z0f{r`@|Y)c`ktrfR~|2}d-RRZPDBZHxI#4Iq+b@6ROUXN9{Wl>OC3B9Yl@w`D7EYJ z_!62I0S#WYf%^BXM|_KuersV=fCQ}-Utux;-hXR7y**^;A9NTQzPg$1UGhoqsTJ}< zMAW^NRvP2t|AzKmX7Qr0(52|$;>NxKZtk6J&$e;3H?u!Gmt8!Z{k3UVsaH#;@MD)` zAwLuQ9T3ubJCe25^K@(*=1-t_g7v2PL3dN{R0el4EVK3 zc3^-avB%N#=zQcd%Gb@#-8hAOkXFFa{#vUq;;H4-VK-I7t^C9{tjWGD^2>|4v}`;2 z>N|J7>r6T|=>=osqhA2&d{urj1VX^XZocthSD&(Jcu>$j#)ygmKq#%faM#Ipn#mQ3 zMnnX7k#9OByD#NTQU}#dkCsu&)>Oz#2RYJ$rASfVa1uR4SJY|vy%`RdAA+~psON=^%AmM(m}53k+9YEll~roS^~sJaO7a_#_HR7JqHAv6gVE(jf4l3L zMaU093y2e$*gecYZ7b{Y>y?+VX+~I361AJ{>5qvB{s8VGS@dHZagn z#3EuHBs?9Z4SscDkVGOW^X>HzA5;sY2WNlg-vO@ zUy_4s*8}${Tp7nrZ~%?sY$v-FV-h{=VjFQDwH*mR7stJfSY18oy?OJDPgU9h_#E9e z7x+Wf>t<>Wk?Z?Wdj^_SCwhAwP-s)2uOl0aJ*ZjaL6t!zvLb`NSW^LR+0(3_EEp%- zIW?RssT=Y>l6s1QhoAtGH1>?*r2yVvXKnS0;nV53sUlJkK}V|gPaky_0ye*Uo5`=m zys&E=b98XWpKg;+>$s&VzbN<<{B%1CeMhR zJnm>!JI>B?XQiB&uBd6u#mHaSZE_nG+?9#-YhJ9xiK%7a+M6PY}_4(IB9X|}(I zxSDJWS%@vJ^syj7T7SHw8jB%A?WL`za9AsoK79N1>qh;-2p$8`;dl$1^n~i9h*}X{ zqn&$g4alO&tAQ%7B z!ISAQej;c!#YX#qvNeWJt0x1X163*mKkyT&_?! zI8eO^Me-Cl>BbzP73ZgEH|}jgl;Ci{qEcrymW$6@7cJ&5ut->gIR}xW@T&DTMa1t4 z3+k)Qi!OaOw-vlLtXkrvqcX*;?CU(Y@$}Aw7?Iz7cpZqjx95JBE>>LZKcuS`1=4vR zuq+vHC@LccS^Cp%vWy76LC4XzcWcg&PZxv<#h3cZ6V<4b0rnscMp_d|e}Q}N$}(m; z`Ny{EdU*!a3($v~x0Ttm!_v z6f%@c*KD?EeDT_)=+(Pq1V1j{Qq)V@r{@>%<)B2(3(nx=l+GPsiO~?R^!%iX&QV|! z8@S5ms5x0ds8*n_|27keUZ9Vidluw;R_2l9Y@-(%R(0Se=s@M${|ytT#KYob@^Suz z;0OyCF?Us?Kn?V5v_YfR@b|mdc45o$9pnmSc|u8}zviLq6y#X=G_0)4;==kX}q$kMe7& zr2HbUcR62zmU_PvHcZJ2f+QTzfJD$NTL*>RhzWLnawJIaIC!_e#0e>rZ!phi4+D0oP-G&rpqPMUSA?z5I!lU)Em%h&RGu=5vk_C3ie;WKWIk8LUFBF@>)_R>j}fxxZQM9)C~AhL#H(;gsQQemaF=QPPJUtD^y^~`>Z z0V>U*Uss8EzZT*L?yExHB|@B*iS0_Z929;Yw$UCVX(Sse@q~;Ius$6d=@xCSIspU^ z69Yj*qz?ESZ&^PONl1uLxEg8_AdOnftzy|wL)s?JT7Y7V@El0u5W5fnV@IdX`kp0_ zK%s)SD$zxQ$vQ!K#Y9E*!QI;YjHeVpZDLL}K}Dmi3rIe#y#6kdp1T*5B2hsD60tkI zIxR(Ea12%k^lH9CKjQ^2u(0n{0*t|7FD+1>M`EmL4jjIVNK2=@hFm{%2M`Wkrb16P zi5^d=;n{Gc)b_olk3RXbjy!WpIHjgHR=U42Y{vX5OQblP%ZMxS#nN&VmiIE?PoZNT02}P(4ox_S!`1p1fbJUwi~BY!rlClMSu;gS~E_ZsG_{7;J%!BCBTszQTq6)JYQMqtzgcR zxWMohG7s@&L>G_VaW;Kb@f{$M4I1Zr@6HQyW*9-)D!FXI_{7O}sB$t*v#F|)VV}9} z#p6)Ml>TU}EM*~F-^nwrhclC7u-rji#)c#6E^jN3RcBgDBGs#p!h8a-=~9(KTf2fq zLjyf@g|DbnY5a%kgaAgZokk>(@McQ{OQqR*x{br(U0~{mt|E}5g?ZL7`TR32WMw-; zNnLhAI?eaUamZ+ZgpLjGvx)(ry8=)i$K?d`LWysnvQqh!;5iYaz)c?mL%l@Rcto04 zwiU%2@H8U)WT<#vaBS0WIAbQ%Doqf0wr8ggo~VS)xivWLTl#ka0#M*ELpA~}URz%| zSH0d(D+8nkh)afVb$BmjloSkEqjIZV3ZmZH8zn;651HVMR#1;p0hDXYOeq_6zmv_g zTa1t1=H?@ZBEp_``Nh4>(%BBQRx1`suXnQ3i$rTQFnEdCS$RFi#mB&78?4M9WDaAP9ffpU1S2s26jK=$xE+ zgFqWQbIwX#ON&cHfnY{R5b~bSqcKS!99j5H}>?BJ1&xi$PDe}MlO+OA5wa?vS3xLa^07@sZG|NeXC%DL%)Gs2yXuZInoTk92LqKZJw#5nRK9e z|4r;FOF39Ovpt6Mawcb&t%5(?p1n2t0akf=|FxS0lHwD&bJz8+f@LXYv5yV!RR3ZG{hVRQ52Wa6B+ARBR=nuw6y41!OPe^Yf zBYhn?2lE?+C9b@o-aTfQxPzlN4t9HUHDXm3nN-2goUwC~KE()~QEZ(Eh7LM)skBjV z-+}z}0{i+7Mh}|$hIfXw`p>IfY8o0(4xtLfiR;02EsEjTAK@LYtv6(NJ}Z76bdVZw z_`V`0OWjjnjAe5$E|Ql0-9g|(f+}1F5_mE`RLTv0QVFim5|k&el2OHb74g!}X*$}2 z>eC!c7}O-x#NNtAlsjf>U-hc~m^Zp@xPWi$2lbqOWxnF{cx}j{PA*Oc=;dCY-(+WW z#`iFGvm1;hM2}39x#GAe$9|>qC~OmRWP+y9L9b+^PaDzmD>NQr@8qg3Jj1Duds;m% zIE@F7UXRkXW!M(|Na0*_KsRc$%S}3b(=d6fbeHcgmTgWz`(s|}K{;)JB|rOjERS8A zQ>;%X+$bGyyBLw1Ua8H1=Zy;zFtqhsQVYH-=KYxbnCKMfr*eUyl}m2&J|56luo0-e zq588O{@)(|#~A55^7a;uAJ+Vy8U_`!kce4IAzc{^8AqR2HOW%wrJbW~1l|8LhLIMZ zCYP1Vlj5A?$Ljszu1)>YZtP8OQ7JLyuaB*7M2r!Z2*T);fqS*LT&IbRKD!9iP*;<{ zzx!1biLL9oTbi8wq>2*wCwY#SjsWSe7x-%o{yGml&;J^O|1D$i=x=Hq%}+JXo?m{b zc~9cm`0r|5;cs)HnE1Kf&+O;OKl^coc|p{_{hRVPo7g%BgMw-xd>^ku^%|D$Si;e z*C5P}PL$i;*0g%<9-q}=3mRLle%6Q-GuNA%hN3r40mW%b1~#*2N(}n-**%Z+Il`Z3 zLOs;%dE$v3+Bs5V#J)`Rd8t`AlB=u_5m-H=OVd#-Z@`HMKT@GMPb|Dl))-rF1`Vw0 zvg^CHye2B$N*q;b4V14evb|`Q&WGQ~0h*wDZ8M&WL=1bwPqDH>(JJ%j3d&KSZgyPu zaSWlBNHgDW=Oem~!y6){KKsh@OrY-dzy54945YsD_1XyUT-bru2CncQ^WUL4h|?i< zyi3cyLN#WnAdzZ~r}y6sdN(8-(}@Sj1GWni(8gvjCHMJ1Ru_F~cD%fc_8YKDRlyA6 zmr2?da=T+O>pdAee9R&|VxE{i&-kMw2oWA0sQ}D4qpA+0A|45ZtQb>p(vd-&*jQouS_`GxjKHTgF}+6q7g> z_|K z`og|8{g{ugA`((n$Qs%y|EE#VPv!#45FyZMxqs9z5oypl$q3aY_a9Uja8;=V`NpTOcHZ2O4jKW0!?SXpe*#cdubl!q z9vlKqEV+Kj(xeb}U`u$d-l#KEc6?zExkymPy)|*|? zVL4H?+9)Le3{4bUE4j5D?%uHjvUR7PtV+V(B?NJK@l^4JCw`(6r^`t*% zc0Rz-Lj>7`V3qq;bMIf^D{TnIsIYa}J5MPKQOFST{%acq+QKE51vVFl)^Ls{2dXe( zF+z~y?Hb^WSz5GA(9fKJFAX?3{dJLauP9h=)0Cn=WNkAeW*HY(>}WGc$dV8#fDVRB`!O=R+?B&)aq(zj2Y|;kR)TyWhT%eP~8Nx~|T( z2ST8Lwl4n5~E-d@_NdBr5G&SZ$yerL!>=My2 zbE|8b16H7|Klz-hzWUrLPe(0u>Bm%aj3}-xX*Mop*?;?qt_9o5demWwKk?gTI zN9QUr+)r;PVP~s z00W)RHSQfFa#h}E;H_ct{DPE25){-L^XOS^{F^7cvddcM|M06kt9Md7m4o~aS6*Bx1?;j}8pdZ3_^P=qAAa_%!JFh$*iGjhWGm03|)S|u>CRZ#A zWA_83t2+!Hq-ix>J>2>;&W7|c;AfY z#mIo$nsDcwZ5$@>&#}Jyen-7#Ns8@zWH8FsmK9xLpoID0_0u`|Clem4oR`x@k!41< zk+gL?(N<_k!BDq^Z|H(I1@B^n5xK$TQf5P|0;bc4_C_>tUs5&E;eJ8<8gXVIGHv2e zpt2p^J@xibd6xqyw9YFvYnf$}pPZm-@uO!B?$?O!#$)AF%FyCz)AZqnSmqC?iZMb| zC|0z`Z+H&Lbr<>~%du{B^C)-pE9d*{X9sXEiEbr+<|411Em3y*ge7cW7icSfv5F_G z8+`qC#h3~guZr`)?v?tndsT7?784kzE=L55>aqS-o7ocf>h?8m;~5XqcQu2=nV7Zu zXD)$eyBw(bWlHS$9(4c-s?UN~p|(@wyuSco3O6lGZa3*HkrvW!8M*!TYot2Ys%Slg z?|fI~fIs14C5n@Ogo`ipRyg)69o%_W`jsm+7G4PBPj3O2*H<=PT zJ*BTFxc4>QW%!H?3iyQN5-~jP4&yeEBUNsZ zi}HF*kMVX?@dIKTtgPHtjQu+}y%*d%iO*o*D5V8VU3cg}v^(6306>2gX~F6`Tkq&Y zUV|7&6Th#&I7e}>*!u!TD*mm&#P|Esm@%*R(EUc3w5TDKJ+cHP1-1|>wrp1R=+i=8 zm103&)sIps7x=x<1Vd{QnZjq_i7t($&EN6a>y)^TIy?^IQ?s{wJMp9P<3$veyxu)| zrg|A?ksN9|{1o(0$K+Uc^nzkuD2PoWBe%1?)`Q*kN5jsv@da?ctZwpLsrX^TVJf>* zY`y_3w>_|2-+-t^L@fqcH7}yK{+O`hKf_nGNnAj!YFruSO?6VP9$&cXeRb$sYg-}S z>9!w`YuB@rae{EA@d)$%D`m`GOzg;|%>cs75btN%&f2WJIzx$l>V&pHLvH1W&c~LBKuBs>un%RivPs|#1X*G|^F>hJ@2{eI{=R7c>)e|X8 zSsE^`YIOiimmjEP{)`?pj~KOI07svqfcHZ!H!|7lSHwy`ezc4G63rc|G#*QVeT0pr zo`}4kVsA|nR_+xb7NE|D$~3i4u^6%&4ntW;HI5(b%nV!C^YgRE`R78}8s7{M3(}0I zyRHhXPS{sHuTQcopVDdoqoA8eyZ9_4O-^iuC6ScN6*e_UsgIuv@Y)eH1+D$goauP* zdZgKu=QBz5G!D5T7E)Z2|Ai6y;7@;lScgch?7Kw?~HSBJ+Bb+6Er)wq^KW6Ec`2H7WCpa z5JgLmKHDEiBE=iLPLGq1g1uY<;7sheTJ}S&6fXg)8ysTIy(s32MYo3{kA2@4ANuZUYT@ z%`P<*8pr(j?Myw)xuse>lYSWKWHnMiApa#a_H*RPJR{wQ%5f~ecJBuMc=|;8+r^@6 zf@@3|{{!?Y+o|Z0dV~bX0WV7Q7Xkqt751Zw$%Y_K7+b~ULYkEh}jl3`%o@K zbNJhwjJxFy$|5|%(du{AZ;uvh>Q|X(?m;u^Uuzn{dD-_rjA8W3lHb{>&&f1L_Fkm55Zw>4rAah8raK7= z5+QWU%<%)7FUMjv)!T7kJ=>kiXW1M3y2U7uIuXpLwDaxmQfTop;Z|s}Vf*we7Cm9Q zTKyc9Ag6uj85#jHZ9{*od7FzDGSMfm`uo zEiTXHiLe)w13JmJvTa#gIZO0oF%Dk@b{D>VCg3`<4&^&Wkc*Qok)X3x)fO2yqbTG1ob@0tfYK-%a zqSO+ezV)#eVBYq7Cr;u#NQo&9h+WA-bQ%k6tP&e1B|c+R?~_ZDPS)0Z9D0(p!QZcm ze;Oa$Ct}tDqlT~c$u>@$X9{TnIW=F$ziMNrL0^B1`~}dD2-Y{)NQ}vK$4Qg3aK?Ut zbtjQ(PE`}1X>NS+d9LQ{Jja4#KiuM&0M4mM}VIGhx{hsR)`aBr|n*P>}*Z~50c%yBS-;NORYxBTQTjyZh8(0mC!{Qw%&3(TB579 zm>zRh&c1JWWUKEoLh}9XY}T?LVV>iVOr}zGOac{q+Fi0eu{m|>g`zWjaMo4IF8#@~ zTxgQ|!IdB<%?2mDqvMVqAEu*&DxK_0`NNJ;6?*Zb3S(?*Au!aSqWSJF=b39Pt7OLg z(d~T9T_6cycA}^$as{3MSCFeJ@Wpsy|G2^-r&r9RFX*RrYedP_lQ)y*>(t;X!=48U zTT{n011zrA~G%;CfkcG#XkwVw_JAdW4GER17%$}a}_lz zRI%0)e2<+tWB1ZvTknNaD2U@k9QbOpR%;Pp1eOideG8g@`ZmtLljgyboxamy=b2(7 zP3oP&q0(U4Nf%{~SGG;nVJNXEOUpq$xmej6%t+TW3IFxCT6MQhh_-y0{*M4Ye^%FShFzc=s%rL&5 zLwr|d@1VEyRln-G?rG9#7mL)>=Z4ZfniNuydbzmA=20%UaM}!i=EA}}8==s!YIZld zs^>o`NYu}NP>{m_g`=~Oad$5EfJxk9F^08^cF)bV7@uQ9cUL1!aAW;=HC-dvR|R6M z5Zfys%4*m<3f*z;taG+6{T zIn4hPo1Fa(n+)(GK-wbVg?&7hv*HgYnR#XAsZaRQ)upf0oMavOK#oc~aCyODLVZGS z5X*Xhv-S$7nF*_b!LG_lKErdfE?4U}+!FpVvS`lWm9smK6t1i$3f~Jk8i?^YD}lMcc2O=LzO=@ZUL4%0mZ{8RSA8gGjyw^Q!ex&fzvl)2o}_Z9|2Cz)%8=v`&cO zt2gnijzvJ}MaGO5&F?L&6?3>8G>JM;*2JFY!$G#QjML(!j z7#5$U@^bNAhIoYi!E=(c84sZ{o(ueD1+2h)a}3-AX=N9rzC!n`M|D|jo?11h*Jsdz%jN_2hnHrB&IhP3*+IC_PaO*jyf4W%MG7^vcj`d+U`6@$qCqxZ zeR0epDt6_k@LT12HCv_D#=2$RaYr*!|W*+0oB%s~v0wHzhgT-);w6dQz zc*Ldj_FAr^nJF)diWgehE;3ExAmXHx! zx`h2+*|0bRNe9Q*NuJ!^Ho*4%ZM6B@11{OMS#4v3>TttqcGGukypQ0Z@TWQz-D6+0 z=an?LnfN7d+6{JWzTVn*dpJ3eivt#`yH*=HP1g!Nx{e9 zWy8|L320E$u@-+=0#jh9~}5% zz2Y{0Hd-+7G)vPmVZ(;#7eKip`S5v1-CasXq9LD(4Hw)kobep{q0r5;9BKb0&dB2%e=a~<# z?eXzNT_V~ZAU(rQ4;ofBvu515ry|)@>oqh*vVCpt*CFMBjwO0JP~9$(Q_1oAEBSZe zASdTT9glw?iqor#j1K?;;r^k#rDf3Ft!}<#Aqy~TyuL^Pu=`IyF{GN=otYNup%U1o z>Ci6TA0hAbq1HDa!v-4i>H6(;!P6}ja9n5_Ts_vQSYjHfM#) zPiZ*kcWJots~!K?Xdd5ARPi(I@vn~s#)1ZW+q?a5G~2LXKCcII=jXUP-bF*^?M`al zyRKi1u4(8wxMh{657l4X+~oS8k^mIsj@1PbHhef@IBx?As@!r9`K0OJz+>Ingxx ztk*owg)Oq4_L4dEXg>FZgErcf789l*;KRjLsD5vlA$QfPo>?1b79M4=o0VZ>(pR|V zI7c3cNFi^CLZo*ejfGx`{=VzgMBb-xAdp0G5#u=<59oj`YKv&zU-*ss*nmp8ew&BC zwxM>s>-2ovlbxOUvPG%r#p2?ZHuf_Uwv22a<5^H;G-=nqqdJbXl&r~`>#Rw=RtqY7 zf&N{aWV(5{sO$@E(`UItck8Ti{H7H}zXHltM*{>Qtx`bRRiIa&6F3fiG434oWCX8q zM|br+O3&tErV?_+5n{TF3=SiQ=JNH+ZaWUto_G0LjYBjSAV1E3M}J?Xkh1!ftO2mCst%?Ir?Qh* z`q_fp_H4C<+@9X6cgwTmdJ8O{k0`n5?wyME2o$5*`H5bO`kb+PHkIyN@ZU2h2{_RH$_Z;m zy`cGKUoCo7(I!0tpHOLmfJhr2OR`p&h7kjzF}l78U@!RiOeu-##!xteX#$`=a{)Jj zde2(E}RrNJzd%}C7MrJx~QAg!*hY4gks8o28 zh;+NzstDV`zU0VkQH5gvXSe+Q2yDA9h1+TJnyr`lUC4< zF8tR!9a1cW+=>GK4Z|w|wog%BL@TLtrB37xJV*3|;K}}h02D;u-tNK(4p2FZrQ#G? z@FZ3(D|Bm(k|FYLaA}zF7aIci!(e*U6MppiSyP17HFSGWSm$$~IGv z2c9WAhg+llnd-Ii z!JW7rmm}joR*3#^B#dNdC=*FcWC)a&rnVH3i_ZMYQ2-@{4&Y9QBlF+x$^Mr+;{Pvp zz$>w3w-wlx*A@$Y1F>WWtV{lkU|B!VWBv~a7NRNje?YK;=<@RZ%y8vk{`CTXjX`_q zUt{ps82s#m^1tCch;P=in9*yUJ~l@*aj0X@i4{k5?m(*ktvoN8bnI<+0w*8-jrIR) zLOk64|8Wc={=ORcJIwm$eohWHi%e5Ia|Gb}h~Yd*r?+)-qzT!r(zZ*t^w&$bM-zxD zyfNjahFi3L54_plX-D1m!B5Z?-{M!$^$>p1jd!(I_6uO?!#yD#QFB9>JGt49=PeOG z%w^`WwaW2FL?tSG7H4=lo-9J8)8-Z-KdIJO+k?J|Di*Y~Cmh>>=JyLV_uql_0WPUA ztBr_V4n*5GqX`C(Z=^!W(_PtuRF7W(1%?8%#-!mk594FJiK@vaHtIsI1vy|@o3mDa za`a#4okyqJSYCgrZyBH7QyD*4otR8HsMu#6Yp9{@UNniXi4W-@hD{f}3J*|7$$Kvx z{l@U64GU@`p1ao<9s6@J2T^q8^Wj^un(^L>ix6kJ9dFR!546>H+G3`o4alOu05~1H zXVUmGvH74G#?XWsQeYJU+f;>2j!k@wEIHD^wYKo`(&A+|BxcAuN+VHsjXOBjW-tze z)wzf6^Ws*a&fL7WCyXv?_eAo?Qqk8CNnfWeZ@2)(`Pa+Ck@}xfQxp?IY6A5#62Xvz z)Y8R$v%l7xPJtuc5>1j-qAis`C`bDpLf4e(@j3yVe8<-Hcy?%MCT-rFv_dxZ@qTTs zF5SxqXE4cmiaraxOvfiWa|Td^;tir}Yt{u118EpdHXPP7!4Vt`Pah=_hRcxcu-N<3?rVT-NrZP`dO@lr%eIaxqg&Mvf@UDOj@ zm9p}5n0dU(*q!_=3e!Y8pMCLeN5}I;-Kvhr&-MTCirCuq!+8R4>PD!QAZq>3{nN4#R@PmcswEx52TgOG!FZ%w2qyj1mNP~2DH!3aN z45j2SbTa%^GefK^4?0bH%-#PcS|G+g&35&JX zto8lAKkpCF?tuBo8v8`wQq|ACaY!9B3XhZ3ZelhtEw~>eow@<_4pdk5 z4yBj(X3#c+c9n(_r2nOQ2P=vo<%|x>)y)f7DNye)-D?NbJ22>+41MN(B;Y=#NhL-0 zR_qf+C17PGYaF%M+{`AUq*$hxHx{&;J@={zFedqTyTh+h>;DeR{}JsDaX;D}a=;(2 z@&k$2`2p{F>RA11fQF;^~k$vmKGr!|edOA&JYwwSi3)ZKYIzTX@d0vf6|L&UGG;XOm4~h5WoA)#C zP)(zIL=E_$({OzrF#d^p!9M_F=Y>!~AfU?Y2Rg2ydv&nUsJo zb}mrmARvBK$|0g&YU!_R{Ma=cFK&^P*a9>;U=4f+eRRBH-;1dwFWAF?VeBH0 zh#t*^2s;RET5An(rTqVUl|zg(hjHo)8B?M-=S0u%AmR0s@1TR#VUfkj<}a7NMZ-7z zW~N&M;*f79*qC1^j{vK5()-J0K+(W8OqCYodpc@ez|2G-O`)}D*4<(A8LdNX!|X<7 zRek2{S|p@uytLQ(Msx&c7YqTkH=IjkQZO?M*3|BDbmkXBGGw9*@nHxZ;_McpSO8CI zekl16$NDjJrFSWEB-vi~c4exTc`s)B8fUk8(cnk$k#XQzPvfUf{DTy9m{%$^PfOC( zm^FI#>4ptj-)(^ldh}lVrzK6*Wwi~V0{H>x*t%M;;UC}!T#?_-E}z8TIfDQt6qQCU zVUJ3O0D@r)+qAxJEFF>^UM*n6H|2nYXGnTg8@8*0>WX8i$55jhfa8r|G(I^=!j9Zbf1qZ727?0fL z0o~>!S%@t#i*{RL74smT3sRyBWJ7-l@*yOa z=7kD)*gD^ayg5u8HaDXdujfAooy8Y5JrvLV79LZ8PUzonc2z9Pv=)TtBLCr=G56eL|dktBcyp*2fKp zf@BoCi7kjwj(rVkTpe%x2J}3aH=BHM_9si#p zBdO@$AtRh0kdcqTSu(EPB&^rbcHUE&_t|60P;JsE(Jn!eOfz#5ijtv?f~}(SxoQ_I zatYnn4E1;ubiW)34^1z$iR)7gutE@16Yfu`N^3MxX-ytewM zoGBs!2*?`?PTUYZFhu7{>tFka)}P46UUBAlO8S*XX=!z1Ng~bkunu8`>I>1uBr(cw zxV4rtr(?sNBxLv3w1rY309eHIcVJPz8C$*Jk|fh>2$*s%-)fF@ele7`grw0i7d!>Y zR_yM#uGE#Qi2o-FhXfa|EG)ueMcf!kN%yCIq}4GC#Z%Ka!UksD+jD?3$eX>k1aQTShU;S}$#LkxD@}w!?cVcb-)5ScdeDsKcST z`BL);?)W%j!Wp5+)*4B0=WB>)pkmAf9CpB9pWgu|V@UAde$hX#=l@&rb7uaRL=Ksx zZ`6munE6{$h~K)3BqewB(y0qEc&y6B1$~85K@-v+Iz)<~Nk#ODbUCt4#{8u(-|4H= z=fMI}p_voi?(Vcfvy2byZgxl^zUWt`@3q&zdz0j5a|^7+bjvt zN#ya9=&f46e(?9 z(73zDhQBBBix)~HU&FcLh3qW-bW-m>zq21UQ{4M`F|59mND(!~j2{NAvX`$ahgEP? z+`*o5M$s`%rD!xCr?}>UxF3j^qpG}reSEP!b5gUI)S#jJuZ`3G9#r_>-TsvxDR25c zJu-UQz9V-~8TyJs*StToAQ;PvLa{%oUiAtE+DAwx4SiUfq{+Ci`+UJn>K<7YnqpFX zHC9+hrGu{Wo~kre@>6ab13aB+$|eK8{+UmBi?!=|`ssQT3WSrr3zAg>T>^zNIoE3c z5Ick;%C`*7->j-3xsXCbsa6|kI=*j_F?5WOyY(F;E7355+&BYs-K4EKk;$7^1vNAC zb?Uo;wwMJ~vc%`%2k*1?48rJrd;_FWpMZjwlK9oV5*OUY|=5d(yc4QP}4BENN*Q({<#(pL$Wta|8tF&)Tp|1G(6TQe&tLe z+wy+BgiNl1BFVIACCJImx(&@5>z*f}YS3m(&n|hDt3tFq&Ms)~^rzV$3<1pkG4i97 z;h_^f>cQP~Q#CI|+Fy*51k|jfj5-o4KPhdFJwSI!v*~t5`ZS0yYQ&hs=5w>dQwVC^ zZnuuUkcbA>*5+qwjeov(SGOT+nlKcFW0(`ce7zH5QEi9$K*`-55c>l&qd=eeG^y?F@|GhjPbePq~D1 zZgMZo(nvoH=aQ|x)8pie(;;w_az{BWi0;=!5kmOS)DFwGI$x|a+Q(?irVNmca8p3> zq&{qo+jdr~FB1HTz3d@SL|3@KsihGP5hnChXydVJSwUYepASPsxa)qZ!L+2e3Sf_w z`PpF`WqK8n8Hksflm#GtL%(B1R3+5la}oO-blOT%_9ysl#ZL{P+67H0#0}R zinRxHNLshh9iO{{_-Nod9nG0qo!=TahbUF6E3_!cJjX%AA5K?963wR|ho_ZQuL{1D za~@VLsC6Om@MDyc%rw&8SdJ`)$1O;~9AQ1rKZLWYMGCRs5xLAO%sFm;G*nCg*!`a* zvNft{9hxS`gMeS9h=Bso`xoP{5&T8(|18+F83(FNpm2rxXj9k3E5-);Upm)B0W)6i z-t-{&J+mS*>C|w_*BxISECNVULMs!U$IA8tUbQ6MDtQC0m+~kreZS<>BR$oby1KFmvt85cyXSVtL zaz)VD6~?o<^~~oLfbqzQIy))tVH6irWa_%pF4C<`bpF72q0bI2LuNUJ5t@bR(o0%YY6yuMW`^sbqf9RS5^hoq1XFEJWfOY(3RUQ4l#UWC$y}<7 zHY6)#x8i>RJ5+xM?Dz+?pTEJ!6#{^rgI~Z-(X=oL7ui>4pfY9FUcHc3=F@7ShoRMB z)$Z)XEUcloQtZX#O`5N*28iK)?GSw^GOE(O8VaL(QikS9cAH zxvAZ7Z zGMOW5=m2TdVZz!lWRMEU-@^#tEZ{&ESgGtIKyRr-o+>5tKa55S6|)GdbLC9J36*x} z&e_~%p{SN{ArCc6$3!=cKD>#~a`Sn%m{7FK`fd;D{fNtcy{j9fhG z0Ea#6&L7vA*ii*`buzvzgt4i~mHKl%FDi@;1mKxq%O7cszC@!y8&!z8A?} z5-6xA8%5^0%y@WEEbUJ~OA+!FqNR#R0YWEL31uKM##64QubzbjX#BSi#h0yKM>QF6`wAa52{H6XR)7UoTjVpIpH_%{2i;U4 z6e-)f99%gOmROoejNePVvaWk}1~DxT&Ysf7E`b4MI^O09piG|&T9%tRI-IoLXkGR! zsg7AG)-N}-@=E6RzE#-xrFC4`NKbEuU`AsZ)$a9e!YSdX{!QcJo`W%z$gh^(EPC5| z_1+o+atdvT@=Z|jlA2nh>a)ic;-Y^Fvt|2^Nf#BXY0nPaC4Pb5weEweqS-{N6|d2J z*Z0c~g97XAED_#q#4lFn(FJ2w$&e9;NiLTyEgq)McTfKir>n_iM4G6UyvxReLuV1C$YFRL+V8S_8s^-lWF5TTsZ4#XCJkn8v?+JJbM~#h@ zM4E5RwGD^xhq6sv(KHGFJ9_4?_x(?&X@1Ye~%52HcWC*%^nl*gjh=o|5Rl)1;hFl#F>C4 zVAF!R$Hc7KYIh>)>+3bqgDjUYsoGJaA%ckxBhhlkb!L{O*r_SB7!EraG0av zg08pX`}QUM2I{*7vY3HlpE`+>-DcB#ehrWO-LmCdRhVPCSZ?NEV0_{u==<|3nk5TE zKExyjw;)j4j#Z?6;jtT(@G)NO4B8&vi`E;ipi}jsU|Q4?z+1yQE>%my8>!jjZ45=O zMzsCXz-RRy?zawpr}QshB#=1fYpvD2dP7q`P|?m@%GD5I&i%P06)EwPTlxJjsMY2U z>I5Ofjiw%|sj1+w^qu?iW7>WX>Vvhs&MPH6>%5aIK1VwR_^X z_iKVl!{6RMMx-bu^|yCY=l37shA>67v3{sNeZiiJ94Fxz;yv4H)j2%Y$P9RhZ#uZV zdP(8%Eo4{kB0_N18kNbv+j1t!mABI?YSJ9nEg*HllZ&YpoEa4ykvZI6`=t0KBJn4D z-lD1?(B3wVS==s=1o}FXQm;F>Ok04X)$G#P(ogJtYt>{Ro^EoNM=W~+Y!YYA$4tz@;JkB6A?aN6wylm3V^LT)ya@9c*^+yP& zeFzSOa9mHAGJb?`kbi}6u&=rTuD_7%TZwz_V0`QRH*j0q4c4Xx`LQ}ZK91YDCJyGTj^tivKNsBY2q^`6= zAcJSc^@7JQV?_3EnHa*WOw4jZ@Fm~ySB2Zs868!T0m3>zGck@cfEvFeEUU}?TJde+ zoBye5tc(4|Q`=Deq_)VgOx21CT^hw5oUa|Px!PD<@n4WtYnbRWiO~xo^g+w64ByDw z*M{$DZJ}&faaK*}%?D6&HoQ-p!nG5c4BZ`-^1vo6)r6)(;2QO8@_Vz!U$yrX=Zhh||A89M4MRW{<#e3z?n1Lcz1 zr?4tVbWaVTKZrZCuZNNRdvrU-&KC@Y*HR!;N7SU&*xq`_y%}x1#$E1K{`GqOw5*@)3IA;gW@_ z^sZCKh*tZ>rxOY2#0N$S6ML_N7R4b(+QJ1F3Mfny!p?QBGRc+O|NXlE4h zZ~%$oSKfiUG#3Ko9l{P(OFNkFNo%2#b&Mb(?k3sm$^nA!RomkLm{ei0MMb=)Fz;bb zMfkPgyMy7LC1HEW!t2UNlyJN5cNJP$k#}iI(2v6Gb!V^JJ-zg9o* z3f}Q`g{xM|x@>KlR=qQ!TQo~>yUHR!jjt=sLCui6zMs*={>UKw(k?JW?=WzE?O~v8Ph{h1v3zJ*i*43pp~z0F zXVCS?uN7;Oa(*T5-vkL4~cmvn!;V7R0*Q* zM?F5AAE=YMME2Te=vQUt=ujo4V%zsNBKUfQ`|wSYhpp)Oi}OCOrJ|!Y_dr zJhD7p)AnqgG{4u0bT*Af^9he4WS8|)ZFWlGFy0})J3?qtfJ(POIK5Im zuJWPtxXtf~I#nq9-w<`Zpyi0V(qVazNEO}N#Cj6rrX#}Lc8t-|#N(^FWKPN?H?3v1zANH zsdRkCRUZU@WBUUW4{4)c;#lgWMUX-qcmZ%2v}qMGolG*JRvW;XtI_}Q=>BsU^WO^U z|Gc{SpVgE7cYogB6x7@Q%@x!z>mWznD+RS-rJ3TDg8Fe+zcPn<^E}VE_ex0ECHmF* zCd6Fmw$2qU4kiH5E+)OnhYg`KKhQ4xYqSdqhpOVJM^XtNkK0{~ zte?<1R!2v}Yqcgx3t2`cZ38Lai2PKL{D3;sFzt~w`M3FiZ()oRkGh#r1p?-T^(K$7 zsfn@y#WWjC-04q>X%9svX6@c$&tp8dsU2!xc_|kLt(KFi@fMoi44C{#k z7AVr^<~bc4yNrlZnT!0rkxKn z2dlt=^Y3!mUIAd#7juA&(!C<1!XY?C9&lqKy8WX}+lkL5qkh1t7l`z4!PY|Gnd(SG zf0syCC?e_qE|F%!MtJbMg<4h|B>pE0^`I!$zu(~B>p=P6+kwiz*8yOq{~xg(po81P zYER>O>UO>_r&rc~X{Z1F2JILBrRyM@oL+-p1!;^oZ#Qf`QVXiq=fpcBR*CD#;e4*A)2nV1@Rd_0gLThxf`+_C=42rByhd1a$ z@_>d%+0$`?VcKs8?M0amx)EF7(&y!Glptnl@E#TO4m&b5QeO&8;d|rIqwr!a=H2dWG&n|AjF%rLZC%I7w{{Ia zQX=k946hnR&6*BguBpF}Sy91FTgpcVJ5;?fUqnj>k*aLVX0ADF3!UmsmKCfPq?B#p z8Hg>eLhM$FV2P*!TY}86=t!(#E<`t@*Upun-}l54ZFW9A%s&1I%+S}3RvL51y)lQ_ z?A%`=E{I6cn?80y3hPj=-@)>qDc-*6vG!Fk4Y2nX)hz=}sS* z&`@5QBvzuYy4`un9MwSK$#l?-bvQBZQPy(@O%y+jX}DTpsB*(<1GYn6URTWnF!Qaw zF0G8W_McTZyX_@%w8d408B-M{J6JA8h*7ZTOiSUdxvSMQI4+oFN{duxdS(z8<%u0q zU?+&NIk=;rcql(Vv!fgSdIOSGGl67VgLFe)YSD)wt#-u1@?0)g59ZRe_RyxiT3eg* zb4uw$c9%JWop#rYwth!@rnVY(nN5nftnBg%Yvz}+3&dav|ApaVy;&a1p1dGCH`BL} ziknGc3!ZAqgf8GV*vlK1LWG|~+iH>@HaUrW1g8?0>dEkHJO*aJ#$WH=Ic%sU-R~2* zq^{kSWqWQX-IdCK=zK4THjnbJvpfIjdqpWSUolj&(9zu7W8WjS^6IJtpSNM}bNSxx zbi41Ij;Ue$053K8zbhmW`dO$%Xni1gv8bXNOq+Mp*`8Y)Pc_T73owxmH>_`;9O(mz z>f#@|>6sp0NUCCNCn|7{2K*76=t;=<+~wMN`% z=e4~ODxC007t)z&6z>a1fEV~V4)70`H~?j_!3kBe&(X=i!i8m)$&!kqQeMzAQRoeG zeOj^3_gG=Z_J=7jeJx5B#$98ozwmV)cz&YLU4uY9{!OIcPks=A?;C zJ1gB1TibI#x`?pv-P9)nc2qpwX4W76=b-%ynFA)WpaUb1xo-2-28>-PfW-aGkUV}4 z1_aRNyHhd?#p|i2|O?CSLH=Yh%!Hx1G#KAc)Wi2TmBl*b79PAUH zDx&I&8%!NneO_K;a4a7g&9Hd^2u2hYaw%Sb{~GvKAK^mRrSAYwO+HcIF{pnl&n`-I z`wsy$a~L3ihSk;tXgTSKMEw8=J$?fS^#Ooz`x+ob2LM9Bs2e`qs|A<}Z9|&tlCo8U z+tw>!#~MQ`MPzjorK9)GDyk_vi8CWdtYY(?N?)sNB57T`B*^aG>0cE~xm_0YdBCx9 z++sP=(xlSN6zWPIPw2T2vCZsGs*V``WxYP$5aOYQ>eZ#S!Pqc`bD75VSDfttnbN{<&9VwZjU zpNwu%zkETCZsUJ*mCzRN9I7Ec%EI*|0vy5$6Z3gyZxeCimvGVZha*~cf%iG!h}ORU z(-BR1V$u0kF2yLK*19_sN_R;PLCeljIuu+8bUMW-Eo>_^S4Ka)jH#OmcIpj&+xsG{?G|WlwMam2=bR_- zwQxwDq*M3u2^N^Mxt`|M$%nt8aqufNPVO3wgE1)ohQ|5u6EK9=?F>yZEu}vhA(tVTsNN5yedKTqX%f*S|j_>1}N3nWCrlrncez*9gt`RxKhQ+xAg>`1yZ7R4@Ri z7s6p_@+JCujP~qXSa~r9zX50F+)BTIGdf^M2msEmJkfZ9komI^F^jYjL-z6w3D_@w zO!A5!gZ|*h#C?4ysa|h@mXb3;x@qMOA>L2N?>)|*VJyT&3KUa+y8lUVR9CY76gSFc zEXH}QJWH@$)pRn+%Q6M{e~M@kEw862210+MyZA7K#0t)uvV1s!r>HlJ$!B$577F_& z0$ZZG?p7nj&|z%1-Kj6-o?*3Qo5kd7PnK<3x<8`^DLrtfrh9@4; zQj>A=>|Tnz?UwM<0s=r39a$U`d@@kxxc_M-6QXiQJ+5J4khM_WO*|&206pyf8?&XT z{rqia!DtIIJmSj(Ea>EG|=R&7;^p{yI(WmxJF0hp} z3H*V2$m+mNDTy0tDrt?oH8}A{H5T@;Q}XF|E5+-ZeGU_W`T{}Fe)3WomQ(m{Zav|^&TpSTk7N$d7YaYZC_&T+j(V<<3~aCKVcpBKVThoxhWN?_O6U-<2Z&S zppZ3V(ezMv947c3MDuAnzP#MazMj;1Hd*9~%7LBIYF$$~npaeg$HZ^4=nKrXD_b;Z zxEMBQ!OX11bUCnzuZY7g`G+mK;2N;m{u5v$DfpyhR9lV-I86xuC5*V)6t5@>|{{O@g@&AQ+1LZ$bO`}X4mqPIuz_kbcCO0yZ!lh8m z)i>swzXhBI2W|w>W+13KdeVQ<9?mGKXGfzXE0Jj7J@wrk6WXGzrW=Z-C}IpAqxW1zJh@DaItLMw}CT2D2C92i^* z$;$^lBFUhypYB$a-SaY`v1S^pHwXQrlhR-J_caY!6de%C$*e{kK7_IMa5GCXN){7C zlfUg@LOX!^ih|+p;f5Cw!bMVuu|-U03Ow1oa*>GvJXZLyY?x%!62IJ`?DMA~ghBR{ z^Xz7?D8t7JcUu^pjtJo8Xd`V4Ocx; zhEg6k)1YPmuYrXHtpIqY4IQf%L5&1rL&$+~*}DRt*A{^Sqp{8&CW$ z_}AOODkupYvj~Qe-1Q(~Q7{V$8K6~E6 zE*qk<=PtsQA^Z$}_vN9gMxVq3qMe}a{WnwjnA8icn!{O6!#Jw4*aAZfg6F|L&L8lJ z1J4=a%SuL=Q_H0RiaP+OdE{mk8siX00rc{a&`B6*gOEHUk@k=jdUO1Ie({XV-o)|M zhiHppRqbb_M@r zjx1ckKX^ajpH4x?bB5GmheWHfEj}x*H?9Vq{r9vOjRSa3UMwaMfR?xj*P#kTEVm{Bb!#75W^gpWXkN5)23I1<$X_-Cvd~dHfP@5HZzX1);&9pe*F#~ZceyW+OcQGMd%PX zm*gYTBt{yyq9G}(;Xu$_Wx31KXiSuv;VJr=o(OX&YbY04geVa=znA0cW~#n$%pvs- z^5G)$QH`3|!>0x*yo>8&wPAOPax=IK4Kt73AYU29&A?}6_ zOkA$fD;F};>sWPw2Kb?Z&Ta2o`}A`u17ALBAJ@yV>nbRSP*nuBe=SA2_>i$^EhH&i zIXm<#^L8V&*vp}p-u**7jFr2%mh4U|buANVyIXKv1?x;*FZM3l;Y-A4G@xK_?ak!? zfxtg&fZ;HiW*mBE}Z@-Y7mJ;f^^=FD{ z!pc-SAA0xGpzK0224$d39sga`P&A63xgmJIeV$9w$KCZd0;WZ+jCzBz`OrB85s&?a za)&4vX08`3eoI%>lYBJ_FJJ=h;CX9%s@BU#d~Topxrr!JI>eF&!$|@$LW3wvazzvi zS}ysZjV?IuWU%v4=W!2-e*f8|uzmv8cDoV$fg*EpVdP>!6{g)wxj>O25vOJzhEU;c zB3oT2fRu9mNlG#NK}vyFrFl=)WM!2y)=0=3Y6hum0%Wf&z;*TPC+0VmIzcO(2sEu9 z38hCSt>gyy6WZi$&%V^}*>(!K6xG!>{~bUD!U$|LxXbSV*QNSf4Nh?V+ajq?9g<42 zQfF1%AJ7eb+)R9Ulkb8dFjD_l0gOz&?XxKa3}#^DH*Cui!fz5*CN#iV+Kr)65C~gA$BM0l@fO-5y5JH3pcr9Gv3G#F=1&N zXl*aI$l4CS7-`M~xpsuOX7^uZiuf!m*ySy6<AsnAOV!r~Fg#==99v7lqr;c)nFo zSynzmjSIZ(k*i?;sfE}(5;3~m*QG&@D{;0QLjKtCFjxOVBiY3zlyNBl9>5`luk_t8N|{ZOyqb}h&*iVkQJ$1_N_28!R8au(nZ#q z^?Ms1B5F@N8v)fL0_t?*c|up}D%b5kfFYY!U$nhq$dYUT?JyDqsAoG&osTC3M-r?l z>9#NT6ViQV*rQ)EVAGE$X^yffi@M4dt(JB1^dE*O&(b&rM=5{Ea{r+nZWv)1yIj83 z4l7I=Cb5Q=BI~7JY<9-YRpg^rmRpVy9D1CDoeFYa(Pvo)GbfisitJ#NQ7&Tnt5i|t zb*jh}<5#Na0}cNEL18macL7U~153F!>?&2H{9CGsOaBo;NOjOg+FkQfZCUIl=PB~Q z8$Y$fV}URn1kX@I}*>q^eZtUjmOxSqF z`z*4Wca?XcPXD&x7460-D2d00%aT*hZ{xP^*qG<)}9=@9sg7Y3@c6bRG^khf-Mc|Di zKs$VKr5)ysDWrs7X@_qzAXHDxUE-t{nI%z<2+HA{+rndT)vvU}GIJ=GXP}1aY+fSu z9w+{!(lmWd7heJ1kdGD6Lmm?Zsr9|vDc?a4pJIe~%an)Bdql(UG1_P|hQAeF_qjd4 zop9+`Xqi1_J_aKx_v#sjO}*Bz2gN6%XogwMM)^^{TByGu7r8wvZ4`|j__ZmdD?;j( zD0V0z$Y?C)jf173%5Y&tFX=|@~I(pNlAbRp;bAe{2cBi(_u$P02*= zs@hUtV~9aWhB$AS-z;?OJb`t+lBzZStj)M59e95N`K+_{bO0s#?Z7cdixU>qSr#kU z!i0~E+Hq0~yP&{FEsxAz<0!x{B+ z%D?c|w+*0~V>628hF06AVZW15qiBXb-yKJMhDbL4IE6XWKJ_9??rGgm@h~_^*7iy~ zY*D=dh=-G|#lwOki(nY%-I-NM$(pij@o>kQ2ulyD5UXdi65wx*5{@qx685Hu3-b65 z@{U=u<vT%+eqF z`!yUBX`BNyLcb_DRfmpIi4mvC}*7w{e_5NpEXJqQq#1)!@J&6`{h&Tut6L{w=@&;eBFemcDqy2 zm3NpXV%nh#@2IF52+N{-N(_A*8oHSshZ|M>Srsz_2<^MIl?|{s;%iHfEsx=&OjOsf6v5M>6Zk_x-flx_T|P@SD~5tjYJZH!ioYJ#j(Y^l;-hc0yb z7w@ivOlqcKz(=_!)|=jCB3*siyHbOA7zNOC$uE`K1MSN{0LjBuyeZv|W(FD^k#vkp zF0QN<>9yL1dTVd+`R0JbLONG^b+TtOMJg~O)-4d~^()Ne7OAb<;Qx%3cK5JIvUg<6 zDK!bXvx3tQ7{!XE;o7Os@!)>t#~mtLTiCYwu6i>&;wVW@DVZODs+w z-U2^pU?A+y(v`G!btSIjXu-CZBv}OuzHJpKQSjI=f+~qxIigd>BDQsq@1e!mQWPO+ zZLjNE{Q+cJ9NOM6RNF(`J7*N$p^00Oxdt+U#+DyIro|%2zD%67uQHuxGn={sUYaO= zR@3g438hr1oX|SSkJWra!a^7HmVXb|-EBPMQ3y6x$1Z0<9zu9&v~V_&2I$^}Ba`ra zf#Xd>U&}3|`=)=!Ha|x&{lYfw7iUhirw+J3GU&2vx9>ndB|T`Kd=Ohlt$yMILpz&2 z-Y?Aiv_q+)v${NnHVIoWTcpI;R9>V!Ga&72=sIWI|2C$U^2NbUV(skAqWbXJp6~>? z`|Q!hHV|{Nh3}bu%bQvPe8VTxp%qI1uy4w!_Ozk}M9J2Bg;a!&2i zWl95(tgn5;y%HT)zTqkt=8U~(xazEJg6&wTc+M0)z2n)2YMciqyl&w?gu~wTrvvr# z_3jcQmqYpa=vBcDWz%hj(q5}A8&aFcry5|*Q^%--=wc3BCPUj>wHPOCJs@S!KAGva z!l2cxf-sf`!frA0r!2?TSMDiO*1wose}#a5U;Yzz*Z+bO-M^kJ|5Y%o=l*A8D+`Q6 z+@EgYHCKo*RK9V&DB;EhMlWt|{tyi-{;Yb2f~ku?4nHFs`wyQKZ< z6lo2Es6)Zoj|HYbuy@^X|1k}%X7*h2k(Qk^LF6@_lZ(%UbA=|ZtY33B>!SAtm9B}L ziXZQ$lq=twI2f2L7Lj?FOlVyzlBd?OvHge#ipi`S*s zFt<2X>}~1s2zXXq^TmnCyt2}p{NqW1^tR!mIOgxJ^ zlxuaW^hMuoPlj$mKJ%j{>S3kC6G;}wb1tzF~Xb3zwsrKZdS zF1IA?r7d`By|(prl@}yS>c3Us-YpH76_Vg)2jV8I8OSu@T6)ZK@|{m!&eFVks`1j* zqyt6EhHsh&VfV1VCQpyB_FKKV_ESmOW}Ym~m>y^ptv*F!4LoUN8&7|=n!l{kP&3#yQ(->+Af<-&+~0cRV$v^?J@R zK(I>QoV3!eK7i@g{Y)BnTaJQ}h{E%uA?Ax#k4|3HVlPv<($dj$u6Zc>dVROOJ>$n2 z#z7p9_V9osn#751?J@r7IJmLrVg1QU{X2Mx&a`%$Nnj3zz^n2_8X8z6fneW}++Fir zW6aIM$?$hK4NPd!i3}nT7MpQk$L^A0ALE)*#$j8pRxTpI&#+?qCT}Y9`1*ZajQhG- z@jAZaJ7|(yD{8*kY&1D6ijvRd97WCn7HQ@@ESo=V#wHWP|3;hZ!-$a@`@ysXuQI#+ zhD)AN%1HLeuxL}Gv>=VMHJWPth7FtJtW&VDC~C6a=t|`(PxQAezXeM|*`a%53o{GQ z_q|gxTRA7QKB1zQl`A7pD1l6w(!-zO_W$Ti8F_|9{&J*_yW5tC9fz8A@s;(~nc5qn z8*2;Ds2cL29~NL0__mh8TQMZx+hWA|Dk?k3TluDzmV5{g@t$WaKkj7O?p&8LQJPC2 z3e%=dd++<_=!@&-UmGl9EmWO_LrTwlD^O+ne=I&s0I&3+srn95^`7P8di+NU=AYpV z{_m-+{|fT!zt?-9U8D2nJTl#N>!JjYgzW!yOXjJ4IyTT=XIc?^%ndmK`?DLW<^hl|pR-8{Q$@wkf z8Ul5mk~kY~#iq=*bW`YIhYC)c>)*g^5FE%uftyE)93Pr9$7*U%Wmae^vIemt90>2% z>18{nf63g8r|%2;jLtkCfJ7o3kUJ=aDfgg_Kfs6T4DnIcqm0;x8f3wXNc-zrdkTz4 z>^d@Em&1EPS8|`*DXb_BiW1*BrxB)Jyrdqo9X^6|UJ6J9Bys=i=2a$|i!XUKiXvzU!YnXCkQvz8l^GrkNt1!LuF-es;+7vNyY?WX0#{cy4zi{XSslN6- zZU7Elf}Qv2{x<*FrRVq_Kpqcfd3Tn3H(wy@W+9{2*SahwqBXdvElb5(?6Evv2r$&m%OacH+m+!{J z#1fTlAj6PO{Y|942ID*Ebgi$j7*aZq@{ z!f57EaFG#juzJe70T_+fw!*MwrTPx$)J8PA;e+>^yArXKZ-rdfj}?(l^-7-=f(b)} zznTVfk9CNttcooW^wsPXzbdrW9%rzK5dZKUX z2#W4=w$o$QFZZPt0vyq{Q=#IcrqSNzsjz``pBraH7?+#~UZe!aZVM+CizDgm0w-qe zniN&GJ`*kHC!5;ZS;f!Nwcmt1`brjDqDDhmx(~8b7^-E#25UD4B+kvyBTx68q_HZ>n04De=6j^o24)`)`c;ec0-4FC~G5D)(|y`w_m{=G&|y^~~+B1%FA z2xn5ckxNoAB%=SYUW3tiw_7q`4;{M`$zUh+J17KX4!>j_aFlJUs2IV@j=az=W4Hbe zawx&i*RE>LT!rF~FpuHJ2x}XZbMw!O((Dw8fSV$YvTHTn zecW2iCCzj=Ei6#iFxBysjaM8&dXD_W_HArGVJPZ&Aqb%MJw>#tcnCa)6!0tyG{|!I z$#zAq_6LBXW+54~l)u^^-WI444wT@LCK??xi#Zk^`))a&5%2GIF2j$>KBU?d*nz0( zmTXT(z3)B*y0~5yImofJ?n)aBBpz8z4f2@UvwnRa+I*P@+8T`-)Wu^j`9!vaC99Q0 zEJglpHkP>ZQ|$|;^e68fY_KsFtA{HgfBMV*{#X7-w^8|WT?!yDKbTPLwHi9(W0`bv zf&q!YRJ%A!a9Y6d)4I4Brun9Nv&TB}6q9$6PF_(2`|$FfwZ<)+D`dl+>-H)~XX8x; zW75dp@=}s@xf)X%+Ae~=i4c@kts8o0=+;5T32+hu_^g-~m9WFu7#fPna3LC_tL1`z9>KD2a5ag6qybO}LY~GtVOf=HH?TdxPoH zG=VFn))-IWhoZ|p>vvv6Q+S>4CB;K?#v>%_za@}pRlM)>61Q1qd?JaO+9AmaDtEb@ zxfVkgCylnc4iP%v!AA^c{__5Qryhff!j4)%rd#ye77suRZTw3MozPW4uV>Dm?-KWQ ziwRE)mbyE3)irNn@c|#mV{8^}w>qmI@sypA(8s7VkZ9v-e$Yv7+|3alK@e_Un8HL( z*NB5@+@}YcGE`;nv7XKIS1WZA5smP8@eDm1W3;f`wxABR>=kOM7nf4K&9{V0FsgtxNyNPftrxB+@ z*=Z5SttuJZEjiZ^Jr2**My7J#*6_9{HcIj>)b>htj#W8zGiqCu1xDOlt?vrFgQymCTE zfaXhwo83VBU~k+>of&bfD($q2(7POyQh7HIC~X+r8unysMwnPEto)Pm>8HPga>0ql z#FWVPZ?lU~Mf}}}|EP|?MITyv1&uB2sJKg@j2=-U9NX)JhAlKo$Z6wQEor4CiIEKW zSWwPkg{|ux*s8+i9)Zj0MuRESP7}YX{So2t$ag8xJ&X)~i;9?(p_aGYM0QW`zPB$T z?n}DgtkAmDgz;3B|BJo1j;iY2_x%@wpaK%ot$;Mr-I5~GEurLMu|T?0K%_%JN$Ff5 z-GX#?F1n?q8}9`58~g5ke*5fw&p7A)?)MMInv20)WALnJ&iTaa{rVVJc*_8xj!1gI z3e9p;=tW{Jpf=1ru6{iHD7C1#=8+WzwL;?qLxjjqTHLn}3vwGNB_0I|u#@}&9vdua zPEy$s^j+%pFM*7d$k>Y-vNW-Pl0G|Ii4avKy)`Nt35kKEPV4oQt-oqP7Qxm0AT|AB z3h+X+*Hk4g177Itnkz3f_Tybvkk`@0Edez^46W!Y_O7!afyBe8N#M)U`FBulat{h6RU7~x&P(B0S51tX6FETQJMyhQ7&kxw-V9!!c?x*ou5$fS`y*%x-29N4>WCce#` zl)HUHW%q_TO|b|frE1}sK z;Yx9d3zHe^a#w*P%P{P@Key48-?=A4RHOEF;}Cj}Bho)@ia5kGf7-_(-@fN|$_~ef zgL8MteBMWxoIK8y3v3)*XMJMm#g>(>NhHHhfn-9pGf=$$9YhL$-WpgdbUC6Sb*gDf z&}u%`jy6VcE|Ok7Si1SRk&COGiD->wO5%Sf*xn7}*~hM1*USjRIkg=V;B2b0h-3i4 z*5b)8$lki6`#?%45QqS^FP~sel>8|IB#f`U>g-<>^Av~x^^Cz8US36je1F=pHwD&W zqcf@O`Fy&ww3~6fMh*$XQ`kJ)G!+aypRup5Yr8YVXz1a5)iW+Dw$*;al_8^nZ%J2< zyx0PAZ;R%Tf}k$hZ_ zO$g|vH+3E6thOu2|ExLf3S)D#LS+#RlMW5>%esh$K6+NRL#5>&BUob* z@%VumzBT##O(ce$nOcx@6wdE^#Aw0lO{YSEd|%ugv5j>aI3?{-*Ti0X9qi|hs2|1# zzjKIoxXoGfn&CmB@M-JVeqMFkeiAxY`aEie{+{n1VbA<4maNw^1C=(GE~)2_M)K1_ zHwFMdb~=Dd|3cJo5C%mTt|X{3Jb?2y&5(_tAsy9gjq3=4zOZ)PaYXm2L&z zL|Tld`GgqZ9@Pyw)roawj+lBW5rQfa!G<#R3Sm-kFR7;#n#WYC4ZWvXXAItiHsw}+ z0pi5nk+7c3v zgLRt5MTjojkbo$dJSH>m!2qvSXvrt@7_vr!-T|1I#}$fZnYJ4{?i`AOi!|PSCX-TfU*#P7i0bD%vaWbENab z>pJ(U6qy~boXAQLCZ#U3fvlA(N8Jh1xW_2ccTk^%_QxAV+ji^P#2Mw$#AQaHNYZMy zUG^a~wREdXTKrefMJz0R${g-FLCkv>B~vZj9Y_+T2C7(w7L;6zF6#=ygTWP&UlV6q zwQP@y8jB3bI~R*2y9TTxcNc=xrjv3+vu~rZ_9W`EuZXvg4hlM}<5CqC>r{USy(oH0 zc^~@>9Qbn9oWhXktL@Dp3l3JBhZ#D|6kQKY8#$PIsVk=W?9SJ7vEHN;*hpwYr@n)z zFKjnnNR})y2s(TfT4*LW4v`^$QoFm*ZrlOrv9}fR>O8C|9c^C~@}PfqX&YP;{Kid| zkn0~i!muf`u`w{ceCw7IGvof)7pAehl0RUx_&>mA5Qm&k=|=q>3y@_q;2K4%o3}fiM{tQP3jD;fr}s%~`;_?bySB z!vR^@iu@;dc!fHtX=tsHi@Vw(A1KKVM%MtW%Q6eDp`|6tab4B^&X210TI!91!QvmQ z56YKKo|H@yM{W)*{xDsC_EO6jAtLS$r52R&-Onx+Ko^%V1MtILu;nI2gt#3l}n=1-d4V{afAb5VuB+@}x1& zcYcpsykmyzA1JY9T6#CClS-T}<-=>aO*;43;}^Eh23K|@YMl9JBv1u%&0=(AN$VKm zG2)N`*`miqnf4j`QIa{+(nYfS(Rg7w&*gS^QbVpq__?6Xvc%GYWVz}|ai#bh^v$Fv zD~Cm+%g*bFvQvMOVv~=LZkk5ln=I14NQQI$p4sCFd{z{Ts`;?GR>F}95wwUEAK3#U zUB_=mWnVj*$JD;0HZ=t88r;L4b=mAz8V-i#Os?@kAXt+{7TR7|tT^Vl2>$g7JOnvW zG7r15U(h{c8B|{%w;YG`ZQ8<~p=-5Uyy!@(rh*=&z8IF?Fx#|tCn+z5%5T!geyTR@ zZ0GEf(mlAK+9iz*rTc z>x0de1PqGrKK06s>5WPci`--7cd{rI4lL1e(W)&C>C=!&Z+uHtUJ*Xp6Lv3nLbN0F z-NLBQ@Tj5)!KvsD@~XP(>!%^qBKPq^R+1i9pkbuja1qf2F_vn>)TC`?|)`Dx)Mh7Ct z;djiKL@PgJ9WvC9u!=t$RRz4h&WCU31*Mt_b(>;!ntd~fMy8k5K|;tnp1K;O^)`dJ zm8R2_P`16zaB#L;$;ErIEdv@7%eG#2Q$vbu zNSoWbLy`qVfo2C=`!i;TCTQKL5wSa}(4W7c`SB)IX@xOnSLP@wfjy_ZTz@H~0Q+Gz ztTaza^tRtLeE5U+>){Xngn||GRe-|$9iA@Jz!r1L;PR)>C9!G|c(vh;U#b%_L0gIw zwRoTJRhN8=ud*ddZOrOqt%777lYx0#gsWSGdl+(o|8Jt3ylMLW8D~cEMI6)!r;`z8 zy46dkD}vyMV_aeq zQnbK@Z39eI(CJAF-gcqMNUeV&qx-jeXJigJ<7THn;*+zaKjM?aKjM>3iN}J~$|-{f z3Bz|^OR03pU(&(Ig z9W;C+$R+h1)HL$Q&s8`_HoaqJ0v?>fyh5fCEa~CsZXpS57>v3}fL@fnc0JV_i)+F^ z3#y);6T5xK;3h&Vxh}Bz?q;WRzZ63HsB!RV#B`<1Hq~xlrf6k|W)+#|L4g?1Nq9JD zzD0j#UKpev+CMyDnj&^BqexU$i8o)#S{bSC_`NURy2|_M5{3y_a1|xa7nK0@Z?5xx zFR=xF&-)n%yjAvzeHWb-bF19myRsK&Vsg!9RZCn!dSq{kaa0*$H_Zz3m}cmc0z+y_ zUTTkRRK&E~3!`tYv0hNM)e(DXKb1DC;6)PmCcH0Aen|n4_HV(?Xs~sm*!mU2|Tnf>X5X--w!dAdGKjIIxZ-y*++`ZPy z80)CXOeB+mB;axb~Ll)8oeua)teN zi0C7UU&7OS+N+kH-))LNQ_$LUui;!#U1sTr`@@a0l z_3FKIo&q(XTa(^0yQFZmP{Kx>UFMVAbb?{+tQJ05V~n zc4?B78jFP<`#vi4PCz8A)nF#wfkOca&q3D31bsk?5kl{Gn;!Q?l7cf);_tl@F<@jL zcwhqF^h=I`Ek>AAX?bO|$WL#2{9OhkMms@0@z0-jknFAEd`(9;%)4%ck1msnUW%2| ze!Pnl&}2O$xnTr|({EBDd_tB3JC;if9|-bI$PJ*U*;5AkFNKFy z1wlnr$Yb(7?p!_e(C-RkY0Kc29%O_g1KBH8^Tn{Dg^viH1bJ6N_N05=dGAYHqMxUy z^m4rS676&NMIS()s>{te~`D+UJ+u z=s6uhPridnoYqeQ)=XihLxXz@Zj5;`IcGWCJe%9i)KLFuY^L&8K$51HuPtAc zD-y)^gbQ@4PGe$lsCQR;4LdIC-Re4INebkkTurelxVNqoj9bdrbEmU1el?pvUNz>; zHs@_1P&7Ys8<{$BS!Yza;D~3Q^N?gDBO9EXgsJs>HB1DE69xW^6Y=ug5f&=#>(`RS z=VmsJ$;?K@z$JdZL=*TU71Tk+Q}sET!r#B%$Utvi=ptvt?-9q_81afSFjF6ES#_|x z+OrA|$(5aazW}ACJ*mhj?St*_AjB6rTrr#n7yQ8U_<2jK;5>uevjxRLqd~D$G3rPB z!3``bcN1jxaigrDxsU--tIWrOfmhn}iPWWMl@WICQ|0 zUb;MJBg+2MX+U&9z;UQ~)JU^Z`o^|Ng__jc`>`w1Tw#(uqu8y)nCzvpL6MuD9(^-+8Cw%z%-?M$2ZtJu^@m%(pyOWqdU$YZjWB!_i5gFL~Ip zH-lWvNlZK;C$u#_TNT;uqp8u1-;+y(!=GY47;#XDK)Mdkd%G+M>~#x{QW->C;0s_|F7^hfA^ff z(5wG`4C^=as_P29Qv9EYUft5To2FRlQ6tPZGw3Rx2Ogn=7>9AtK10=FNPH$wrCN6^ z=PL0XBmndHh9G<#s}=e<3W>~zNNarfTr_9xFdKbWtT1)!CX*U_yt5|*k=IQbC{lS0 z>x8!CKrba!dJy0&RH|N~=V)ewUJK~Io>|6S@6)MvOgzy#lkx6oP_db?qG}W>N zg-7^_+*n$^<51S&o(x)tK{OZb*GXLcSE6K<8H>)NSyN`^R?<{SO=M&M<2u$=WwSK2 zOHA$53$xM1uN^8ych+W*734ChdEd!Vtc9WxBk<{RZEtWWfEkbX1B@A(>2(L+6CVP*4pS zDXZ=$tTQa#Q4ne$Wm?;!WM zbA~?KHakJOePV{(Zg!7h|^P;g?hBA`Q5wDHrj!fIh`46)||Zo0(-9nQgL42 zci=uvuDfX!wDpAqFr`~33hBR>HehKZL5mu*2~C#~3|`7owt@(V_DQENP|`b-r#llr z2W*e1*n{1P8v>^)^euE$Y7VU4+yp%v7K@`Y1q7S67pHabr4p8wVAA*_jAbErBYkbK z@*q?Dma}3PNoJr9d{U!#QK#XXY^k>4YZN3y5|;qK+Shs&!?XRIf-e-hV!-6%6fU@X zP|>qx`4|C^NRM;C&MA0OP6HUeCjafE@gKg&b&wtO%eII5Hoa<7d4Ci_T35ZP#<-7~ z`!-)~Hc%Q?ydq0GC;#yvjh|3O!TE|GrSt!{B1zIOgZrYNC$yxU3Fu8;fSGgm`Ls%wT zcgC)Rte%h3Yjm~FUw=%$y073I|It|f=MTMkWheLkB`e3d3dP;|sWN}12$;<)=(T9C zMdyE=2EvCjIiy8QAK)Y>m{=`r zP5Yd}=*5r38d2-iN>=J}W-yO`elYwUwB7$5bY~fQkf1hz>o=i_&J_<)8UqU=gK&~!0Dy7RVpWWf%}LPwfdcMl;(;F=+sjt=Uv~2 z%(+hW+8wSB7O$!E4TL@Q<-ao2Y8pX;!BOY@f`D+`(6*-9(3P%U4P@J~LUypiXP@ej zHY4R?Ko>C2B31!fphVf{Q~>^shxr^E&WDxY>-^3+$JkYVCtvd_zf-@2VxS>(W9Z>v zY3sLB>Qt1U`5ld)`JLxFm+3aysEW274I@)bDGgpeik=t+BQdf=TO}_0wM9lU{hFdi zXe{-wzZ`N@+TMjed)=rmL;#hQ@mb|=*>A@_3AVk1-?n1GXHv@FLgW`{lWW#yUWz<4 zFgK5nt%EG0+Q#$zRRs#7fEwV0A$=@@9V|Gn$Kw4ooFPoo%G=p4Z#5%geqM9gdbeX~ zDpc)?q<;qY-4|r|5-VN~$9S{6NBLHNnEE}+`XkT_H)rl8dEb)GI8)}j`DajLzj@i1 z*q6*mK9zE*_Iw+gx=u#9Gpj3HrOB-dI3I}BlP6d2TcTqe@8zI5 zP{x@G=s=A4l9$P_3Gm3M!=d%6ihq>z{#PC|#0}M`acqiil67rqzkhId;DshtZx0IwMK(d!(#|^tI5cY`T|U##I()ZORWm-c7mEf~#hYYsuMJ%|Ru3?mwmqG4|P1V3WsK z)gpTHmeIDFfj=%i3EvTm$|~mNldTq%QV^v7x$U&D*ELIPIsKERB|{;2?pmM7x1&|% z5s(MKq?`B4>tx7z*x*%<5CtN5uC3rZD1qi2c)_|5@bjnHR<|k?8KoPyeb%O=$lh?G z&jjzkw+kdDcA2=H`kr0>l|{c2E@Ft&&9}36K&x3fF z3o5Y4tn|h}HIrv5_Fq)7`=HK&afAZ=PwDTQgUEePHw zU03_Zb%Ot`ewjm*k;Rdf8lG2R@w#kMOT>ub0P*8T)O~dZ^5B6rr;kN_2jFENFM22X zxZ4}e{y;XMiaFaUM~Z5c$a0*5fwC+eo-cjuwKYoytB=@V=eLPp)5BU)@rSzYpbw#LMSDNkJ@W zLtnP6yu4tlgs>az5ss^xaF38p3xfyO&Tp*CXf0&ci88jw+yv)R90((d&+R`f9B*S$ zCP@raR@?5mzK6o)ry_k_XJ5Hlg*x{QoogeC+9Wjp`=ppbh*XUlhdkRrNd|Zu6vrzmwl5 zc3LzlT%J5M`B0GdMmMe(O0cW2m3x`h+8sla-TnX;DNB*#FX!vBDp$1(u8iLdNPzKM z^bf{wj!;Z+?0lQ;Su&+WC>vY44*MXzh;Xplkn0N|01^szaK$s-S*DllU0OMt5N-Vq z()Hw;NH?0YgWXyVSe|<5EgnIG5Z<@Qa)4aCbs7sA48730xXBksewucA#||(|YC2RM zz=AuqJ8v$qdCE#zbkzhM+{nRvHOVvo@NX`HC%L`;9GI{>he2 z(g4oyel`=K59kjlKb+tB?pK6ZfDE~8%@rXwMesxVeFR9q-$<*xt%vSS zOD556dsSSLD4&+f>dpjw2eBOX)z(Sc0*?}XGeG@ac1cwlDPR3L$q?_G^g1zqdlb&X zE3y@eI~9ZPhUeeDTObAW**0pQS$$zli?xH>&_w$?b(O|qGW@T`2;08E7&gJ?7Ee*+ zhfHQkziH#^x;29tIW;OoHk|6@`r;6yJLIhu-Kh07JsMZ@G%0=GzU>!i47kne2cc|2~WIQj$mifrW=?MZN zB2qN(2G99w*g9)x-joJrz$eKNfCcWZ7BHAt*P>UpT9%dj4iY1k&V-M?5L-IlNQVHkaV((f9lcUpIv=T?7~otRrchR;>BS+h6#QtZ;9w-ny?#E?Ikxv zk5)jJq}fiTbb2WCqWFDNmdet@(w0U;0Kz`Ium)R0H(dcd`1D&=qizBFCU%9}tp z78LWKV=R~>=6;hn6@F`>a=RO>X6^HFlj^x)TE2Gx1KIlXMEIJty2OyN3JK zxFJ4c6YGf?U-8R;l?OZ8&vw(a9;R*HGY>=3izh3gJ|S*mlaeS#GrSWmTfiuyXTDzf8 z+)Y;}FG%Mi9sI(q9OCh0W;r;P z0ehthjF)7@fmbBw;2iKx3mKt}k{94sQ&Db*D{QLA1_{?N)#nP z^1ssBe!m8clyu;vosAh_V@p)sEc(ND5Lx#nF#N=|kGm0_3B2pPddF%1$86|VVDkj{ zk}&YrjAlLc>U#l< zHE2}zxm4rVx&h9!ca@L|>S_dw_Xa)sb^Le7+80Q3%hUe2W%RelC=9R}GlyxK@^6PR z&WytS!BfrkLHrw2CG@Xbl}FEGqqRaxGmcxJ?8-wDOL=?{9XiY${FC0UF%oVhs}>MX zH-EFcM1jBUdK;(Dz=7J^RH+L85_YNhD1$zd*@Mfdq`Bk8+MR>NK{M91INNRJWm9#m zRQ4UBg|hy{%m}cTpwDNzVGf!d60Ht#L-km6;f=2bW9+_6L5mA8TOrKPl|$z=nbW#Y zjVq$rbj3be@cVxS;Wjo3a8;3RCS(SF43!A&Qbr1cR!OX|29NOy1TC!UWP0mIPkf10 zQNAxD5Y{Yj9wGJh+8O^JHpJgH%pc#QgdZn1%GQo1B|hJY}h;aV8ql)_8&Ql%0Q#+P0RdQPvy&`jTr1D5|H>wo7c#+HatEjv@x8rRE$t&JKz zQ7y37!oH~!ootk4CPXu+gnrmRKGyy~hvUV&C&wZz&S7j;A|VfTUSRJj4r@1+TUwbm z^bBJ}7j?wNxEQCVLsWkU7;ndKV}o`<38l95({IaPn~ zSP%XVkEJO02Oeurr020>t@mKdCB;26XK3^)MSX1%d-O$z+W^7K!aO@vl|IV{Py?yp z@s$U39P~ovXbePpHr-t%&09$+m zZSOWlciZ+TP>0G*NIUD2eDy(3k8HLsAd4qyc&K0i`gAReFDPS;u7|J72^PVIzMdAu zQwB>@g`uE_B%F<=mc4d)7;{LobMq3g#m6IIa9rYa9n za%p!h0c7zsj8hl}BcAu3RMeH!7FOXo$LHEyCR^C0+lJxxh$Yo}bvu*3dS$BQD65BW z1-3SGc5#i~3jVB(DLaN874Qz1fcC+2){NCr5Aa(5L7p|kE&UQ;mY?%zy zmA=v{*3TY2Hm)r22a*sC_uLT>0>yBWl<5&pM`fR{1OTphnSIzpz!eYPQiEg{{tlIW zn(T~JAJz{~iD|wh3=yZ+Arru*^uD#n!QS4^%o@eQ;**aYs9R-;eN8( zY_iJ0S##RZK6jfF9iBdzw-Jt(9kxLH?MfCeNFCWqn~O7h(asPAP-q`- z*{voA&f~N|-Ab%3Vlek`GJ9Odd4QAjy?h1TxBd?pm7G%&OZRKO^p={Knikge##`tp-p zlb$76_9VSd0!IEy0un}UoljczYOSxwebY(rE{kzu>Q03d=dR`hWnS1Qu{=e-I{wiW zkE^a!tHUi@Rckj{w!`7$JZlV7!7qF)=-Z@zM+-kVsv#&M%_c|z1x>Hn&XEbWwxB-Oe{xv3x z#NlTctux>Bb-dSg2L+&+tN8GO3C479&ByN*3BU1ip_tnd^f+bhSGvm1^UECMLSLAt zu?c(<3#Jg@tI<+bemZvKZ_#7o+dGzEQ658+iQcunmtuRZ$}|~eC@Wvvw>@ysd`c`L5>r( z0@kt+aiX6pFstv5gOKi!u?~OZXAWi7;v9NW71*7~rSybhkD_fZ;C$>LA6qh1MH3Fm zdlR>U&sT!gw)|Uou=Y{osI%|x-y(zx!thC_gM5r9gWGD|uQed!d&|OKS3&Xz!Gq3Q z=U;Eg39LCsXEI);20bislu)$4W=i^ZAl^3;4ME`P&4fXZ^W}_Om6P3K;obcvHfDxV zUJko)uPk^7dRSv$KPHO0(%Z4^?Gx3cC?x7Kb1eZQhqD=R^8{Z0g>Isq1t=-r zt;@U@v{;dL26ppI2C6lo&jzi){8}Z&x|8Bvn1`$(@CJnynuH=!MNYmRVC>CQa9Y`N^whCN^< zYNd|+4oZ8FtlYtk=D6X~$6lH8vA9Zmg2zIM*8tGp%P2$8PD5HUe;a)v{kL`XgIt2xJSVOCn)^$QI%z!@jy->F@E9iB^@z;d>BE8%9qC4>wO; z?LmN!1piJ)N?YKj>J_rH+>z3Ie^>PKU47f=el^Fj4s}seAPF9X%GGTIMA|sRd%ms) zZd+!KD84^Sp+J%&Ei*xF}2ONe!M1j;_Iw7QQ$BOa{CA2R>R7%&dpe=n)HJ z285@ou&1lKK;Y02v$W|ns7oAuueR%l``%W%Mgnl(AB|KA5V=}ysunw;GV_555CWQG z#CKlo2*BIrh?ZImN;Q{bFlj!a9);Q*d_*UuPX1=%z42fq-^ZA>FfJP5ePns)vm{^R zwQ0IRJ0?Uew}*S(S8+tP98tY@v%7*2*kDM?$Q?VCQtg_AhVc)PgbT!;g7k@*mZVc9 zhXeU9W4VG`b3RdA`i0?_{4ubY1$}_2`Q;Xs|AH#g0S`fT7ARl1`Nr1tJfe*&b#X;p zr?#=j15RR_y^5tu@+TV%F*}qpPBv(CM%jKP@1!Fin@6N#*KLwHpW6Mdzo*tkriv8r zw%@Yl()2NWpc}P&$c)^8EPARgI(GmB6YtwR%<784JMobtFhI3wx8M#*@Zf7U8X|o1 z{=gjT^>+|}w}Z`?7NPTXQW5tx{gwYd@)E`(i?w~NzgNH}CPd<5 zE?iZtpc9$z8lAjx6hlUvs?00Ua_k6hdxeb>1 zh-u{Fva1KnQtNT|9SuVP$c zzqeh!c(tPFWMb83Ryg4SZFiXGd~Eo!(FnPb!ooLx)^4+RzuQo|b568Cmk|1bOOp0H z>Wm+gIAPKtWO!5;qK;Q?EfULlzUK2%V+hxRy_GZ6GHa$0*akxp8+vNfOhoTPc+)0+ zZ(FyNurqvmU5<&WDnEhz{GNB3L3gHmcU&y~p<R>InK*e9l?Nj>?DJsvvg#;<0Z7ys_Gw7PoyKsUE7d)L5Y z?9?B*h#3ZGAGgz#?8((^zbBDL=NZJYZ%(Ds8?;vH%CW~l1j|tQ}?RI8JR>&{$vDvbF7_d89 zPCFJh3ddKmpEsJTynPrR*I`UU?m!X&QEyULoYDy98C$z2*pQa2A4vS_izlNa3PZQC ztWl1(873sgeovsNy9@$(T+@6@@=o0*NqpiI>+=$hbg(6?V6MwM$XXITKG_Hh@U`dz|UVtqR?V(W`@E?!bTeJkL$TcX3SP=Oto zUKu-$9Dq^A%DAy~Cz{-apj*~yF1ImTgJNL6O+4siw=06?>G_2)nnSikS;i3_Q8k!y zkLnzrTUo@&+I`jCoCI0%6&-}^`Ihp zgnMw9$S{b7(#6QyWp*g5T6^$-J4z!vd!zI_Xu_kd@n;?vJVIGvI9>jL?WLhPF0ua{ zP`;tGh8JoEPlBrnYUq?0EygZW63Hf{q7+hQox9P8q`q(gzi===JW@LO6v#l3d@^hx z#?m8&5LfW5rHYBK<*-xzL%Bs^g|E(Qp{F(=9Ip+L-Z@o*&(NUtp@3u~<_iZc@X19> zGmfGTO~9}Dk!sSVknk+!Ni6NJ13;DwY@Ym-Zb^46U06&nTt65^Zm#@^0^6d^-WPtYpWmHjx7xDQ?A^~18 z%D%y@k9X{2)eCX!Jgzu6OK~KfK7=Jc9<8_ViY-h!=!rNNA;a65_Cm zVmG6KNlaO?0zimkcieFP!wLjQ_-gj$eJ9+}eUlRL8y^t!-CmiN7MB*jX)h`Bn`T@w zq{XsX_fqZ`!Aa{csm%X8%p7NYMA#eKN9TIFLYQ0f-;b>0)D@Q0mAMt4arJI$m!C|F zZBMON6LxDTp@u>y#-aamFOK679 zBx+y+Uk|v2l`4#Zn{3fIzh49dLPPNS(?0Eg+>n1<*Zp^nZ(M6nwSotVwyOG&n&xiV}7tbJuNhU!N~ra_REh`Bwzfv}?Q`xcD*> zN9M<00?hh-w%ZSw(=3(G9}iiHVD>A^K&)^}xYh_b%G393+M2%0@=kzh)X8cF8$ z?wOWZx}#?Zi7c_>K)8u32#Xp%=&~Ov+wB(kFiu3rI7Y}rE+Qx1-}YgOIG=}Ci58(m zW!uP(G+sT_l78Z8S7C?BrZu0ZTNa)Jli{fMw6a;ztyuj`Q&$rUH!JB|wCQ(b>Xqa_ z;_R0viiy8^vS=-q%uyc_5I?SyMFsBxEdrC3{j7hjHUDilscLcn_iyDVUa15{2L%2G z3ew)tqW>NJ{&?Fo>+==#eT`gtQm3R`!5+ES(S1$pe~ot0FfgWz2gMgz3Uxwbwg1=DpAq9VzooBvLwICx7@i- zk$_|+B(7NP>l6vj&k8rQsehgJ&ol`ZkenhX|AuwmjWdp=WKLTT7ygg}6kf_o30UK8 z0H6r;P4=eKkp%tdGVpD$+i8mR1E*O3J#|aV>#W7N4~5`W2-l|ZGcos5^KNl6o?KpijKUfI-~YI zn3{&}SKp>m_hK@5zD<+i$n#|j(zBnnnLZ4S*qxrApKvz{7&DgA6V(m3GK}3SHn6jq z)BIQh@qYo{&OkJGYG?^JM6WqSsmu;nWS$x`dz1qH)H;`NM>9Nqk7+V9=I)c(OyTAp zckjwjWZmtN16dyZQ2FW#Y~IRpxa<4DNNfhzkJuTKYY*PX;A#$>kx*l>KgAERW8|F znvOLe*<7}^+bxn)Z<1OnE&a{P-L+89?p?$hhIT@Vshi?HIOq3!vkr1FwH)#}3iTsd z8bR!ExOT=`!n7a1+>O&De2l_WvPDA`<|gI-^enA75wAQ^qDW^~hYD^Uml+oNS%U&K z2u_>Rf894O%^p zSdY`(O;jhmUF>-C5v2#Wsdi+1W}1@5cSE_rTU;2-+#s(+`Db`l48c#=;HS$)vgMZ=P7;06`z3S93Ki z^BB@Ub!ojjGj*8D-y{_$TTD{@UaI>s12hw>G$*#Ehi=P&8!z zcrI}XA3*kT*8Y#r)&E|<$`w9$^{AKH<52u{pp5lx30PH-;sL%=1p66{VW#^U&{F=d z4|KzuUwuveiqI?z6hpXM3BX@4;0O`OMG$qTM7^=ssv0^#T~w*5tG+JdVE+mu3u#!3 zHsgVdY-b#5T4hPXEFcUL=b@xT&J5HTdN52e6g*k1Q~xD3!hsD_>TG;It6v)ZYYk+c zCv(rEG@rbn{r=<|;f?(qBHhv~(*l85x7Ki~_QH5t8p2+r5PDx64F@WjrI1yN$I&02 z%hX=J)aGsP)de4w+nC`W;g>TKIW2;zDD?4YXhMc>;xw79ex@8Q38Z7PJu52@kwFSl zl$;l71u7HZhX}~xWK#^UK+{O`5m44xyKVNBfcg&9O}%zDOigKo)b`;$tkESV5j0#LVkq&<>rer~XhGTz~zW%S8 z4FCW2a}lnKRl+1!H63(J5ug3ICVxp&{yIBPmG;$79&IkRRN*%v$WZf0kqp%T{-3W34GNY8zRnR?fXf{*)a`VGoqS^anR4w+A>)sd( zdQZmPa^Sa1ruY>?;5|%iv`}*x$6E{Zpf0bb47nhZ_z0B)B!_mcFG%=YH;6z`=&RjccN? zX1OgXx~prZ#vTECV>R`Xo60Ca70wNUu7=@#@3k9`M4>QwgD12t)YnUTcPoRoAZ8Ex z=+QvRkQ@LU%TqL)62$3lH=9C!fexpd$%jkR2>^>uLMJS7rS5 zmx)b-$w?+7c+^c4_BQvutr+anf@Ve5_j+dRJdIu(7EuTiLBBBQp${!~mhn`id z#I^BNkT>DZwD)VTyHvr%o8dPe&AxROdn(n^tE?z1Yotp2lx-R6I*!LqP^(9({-RL$ zS?{Sd*h7AimV7;TNjZ!XEL-=aAfFJNN(f=<*E`TFwW`C*W0E)65I)%=Motcyh|}D| z0%vSj=+f263ahYAcm}U?VNsVa(zon1r=0eR-h# zg%)4JLnB8WKZkIb*t8&Dpr*vy%Rt9H>0As{zAm+dds?w#%`@|7>mn-8Yu^?F_l9uc z#A{5|vR}qzCJ#SXY}U5edD2(DBysPuiyUK)Y=5w+@d0hYRgq5Pj#84$c4M3EZXcGu zX05J3d@Pq5?^XH`!kcrgQ?)rM^SsgX;dQzzkMQ*IH+2|`3F7nNm`8kEt9AroN1U>3 zGj@dk5nJHs$;1mNEv?+4wA;E6&Ie+Cggq(nA}ik&I&cgiNhkzn@x?Ti>o^(dD(T0N z#DLTlnmqtf!%_b)?6%{5&e3`&e+LF(Z$1n|SFs$$ClqpQ9v$6%X4o{!<{@!kU5ZN2 zJ{l-Ht42?_r$x0rBcoIm;m79=@S^(11C-Ci6)w5NrIKDt2bYA=({c+^V?T05{@Q!} z+AH`^`DoE|P9GV8|EZkTubOj0fD!KXgY08bfEv}T5s7=ov1oh-*x4fI{y?=-fPUW* zqjXASzyx?at^O6bv{vAmEWDJQSOBGRQvHWLXdpxpsR{9*=t+U(JJ-<;wadOIk&y%Z z&eY)qz(H;pU|>q0lsb@3rqDnw35z_B_kjIIvV7{cy}B@?G3SvElokCEao*;L&T%SM zV4)*<2S=ZPdBOnvLNqkbcFw^Y@kX4ovS9=mCt?b{$gwRKxsgN^kf{cDQySF(2UsJp z`L`Uhh_IX?(?A%tg`U)!hj6A=+t)ExbHSMNu!sd{fdG<$$vhgUsFPw3UFbUPC|Ci( zsa3yXS6CdscOe4~dy9NCUHJc+!b5DX&xH;N__PAu)C*&_Aly2X8vzsS^k9E@PV`{^ zBQqOV8Cv6g);UwR=NFgD4$?sN834cRf;A$~Y02yn%_mcBX(t{&P|LQho#~J+U{AVx zhtMV7=ogJSY7RCRQ&+JVOkb4TgC{uy2j$O^4}2+w7Tqp>5g!sqo}qcGNz*)mp=|HG zR(#?kD(3Xro8Kqy_=Q_#P8%8siJWDo9uE}x@S8PwSDSQ8$b44JJ&qeV4 z+NU?1*xW8LPTj_v1`Ai%CXY#^VPvL*;MNS4$08V=2{I!(61obNs-ubq>T&9F?hk5q zv&N&iTA37buJ<;`Xm}k9U=-5b2wqaD!u{9r?SamL%4_xu9$9~xr?^W%$*$3~#!*{q zO}RNE+C$Ja=G-YAkGqFL>s7Xh?;`}DA_EK=c zR%XOtSU4(=SHlqiU`v0X+W5j~EQ5KuQI#BMAT#7ElgAh*HbjL+(MTv2W|rGI11Irz zBZAk|kDl(rFf?S&UkdkvcOosxS96fZYwxfcgLciiA#=PKz8%5g2p^+ z)1p`BXDuaL>ONqjKBA-^dU>qXv2^tT_yRxR1Q?t&8WWqHdNTbO`oI}O2{-|iM^s@{ zn0-t3aI&!p-Y#CWClH>EdvV8@#Vz_wtbNa3AjtFA&U3OeaTCra5?^L+tvH$RP!RuCZnHLfxn&-M!(|&XT-Ce$bx2X|%~D%O}a-K7Dq_Me7y-5iHB-$)^nr?ciPpx#?zBEMLdg4W!bul}6AW$P``2?o1 z4byxlD|?I_0#jF|2NGTj%Auu*ZZEyJ7MFbsWMyunuiLqQyB+M0NG z)$qx1ri?&UDO*d}hBloc05#-%#a@+^gTOk?T8XKYyvgIkM4$AG`4bx`YJQ?WHyE5O z;DX<`bTxE+XMRYh`h9rci_nng%g;-)OdMgzwXb^;A2n0X)u`pTiPD|x!K|Y%DzcH^ zPa&1a`mDtdT{i8H%Wbj=#>9mBu?js)2I9^OJmQW{qO*;>$GI*c6f?CMN6(Z=SXc((1Re9~FIif;cX#7#9}iHaX%4`u+A7FHt&EypGSnTkMbpAb%5tKbeWPgB-qh-}ao}fY}oE zLUx2VW<&K$Awt;QL#;;>$h|vD(CFm8;P&j^fvXtTN&>evb$8=##p)Ax?m??vcX_0) zzgCcJUlID;EFzfAfKv(R`4Qh0s2DAYI_Azdk!jS?!Y|qi0@=HDIqyRFO96~DkNK+MCVmxhcyWipEo3c8Zb$ErFkD8VCzR zYysDy8^`Lb0PEO~)eOFS?W_Qjs3%m#)vYg}u zU>b#~kMaSl2_!m!Y?w1~ixdnQofeo?pOhl4Xh(GFBOYkQA)XkvQ%ULkb4HbrcqGxJ zv(k?sOU`_X=oWcWG$an}oPB`=%5sQ5fJ8KPA`|jY&DjAXfXx(h;aN?&l;E^ZvJt4svW#~J9`Qt%7&~dH!PK=G$X-bXKtEYcyF)rfAGr0X* z@Bg-O7pC(T^s+#TX^!~io96P@PM6=EjE_#~@Qq16dQ#6iK5*f|Li7%+|AMr!jtad) j_cKS-FFF6sA7cT%+jn#XUs(hG#{arNv1+Xz2d(XYt_zrU literal 0 HcmV?d00001 diff --git a/screenshots/2.jpg b/screenshots/2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..828577a781ece69a2fb54886b79af5065fc6ebba GIT binary patch literal 159253 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 literal 0 HcmV?d00001 diff --git a/screenshots/5.jpg b/screenshots/5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b2c18f5acee29fbc6cdae5660a81bfb42c28094b GIT binary patch literal 185965 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

OuUbrPYxJF&RkB=nxsPCq36i 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
{ + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 地址类型 + */ + @ApiModelProperty("地址类型") + @EnumConvert + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty("手机号") + private String telephone; + + /** + * 省ID + */ + @ApiModelProperty("省ID") + private String provinceId; + + /** + * 省名称 + */ + @ApiModelProperty("省名称") + private String provinceName; + + /** + * 市ID + */ + @ApiModelProperty("市ID") + private String cityId; + + /** + * 市名称 + */ + @ApiModelProperty("市名称") + private String cityName; + + /** + * 区ID + */ + @ApiModelProperty("区ID") + private String districtId; + + /** + * 区名称 + */ + @ApiModelProperty("区名称") + private String districtName; + + /** + * 地区全称 + */ + @ApiModelProperty("地区全称") + private String areaFullName; + + /** + * 详细地址 + */ + @ApiModelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty("是否默认地址") + private Boolean isDefault; + + public AddressSelectorBo() { + + } + + public AddressSelectorBo(Address dto) { + + super(dto); + } + + @Override + protected void afterInit(Address dto) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + DicCityDto province = dicCityService.findById(dto.getProvinceId()); + this.provinceName = province.getName(); + + DicCityDto city = dicCityService.findById(dto.getCityId()); + this.cityName = city.getName(); + + DicCityDto district = dicCityService.findById(dto.getDistrictId()); + this.districtName = district.getName(); + + this.areaFullName = + this.provinceName + StringPool.CITY_SPLIT + this.cityName + StringPool.CITY_SPLIT + + this.districtName; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/GetAddressBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/GetAddressBo.java new file mode 100644 index 0000000..e9fcbba --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/GetAddressBo.java @@ -0,0 +1,161 @@ +package com.lframework.xingyun.basedata.bo.address; + +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetAddressBo extends BaseBo
{ + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 实体ID + */ + @ApiModelProperty("实体ID") + private String entityId; + + /** + * 实体名称 + */ + @ApiModelProperty("实体名称") + private String entityName; + + /** + * 实体类型 + */ + @ApiModelProperty("实体类型") + @EnumConvert + private Integer entityType; + + /** + * 地址类型 + */ + @ApiModelProperty("地址类型") + @EnumConvert + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty("手机号") + private String telephone; + + /** + * 省ID + */ + @ApiModelProperty("省ID") + private String provinceId; + + /** + * 省名称 + */ + @ApiModelProperty("省名称") + private String provinceName; + + /** + * 市ID + */ + @ApiModelProperty("市ID") + private String cityId; + + /** + * 市名称 + */ + @ApiModelProperty("市名称") + private String cityName; + + /** + * 区ID + */ + @ApiModelProperty("区ID") + private String districtId; + + /** + * 区名称 + */ + @ApiModelProperty("区名称") + private String districtName; + + /** + * 详细地址 + */ + @ApiModelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty("是否默认地址") + private Boolean isDefault; + + public GetAddressBo() { + + } + + public GetAddressBo(Address dto) { + + super(dto); + } + + @Override + protected void afterInit(Address dto) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + DicCityDto province = dicCityService.findById(dto.getProvinceId()); + this.provinceName = province.getName(); + + DicCityDto city = dicCityService.findById(dto.getCityId()); + this.cityName = city.getName(); + + DicCityDto district = dicCityService.findById(dto.getDistrictId()); + this.districtName = district.getName(); + + if (dto.getEntityType() == AddressEntityType.SC) { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getEntityId()); + this.entityName = sc.getName(); + } else if (dto.getEntityType() == AddressEntityType.CUSTOMER) { + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getEntityId()); + this.entityName = customer.getName(); + } else if (dto.getEntityType() == AddressEntityType.SUPPLIER) { + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getEntityId()); + this.entityName = supplier.getName(); + } else if (dto.getEntityType() == AddressEntityType.MEMBER) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getEntityId()); + this.entityName = member.getName(); + } else if (dto.getEntityType() == AddressEntityType.SHOP) { + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + Shop shop = shopService.findById(dto.getEntityId()); + this.entityName = shop.getName(); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/QueryAddressBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/QueryAddressBo.java new file mode 100644 index 0000000..a4e0188 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/QueryAddressBo.java @@ -0,0 +1,174 @@ +package com.lframework.xingyun.basedata.bo.address; + +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryAddressBo extends BaseBo
{ + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 实体ID + */ + @ApiModelProperty("实体ID") + private String entityId; + + /** + * 实体名称 + */ + @ApiModelProperty("实体名称") + private String entityName; + + /** + * 实体类型 + */ + @ApiModelProperty("实体类型") + @EnumConvert + private Integer entityType; + + /** + * 地址类型 + */ + @ApiModelProperty("地址类型") + @EnumConvert + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty("手机号") + private String telephone; + + /** + * 省ID + */ + @ApiModelProperty("省ID") + private String provinceId; + + /** + * 省名称 + */ + @ApiModelProperty("省名称") + private String provinceName; + + /** + * 市ID + */ + @ApiModelProperty("市ID") + private String cityId; + + /** + * 市名称 + */ + @ApiModelProperty("市名称") + private String cityName; + + /** + * 区ID + */ + @ApiModelProperty("区ID") + private String districtId; + + /** + * 区名称 + */ + @ApiModelProperty("区名称") + private String districtName; + + /** + * 详细地址 + */ + @ApiModelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty("是否默认地址") + private Boolean isDefault; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + public QueryAddressBo() { + + } + + public QueryAddressBo(Address dto) { + + super(dto); + } + + @Override + protected void afterInit(Address dto) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + DicCityDto province = dicCityService.findById(dto.getProvinceId()); + this.provinceName = province.getName(); + + DicCityDto city = dicCityService.findById(dto.getCityId()); + this.cityName = city.getName(); + + DicCityDto district = dicCityService.findById(dto.getDistrictId()); + this.districtName = district.getName(); + + if (dto.getEntityType() == AddressEntityType.SC) { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getEntityId()); + this.entityName = sc.getName(); + } else if (dto.getEntityType() == AddressEntityType.CUSTOMER) { + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getEntityId()); + this.entityName = customer.getName(); + } else if (dto.getEntityType() == AddressEntityType.SUPPLIER) { + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getEntityId()); + this.entityName = supplier.getName(); + } else if (dto.getEntityType() == AddressEntityType.MEMBER) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getEntityId()); + this.entityName = member.getName(); + } else if (dto.getEntityType() == AddressEntityType.SHOP) { + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + Shop shop = shopService.findById(dto.getEntityId()); + this.entityName = shop.getName(); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/CustomerSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/CustomerSelectorBo.java new file mode 100644 index 0000000..1453d3c --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/CustomerSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.bo.customer; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Customer; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class CustomerSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public CustomerSelectorBo() { + + } + + public CustomerSelectorBo(Customer dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/GetCustomerBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/GetCustomerBo.java new file mode 100644 index 0000000..cd6d2c8 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/GetCustomerBo.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.basedata.bo.customer; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetCustomerBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 助记码 + */ + @ApiModelProperty("助记码") + private String mnemonicCode; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + private String email; + + /** + * 邮编 + */ + @ApiModelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ApiModelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private List city; + + /** + * 地区名称 + */ + @ApiModelProperty("地区名称") + private String cityName; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 结账方式 + */ + @ApiModelProperty("结账方式") + private Integer settleType; + + /** + * 统一社会信用代码 + */ + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ApiModelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ApiModelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ApiModelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ApiModelProperty("银行账号") + private String accountNo; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetCustomerBo() { + + } + + public GetCustomerBo(Customer dto) { + + super(dto); + } + + @Override + public BaseBo convert(Customer dto) { + + return super.convert(dto, GetCustomerBo::getSettleType); + } + + @Override + protected void afterInit(Customer dto) { + + if (dto.getSettleType() != null) { + this.settleType = dto.getSettleType().getCode(); + } + + if (!StringUtil.isBlank(dto.getCityId())) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List cityList = dicCityService.getChainById(dto.getCityId()); + this.city = cityList.stream().map(DicCityDto::getId).collect(Collectors.toList()); + + this.cityName = cityList.stream().map(DicCityDto::getName) + .collect(Collectors.joining(StringPool.CITY_SPLIT)); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/QueryCustomerBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/QueryCustomerBo.java new file mode 100644 index 0000000..365fbd4 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/customer/QueryCustomerBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.bo.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Customer; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryCustomerBo() { + + } + + public QueryCustomerBo(Customer dto) { + + super(dto); + } + + @Override + protected void afterInit(Customer dto) { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/GetLogisticsCompanyBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/GetLogisticsCompanyBo.java new file mode 100644 index 0000000..bdb896f --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/GetLogisticsCompanyBo.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.basedata.bo.logistics.company; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetLogisticsCompanyBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private List city; + + /** + * 地区名称 + */ + @ApiModelProperty("地区名称") + private String cityName; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetLogisticsCompanyBo() { + + } + + public GetLogisticsCompanyBo(LogisticsCompany dto) { + + super(dto); + } + + @Override + protected void afterInit(LogisticsCompany dto) { + + if (!StringUtil.isBlank(dto.getCityId())) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List cityList = dicCityService.getChainById(dto.getCityId()); + this.city = cityList.stream().map(DicCityDto::getId).collect(Collectors.toList()); + + this.cityName = cityList.stream().map(DicCityDto::getName) + .collect(Collectors.joining(StringPool.CITY_SPLIT)); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/LogisticsCompanySelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/LogisticsCompanySelectorBo.java new file mode 100644 index 0000000..714fcb9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/LogisticsCompanySelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.bo.logistics.company; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class LogisticsCompanySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public LogisticsCompanySelectorBo() { + + } + + public LogisticsCompanySelectorBo(LogisticsCompany dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/QueryLogisticsCompanyBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/QueryLogisticsCompanyBo.java new file mode 100644 index 0000000..cb76019 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/logistics/company/QueryLogisticsCompanyBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.bo.logistics.company; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryLogisticsCompanyBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryLogisticsCompanyBo() { + + } + + public QueryLogisticsCompanyBo(LogisticsCompany dto) { + + super(dto); + } + + @Override + protected void afterInit(LogisticsCompany dto) { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/GetMemberBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/GetMemberBo.java new file mode 100644 index 0000000..890397a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/GetMemberBo.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.basedata.bo.member; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDate; +import lombok.Data; + +@Data +public class GetMemberBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 性别 + */ + @ApiModelProperty("性别") + private Integer gender; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + private String email; + + /** + * 出生日期 + */ + @ApiModelProperty("出生日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate birthday; + + /** + * 入会日期 + */ + @ApiModelProperty("入会日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate joinDay; + + /** + * 所属门店ID + */ + @ApiModelProperty("所属门店ID") + private String shopId; + + /** + * 所属门店名称 + */ + @ApiModelProperty("所属门店名称") + private String shopName; + + /** + * 所属导购ID + */ + @ApiModelProperty("所属导购ID") + private String guiderId; + + /** + * 所属导购名称 + */ + @ApiModelProperty("所属导购名称") + private String guiderName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetMemberBo() { + + } + + public GetMemberBo(Member dto) { + + super(dto); + } + + @Override + public BaseBo convert(Member dto) { + + return super.convert(dto, GetMemberBo::getGender); + } + + @Override + protected void afterInit(Member dto) { + + this.gender = dto.getGender().getCode(); + + if (!StringUtil.isBlank(dto.getShopId())) { + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + Shop shop = shopService.findById(dto.getShopId()); + this.shopName = shop.getName(); + } + + if (!StringUtil.isBlank(dto.getGuiderId())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto guider = userService.findById(dto.getGuiderId()); + this.guiderName = guider.getName(); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/MemberSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/MemberSelectorBo.java new file mode 100644 index 0000000..734bf7f --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/MemberSelectorBo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.basedata.bo.member; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Member; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class MemberSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public MemberSelectorBo(Member dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/QueryMemberBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/QueryMemberBo.java new file mode 100644 index 0000000..9a4f387 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/member/QueryMemberBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.bo.member; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Member; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryMemberBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryMemberBo() { + + } + + public QueryMemberBo(Member dto) { + + super(dto); + } + + @Override + protected void afterInit(Member dto) { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/GetPayTypeBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/GetPayTypeBo.java new file mode 100644 index 0000000..03efdf9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/GetPayTypeBo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.basedata.bo.paytype; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.PayType; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetPayTypeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 是否记录内容 + */ + @ApiModelProperty("是否记录内容") + private Boolean recText; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetPayTypeBo() { + + } + + public GetPayTypeBo(PayType dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/PayTypeSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/PayTypeSelectorBo.java new file mode 100644 index 0000000..215e7b6 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/PayTypeSelectorBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.bo.paytype; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.PayType; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class PayTypeSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 是否记录内容 + */ + @ApiModelProperty("是否记录内容") + private Boolean recText; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public PayTypeSelectorBo() { + + } + + public PayTypeSelectorBo(PayType dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/QueryPayTypeBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/QueryPayTypeBo.java new file mode 100644 index 0000000..f869efa --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/paytype/QueryPayTypeBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.bo.paytype; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.PayType; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPayTypeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryPayTypeBo() { + + } + + public QueryPayTypeBo(PayType dto) { + + super(dto); + } + + @Override + protected void afterInit(PayType dto) { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/GetProductBrandBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/GetProductBrandBo.java new file mode 100644 index 0000000..1cf8f35 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/GetProductBrandBo.java @@ -0,0 +1,67 @@ +package com.lframework.xingyun.basedata.bo.product.brand; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetProductBrandBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * logo + */ + @ApiModelProperty("logo") + private String logo; + + /** + * 简介 + */ + @ApiModelProperty("简介") + private String introduction; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetProductBrandBo() { + + } + + public GetProductBrandBo(ProductBrand dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductBrandSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductBrandSelectorBo.java new file mode 100644 index 0000000..f41c329 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductBrandSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.bo.product.brand; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ProductBrandSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public ProductBrandSelectorBo() { + + } + + public ProductBrandSelectorBo(ProductBrand dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductCategorySelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductCategorySelectorBo.java new file mode 100644 index 0000000..a540cc0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/ProductCategorySelectorBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.bo.product.brand; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ProductCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public ProductCategorySelectorBo() { + + } + + public ProductCategorySelectorBo(ProductCategory dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/QueryProductBrandBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/QueryProductBrandBo.java new file mode 100644 index 0000000..aed56bc --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/brand/QueryProductBrandBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.bo.product.brand; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryProductBrandBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public QueryProductBrandBo() { + + } + + public QueryProductBrandBo(ProductBrand dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/GetProductCategoryBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/GetProductCategoryBo.java new file mode 100644 index 0000000..5674873 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/GetProductCategoryBo.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.basedata.bo.product.category; + +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetProductCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 父级名称 + */ + @ApiModelProperty("父级名称") + private String parentName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetProductCategoryBo() { + + } + + public GetProductCategoryBo(ProductCategory dto) { + + super(dto); + } + + @Override + protected void afterInit(ProductCategory dto) { + + if (!StringUtil.isBlank(this.getParentId())) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory parentCategory = productCategoryService.findById(this.getParentId()); + if (!ObjectUtil.isNull(parentCategory)) { + this.setParentName(parentCategory.getName()); + } + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/ProductCategoryTreeBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/ProductCategoryTreeBo.java new file mode 100644 index 0000000..eeef7e7 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/category/ProductCategoryTreeBo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.basedata.bo.product.category; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ProductCategoryTreeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public ProductCategoryTreeBo() { + + } + + public ProductCategoryTreeBo(ProductCategory dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/GetProductBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/GetProductBo.java new file mode 100644 index 0000000..0fd52d2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/GetProductBo.java @@ -0,0 +1,306 @@ +package com.lframework.xingyun.basedata.bo.product.info; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.dto.product.ProductPropertyRelationDto; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.entity.ProductRetail; +import com.lframework.xingyun.basedata.entity.ProductSale; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyRelationService; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductRetailService; +import com.lframework.xingyun.basedata.service.product.ProductSaleService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 重量(kg) + */ + @ApiModelProperty("重量(kg)") + private BigDecimal weight; + + /** + * 体积(cm3) + */ + @ApiModelProperty("体积(cm3)") + private BigDecimal volume; + + /** + * 进项税率(%) + */ + @ApiModelProperty("进项税率(%)") + private BigDecimal taxRate; + + /** + * 销项税率(%) + */ + @ApiModelProperty("销项税率(%)") + private BigDecimal saleTaxRate; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 商品类型 + */ + @ApiModelProperty("商品类型") + @EnumConvert + private Integer productType; + + /** + * 单品 + */ + @ApiModelProperty("单品") + private List productBundles; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 销售价 + */ + @ApiModelProperty("销售价") + private BigDecimal salePrice; + + /** + * 零售价 + */ + @ApiModelProperty("零售价") + private BigDecimal retailPrice; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 属性 + */ + @ApiModelProperty("属性") + private List properties; + + public GetProductBo() { + + } + + public GetProductBo(Product dto) { + + super(dto); + } + + @Override + public BaseBo convert(Product dto) { + + return super.convert(dto, GetProductBo::getProperties); + } + + @Override + protected void afterInit(Product dto) { + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(dto.getCategoryId()); + this.categoryName = productCategory.getName(); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(dto.getBrandId()); + this.brandName = productBrand.getName(); + + if (dto.getProductType() == ProductType.BUNDLE) { + ProductBundleService productBundleService = ApplicationUtil.getBean( + ProductBundleService.class); + List bundles = productBundleService.getByMainProductId(dto.getId()); + this.productBundles = bundles.stream().map(ProductBundleBo::new).collect(Collectors.toList()); + } + + ProductPurchaseService productPurchaseService = ApplicationUtil.getBean( + ProductPurchaseService.class); + ProductPurchase productPurchase = productPurchaseService.getById(dto.getId()); + this.purchasePrice = productPurchase.getPrice(); + + ProductSaleService productSaleService = ApplicationUtil.getBean(ProductSaleService.class); + ProductSale productSale = productSaleService.getById(dto.getId()); + this.salePrice = productSale.getPrice(); + + ProductRetailService productRetailService = ApplicationUtil.getBean( + ProductRetailService.class); + ProductRetail productRetail = productRetailService.getById(dto.getId()); + this.retailPrice = productRetail.getPrice(); + + ProductPropertyRelationService productPropertyRelationService = ApplicationUtil.getBean( + ProductPropertyRelationService.class); + List propertyRelationDtos = productPropertyRelationService.getByProductId( + dto.getId()); + if (!CollectionUtil.isEmpty(propertyRelationDtos)) { + this.properties = new ArrayList<>(); + for (ProductPropertyRelationDto property : propertyRelationDtos) { + if (property.getPropertyColumnType() == ColumnType.MULTIPLE) { + PropertyBo propertyBo = this.properties.stream() + .filter(t -> t.getId().equals(property.getPropertyId())).findFirst().orElse(null); + if (propertyBo == null) { + this.properties.add(new PropertyBo(property)); + } else { + propertyBo.setText(propertyBo.getText().concat(StringPool.STR_SPLIT) + .concat(property.getPropertyItemId())); + propertyBo.setTextStr(propertyBo.getTextStr().concat(StringPool.STR_SPLIT_CN) + .concat(property.getPropertyText())); + } + } else { + this.properties.add(new PropertyBo(property)); + } + } + } + } + + @Data + public static class PropertyBo extends BaseBo { + + /** + * 属性ID + */ + @ApiModelProperty("属性ID") + private String id; + + /** + * 属性名 + */ + @ApiModelProperty("属性名") + private String name; + + /** + * 字段类型 + */ + @ApiModelProperty("字段类型") + private Integer columnType; + + /** + * 属性值 + */ + @ApiModelProperty("属性值") + private String text; + + /** + * 属性文本 + */ + @ApiModelProperty("属性文本") + private String textStr; + + public PropertyBo() { + + } + + public PropertyBo(ProductPropertyRelationDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(ProductPropertyRelationDto dto) { + + return super.convert(dto, PropertyBo::getColumnType); + } + + @Override + protected void afterInit(ProductPropertyRelationDto dto) { + + this.id = dto.getPropertyId(); + this.name = dto.getPropertyName(); + this.text = dto.getPropertyColumnType() == ColumnType.CUSTOM ? dto.getPropertyText() + : dto.getPropertyItemId(); + this.textStr = dto.getPropertyText(); + this.columnType = dto.getPropertyColumnType().getCode(); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductBundleBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductBundleBo.java new file mode 100644 index 0000000..f033441 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductBundleBo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.basedata.bo.product.info; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class ProductBundleBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单品ID + */ + @ApiModelProperty("单品ID") + private String productId; + + /** + * 包含数量 + */ + @ApiModelProperty("包含数量") + private Integer bundleNum; + + /** + * 销售价 + */ + @ApiModelProperty("销售价") + private BigDecimal salePrice; + + /** + * 零售价 + */ + @ApiModelProperty("零售价") + private BigDecimal retailPrice; + + public ProductBundleBo() { + } + + public ProductBundleBo(ProductBundle dto) { + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductSelectorBo.java new file mode 100644 index 0000000..2ad4c61 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/ProductSelectorBo.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.basedata.bo.product.info; + +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ProductSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 商品类型 + */ + @ApiModelProperty("商品类型") + @EnumConvert + private Integer productType; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public ProductSelectorBo() { + + } + + public ProductSelectorBo(Product dto) { + + super(dto); + } + + @Override + protected void afterInit(Product dto) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(dto.getCategoryId()); + this.categoryName = productCategory.getName(); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand brand = productBrandService.findById(dto.getBrandId()); + this.brandName = brand.getName(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/QueryProductBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/QueryProductBo.java new file mode 100644 index 0000000..c755cfe --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/info/QueryProductBo.java @@ -0,0 +1,109 @@ +package com.lframework.xingyun.basedata.bo.product.info; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 名称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 商品类型 + */ + @ApiModelProperty("商品类型") + @EnumConvert + private Integer productType; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryProductBo() { + + } + + public QueryProductBo(Product dto) { + + super(dto); + } + + @Override + protected void afterInit(Product dto) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(dto.getCategoryId()); + this.categoryName = productCategory.getName(); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand brand = productBrandService.findById(dto.getBrandId()); + this.brandName = brand.getName(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/GetProductPropertyBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/GetProductPropertyBo.java new file mode 100644 index 0000000..24e213b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/GetProductPropertyBo.java @@ -0,0 +1,105 @@ +package com.lframework.xingyun.basedata.bo.product.property; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.ProductCategoryProperty; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.enums.PropertyType; +import com.lframework.xingyun.basedata.service.product.ProductCategoryPropertyService; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetProductPropertyBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 是否必填 + */ + @ApiModelProperty("是否必填") + private Boolean isRequired; + + /** + * 录入类型 + */ + @ApiModelProperty("录入类型") + private Integer columnType; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer columnDataType; + + /** + * 属性类别 + */ + @ApiModelProperty("属性类别") + private Integer propertyType; + + /** + * 类目 + */ + @ApiModelProperty("类目") + private List categories; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetProductPropertyBo() { + + } + + public GetProductPropertyBo(ProductProperty dto) { + + super(dto); + } + + @Override + protected void afterInit(ProductProperty dto) { + + this.columnType = dto.getColumnType().getCode(); + this.propertyType = dto.getPropertyType().getCode(); + if (dto.getColumnDataType() != null) { + this.columnDataType = dto.getColumnDataType().getCode(); + } + + if (dto.getPropertyType() == PropertyType.APPOINT) { + ProductCategoryPropertyService productCategoryPropertyService = ApplicationUtil.getBean( + ProductCategoryPropertyService.class); + List categoryPropertyList = productCategoryPropertyService.getByPropertyId( + dto.getId()); + + this.categories = categoryPropertyList.stream().map(ProductCategoryProperty::getCategoryId) + .collect(Collectors.toList()); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/ProductPropertyModelorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/ProductPropertyModelorBo.java new file mode 100644 index 0000000..6ee6551 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/ProductPropertyModelorBo.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.basedata.bo.product.property; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.dto.product.property.ProductPropertyModelorDto; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class ProductPropertyModelorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 是否必填 + */ + @ApiModelProperty("是否必填") + private Boolean isRequired; + + /** + * 可选项,当columnType != CUSTOM时 不为空 + */ + @ApiModelProperty("可选项,当columnType != CUSTOM时 不为空") + private List items; + + /** + * 显示值 当columnType != CUSTOM时,此值为items项ID 当columnType == CUSTOM时,此值为录入值 + */ + @ApiModelProperty("显示值 当columnType != CUSTOM时,此值为items项ID 当columnType == CUSTOM时,此值为录入值") + private String text; + + /** + * 录入类型 + */ + @ApiModelProperty("录入类型") + private Integer columnType; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer columnDataType; + + /** + * 属性类别 + */ + @ApiModelProperty("属性类别") + private Integer propertyType; + + public ProductPropertyModelorBo() { + + } + + public ProductPropertyModelorBo(ProductPropertyModelorDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(ProductPropertyModelorDto dto) { + + return super.convert(dto, ProductPropertyModelorBo::getItems, ProductPropertyModelorBo::getColumnType, + ProductPropertyModelorBo::getColumnDataType, ProductPropertyModelorBo::getPropertyType); + } + + @Override + protected void afterInit(ProductPropertyModelorDto dto) { + + if (!CollectionUtil.isEmpty(dto.getItems())) { + this.items = dto.getItems().stream().map(ProductPropertyItemModelorBo::new).collect(Collectors.toList()); + } + + this.columnType = dto.getColumnType().getCode(); + if (dto.getColumnDataType() != null) { + this.columnDataType = dto.getColumnDataType().getCode(); + } + + this.propertyType = dto.getPropertyType().getCode(); + } + + @Data + public static class ProductPropertyItemModelorBo + extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public ProductPropertyItemModelorBo() { + + } + + public ProductPropertyItemModelorBo(ProductPropertyModelorDto.ProductPropertyItemModelorDto dto) { + + super(dto); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/QueryProductPropertyBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/QueryProductPropertyBo.java new file mode 100644 index 0000000..f29d752 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/QueryProductPropertyBo.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.basedata.bo.product.property; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryProductPropertyBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 是否必填 + */ + @ApiModelProperty("是否必填") + private Boolean isRequired; + + /** + * 录入类型 + */ + @ApiModelProperty("录入类型") + private Integer columnType; + + /** + * 属性类别 + */ + @ApiModelProperty("属性类别") + private Integer propertyType; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public QueryProductPropertyBo() { + + } + + public QueryProductPropertyBo(ProductProperty dto) { + + super(dto); + } + + @Override + protected void afterInit(ProductProperty dto) { + + this.columnType = dto.getColumnType().getCode(); + this.propertyType = dto.getPropertyType().getCode(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/GetProductPropertyItemBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/GetProductPropertyItemBo.java new file mode 100644 index 0000000..c68676f --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/GetProductPropertyItemBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.bo.product.property.item; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetProductPropertyItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetProductPropertyItemBo() { + + } + + public GetProductPropertyItemBo(ProductPropertyItem dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/QueryProductPropertyItemBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/QueryProductPropertyItemBo.java new file mode 100644 index 0000000..1326480 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/product/property/item/QueryProductPropertyItemBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.bo.product.property.item; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryProductPropertyItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public QueryProductPropertyItemBo() { + + } + + public QueryProductPropertyItemBo(ProductPropertyItem dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/GetShopBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/GetShopBo.java new file mode 100644 index 0000000..256466b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/GetShopBo.java @@ -0,0 +1,96 @@ +package com.lframework.xingyun.basedata.bo.shop; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.template.core.dto.DeptDto; +import com.lframework.xingyun.template.core.service.DeptService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * 门店 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetShopBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 所属部门ID + */ + @ApiModelProperty("所属部门ID") + private String deptId; + + /** + * 所属部门名称 + */ + @ApiModelProperty("所属部门名称") + private String deptName; + + /** + * 经度 + */ + @ApiModelProperty("经度") + private BigDecimal lng; + + /** + * 纬度 + */ + @ApiModelProperty("纬度") + private BigDecimal lat; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetShopBo() { + + } + + public GetShopBo(Shop dto) { + + super(dto); + } + + @Override + protected void afterInit(Shop dto) { + if (!StringUtil.isBlank(dto.getDeptId())) { + DeptService deptService = ApplicationUtil.getBean(DeptService.class); + + DeptDto dept = deptService.findById(dto.getDeptId()); + + this.deptName = dept.getName(); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/QueryShopBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/QueryShopBo.java new file mode 100644 index 0000000..a10f8dc --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/QueryShopBo.java @@ -0,0 +1,93 @@ +package com.lframework.xingyun.basedata.bo.shop; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.template.core.dto.DeptDto; +import com.lframework.xingyun.template.core.service.DeptService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 门店 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryShopBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 所属部门名称 + */ + @ApiModelProperty("所属部门名称") + private String deptName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryShopBo() { + + } + + public QueryShopBo(Shop dto) { + + super(dto); + } + + @Override + protected void afterInit(Shop dto) { + if (!StringUtil.isBlank(dto.getDeptId())) { + DeptService deptService = ApplicationUtil.getBean(DeptService.class); + + DeptDto dept = deptService.findById(dto.getDeptId()); + + this.deptName = dept.getName(); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/ShopSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/ShopSelectorBo.java new file mode 100644 index 0000000..322e70e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/shop/ShopSelectorBo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.basedata.bo.shop; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Shop; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 门店选择器 Bo + *

+ * + * @author zmj + */ +@Data +public class ShopSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public ShopSelectorBo() { + + } + + public ShopSelectorBo(Shop dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/GetStoreCenterBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/GetStoreCenterBo.java new file mode 100644 index 0000000..8755762 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/GetStoreCenterBo.java @@ -0,0 +1,105 @@ +package com.lframework.xingyun.basedata.bo.storecenter; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetStoreCenterBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系人手机号码 + */ + @ApiModelProperty("联系人手机号码") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private List city; + + /** + * 地区名称 + */ + @ApiModelProperty("地区名称") + private String cityName; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 仓库人数 + */ + @ApiModelProperty("仓库人数") + private Integer peopleNum; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetStoreCenterBo() { + + } + + public GetStoreCenterBo(StoreCenter dto) { + + super(dto); + } + + @Override + protected void afterInit(StoreCenter dto) { + + if (!StringUtil.isBlank(dto.getCityId())) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List cityList = dicCityService.getChainById(dto.getCityId()); + this.city = cityList.stream().map(DicCityDto::getId).collect(Collectors.toList()); + + this.cityName = cityList.stream().map(DicCityDto::getName) + .collect(Collectors.joining(StringPool.CITY_SPLIT)); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/QueryStoreCenterBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/QueryStoreCenterBo.java new file mode 100644 index 0000000..972ee16 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/QueryStoreCenterBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.bo.storecenter; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryStoreCenterBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryStoreCenterBo() { + + } + + public QueryStoreCenterBo(StoreCenter dto) { + + super(dto); + } + + @Override + protected void afterInit(StoreCenter dto) { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/StoreCenterSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/StoreCenterSelectorBo.java new file mode 100644 index 0000000..362e3e1 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/storecenter/StoreCenterSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.bo.storecenter; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class StoreCenterSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public StoreCenterSelectorBo() { + + } + + public StoreCenterSelectorBo(StoreCenter dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/GetSupplierBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/GetSupplierBo.java new file mode 100644 index 0000000..c6b5616 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/GetSupplierBo.java @@ -0,0 +1,185 @@ +package com.lframework.xingyun.basedata.bo.supplier; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSupplierBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 助记码 + */ + @ApiModelProperty("助记码") + private String mnemonicCode; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + private String email; + + /** + * 邮编 + */ + @ApiModelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ApiModelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private List city; + + /** + * 地区名称 + */ + @ApiModelProperty("地区名称") + private String cityName; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 送货周期(天) + */ + @ApiModelProperty("送货周期(天)") + private Integer deliveryCycle; + + /** + * 经营方式 + */ + @ApiModelProperty("经营方式") + private Integer manageType; + + /** + * 结账方式 + */ + @ApiModelProperty("结账方式") + private Integer settleType; + + /** + * 统一社会信用代码 + */ + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ApiModelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ApiModelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ApiModelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ApiModelProperty("银行账号") + private String accountNo; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSupplierBo() { + + } + + public GetSupplierBo(Supplier dto) { + + super(dto); + } + + @Override + public BaseBo convert(Supplier dto) { + + return super.convert(dto, GetSupplierBo::getSettleType, GetSupplierBo::getManageType); + } + + @Override + protected void afterInit(Supplier dto) { + + if (dto.getManageType() != null) { + this.manageType = dto.getManageType().getCode(); + } + + if (dto.getSettleType() != null) { + this.settleType = dto.getSettleType().getCode(); + } + + if (!StringUtil.isBlank(dto.getCityId())) { + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List cityList = dicCityService.getChainById(dto.getCityId()); + this.city = cityList.stream().map(DicCityDto::getId).collect(Collectors.toList()); + + this.cityName = cityList.stream().map(DicCityDto::getName) + .collect(Collectors.joining(StringPool.CITY_SPLIT)); + } + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/QuerySupplierBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/QuerySupplierBo.java new file mode 100644 index 0000000..c88dbdf --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/QuerySupplierBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.bo.supplier; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Supplier; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySupplierBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySupplierBo() { + + } + + public QuerySupplierBo(Supplier dto) { + + super(dto); + } + + @Override + protected void afterInit(Supplier dto) { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/SupplierSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/SupplierSelectorBo.java new file mode 100644 index 0000000..745e218 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/supplier/SupplierSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.bo.supplier; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.basedata.entity.Supplier; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SupplierSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SupplierSelectorBo() { + + } + + public SupplierSelectorBo(Supplier dto) { + + super(dto); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/AddressController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/AddressController.java new file mode 100644 index 0000000..edf63b6 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/AddressController.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.address.GetAddressBo; +import com.lframework.xingyun.basedata.bo.address.QueryAddressBo; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.excel.address.AddressExportModel; +import com.lframework.xingyun.basedata.excel.address.AddressImportListener; +import com.lframework.xingyun.basedata.excel.address.AddressImportModel; +import com.lframework.xingyun.basedata.service.address.AddressService; +import com.lframework.xingyun.basedata.vo.address.CreateAddressVo; +import com.lframework.xingyun.basedata.vo.address.QueryAddressVo; +import com.lframework.xingyun.basedata.vo.address.UpdateAddressVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 地址库 + * + * @author zmj + */ +@Api(tags = "地址库") +@Validated +@RestController +@RequestMapping("/basedata/address") +public class AddressController extends DefaultBaseController { + + @Autowired + private AddressService addressService; + + /** + * 地址列表 + */ + @ApiOperation("地址列表") + @HasPermission({"base-data:address:query", "base-data:address:add", "base-data:address:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryAddressVo vo) { + + PageResult
pageResult = addressService.query(getPageIndex(vo), getPageSize(vo), vo); + + List
datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryAddressBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询地址 + */ + @ApiOperation("查询地址") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:address:query", "base-data:address:add", "base-data:address:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + Address data = addressService.findById(id); + if (data == null) { + throw new DefaultClientException("地址不存在!"); + } + + GetAddressBo result = new GetAddressBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增地址 + */ + @ApiOperation("新增地址") + @HasPermission({"base-data:address:add"}) + @PostMapping + public InvokeResult create(@Valid CreateAddressVo vo) { + + addressService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改地址 + */ + @ApiOperation("修改地址") + @HasPermission({"base-data:address:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateAddressVo vo) { + + addressService.update(vo); + + addressService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"base-data:address:export"}) + @PostMapping("/export") + public void export(@Valid QueryAddressVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("地址信息", + AddressExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult
pageResult = addressService.query(pageIndex, getExportSize(), vo); + List
datas = pageResult.getDatas(); + List models = datas.stream().map(AddressExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:address:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("地址导入模板", AddressImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:address:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + AddressImportListener listener = new AddressImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, AddressImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/BaseDataSelectorController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/BaseDataSelectorController.java new file mode 100644 index 0000000..b68b3c0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/BaseDataSelectorController.java @@ -0,0 +1,594 @@ +package com.lframework.xingyun.basedata.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.basedata.bo.address.AddressSelectorBo; +import com.lframework.xingyun.basedata.bo.customer.CustomerSelectorBo; +import com.lframework.xingyun.basedata.bo.logistics.company.LogisticsCompanySelectorBo; +import com.lframework.xingyun.basedata.bo.member.MemberSelectorBo; +import com.lframework.xingyun.basedata.bo.paytype.PayTypeSelectorBo; +import com.lframework.xingyun.basedata.bo.product.brand.ProductBrandSelectorBo; +import com.lframework.xingyun.basedata.bo.product.brand.ProductCategorySelectorBo; +import com.lframework.xingyun.basedata.bo.product.info.ProductSelectorBo; +import com.lframework.xingyun.basedata.bo.shop.ShopSelectorBo; +import com.lframework.xingyun.basedata.bo.storecenter.StoreCenterSelectorBo; +import com.lframework.xingyun.basedata.bo.supplier.SupplierSelectorBo; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import com.lframework.xingyun.basedata.service.address.AddressService; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.logistics.LogisticsCompanyService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.basedata.vo.address.AddressSelectorVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerSelectorVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanySelectorVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberSelectorVo; +import com.lframework.xingyun.basedata.vo.paytype.PayTypeSelectorVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandSelectorVo; +import com.lframework.xingyun.basedata.vo.product.category.QueryProductCategorySelectorVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductSelectorVo; +import com.lframework.xingyun.basedata.vo.shop.ShopSelectorVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterSelectorVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierSelectorVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 基础数据数据选择器 + * + * @author zmj + */ +@Api(tags = "基础数据数据选择器") +@Validated +@RestController +@RequestMapping("/selector") +public class BaseDataSelectorController extends DefaultBaseController { + + @Autowired + private ProductBrandService productBrandService; + + @Autowired + private ProductCategoryService productCategoryService; + + @Autowired + private MemberService memberService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private SupplierService supplierService; + + @Autowired + private CustomerService customerService; + + @Autowired + private ShopService shopService; + + @Autowired + private AddressService addressService; + + @Autowired + private PayTypeService payTypeService; + + @Autowired + private ProductService productService; + + @Autowired + private LogisticsCompanyService logisticsCompanyService; + + /** + * 商品 + */ + @ApiOperation("商品") + @GetMapping("/product") + public InvokeResult> product( + @Valid QueryProductSelectorVo vo) { + + PageResult pageResult = productService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(ProductSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载商品 + */ + @ApiOperation("加载商品") + @PostMapping("/product/load") + public InvokeResult> loadProduct( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> productService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(ProductSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 品牌 + */ + @ApiOperation("品牌") + @GetMapping("/brand") + public InvokeResult> brand( + @Valid QueryProductBrandSelectorVo vo) { + + PageResult pageResult = productBrandService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(ProductBrandSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载品牌 + */ + @ApiOperation("加载品牌") + @PostMapping("/brand/load") + public InvokeResult> loadBrand( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> productBrandService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(ProductBrandSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 类目 + */ + @ApiOperation("类目") + @GetMapping("/category") + public InvokeResult> category( + @Valid QueryProductCategorySelectorVo vo) { + + List datas = productCategoryService.selector(vo); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(ProductCategorySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 加载类目 + */ + @ApiOperation("加载类目") + @PostMapping("/category/load") + public InvokeResult> loadCustomList( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> productCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(ProductCategorySelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 会员 + */ + @ApiOperation("会员") + @GetMapping("/member") + public InvokeResult> selector(@Valid QueryMemberSelectorVo vo) { + + PageResult pageResult = memberService.selector(getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(MemberSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载会员 + */ + @ApiOperation("加载会员") + @PostMapping("/member/load") + public InvokeResult> loadMember( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> memberService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(MemberSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 仓库 + */ + @ApiOperation("仓库") + @GetMapping("/sc") + public InvokeResult> selector( + @Valid QueryStoreCenterSelectorVo vo) { + + PageResult pageResult = storeCenterService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(StoreCenterSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载仓库 + */ + @ApiOperation("加载仓库") + @PostMapping("/sc/load") + public InvokeResult> loadSc( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> storeCenterService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(StoreCenterSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 供应商 + */ + @ApiOperation("供应商") + @GetMapping("/supplier") + public InvokeResult> selector(@Valid QuerySupplierSelectorVo vo) { + + PageResult pageResult = supplierService.selector(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SupplierSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载供应商 + */ + @ApiOperation("加载供应商") + @PostMapping("/supplier/load") + public InvokeResult> loadSupplier( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> supplierService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SupplierSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 客户 + */ + @ApiOperation("客户") + @GetMapping("/customer") + public InvokeResult> selector(@Valid QueryCustomerSelectorVo vo) { + + PageResult pageResult = customerService.selector(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(CustomerSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载客户 + */ + @ApiOperation("加载客户") + @PostMapping("/customer/load") + public InvokeResult> loadCustomer( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> customerService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(CustomerSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 门店 + */ + @ApiOperation("门店") + @GetMapping("/shop") + public InvokeResult> selector(@Valid ShopSelectorVo vo) { + + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Shop.class) + .orderByAsc(Shop::getCode); + if (!StringUtil.isEmpty(vo.getCode())) { + queryWrapper.eq(Shop::getCode, vo.getCode()); + } + if (!StringUtil.isEmpty(vo.getName())) { + queryWrapper.like(Shop::getName, vo.getName()); + } + if (vo.getAvailable() != null) { + queryWrapper.eq(Shop::getAvailable, vo.getAvailable()); + } + + Page page = new Page<>(getPageIndex(vo), getPageSize(vo)); + page = shopService.page(page, queryWrapper); + + PageResult pageResult = PageResultUtil.convert(page); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(ShopSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载门店 + */ + @ApiOperation("加载门店") + @PostMapping("/shop/load") + public InvokeResult> loadShop( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> shopService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(ShopSelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 地址 + */ + @ApiOperation("地址") + @GetMapping("/address") + public InvokeResult> selector(@Valid AddressSelectorVo vo) { + + PageResult
pageResult = addressService.selector(getPageIndex(vo), getPageSize(vo), + vo); + + List
datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(AddressSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载地址 + */ + @ApiOperation("加载地址") + @PostMapping("/address/load") + public InvokeResult> loadAddress( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List
datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> addressService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(AddressSelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 默认地址 + */ + @ApiOperation("默认地址") + @GetMapping("/address/default") + public InvokeResult selector( + @NotBlank(message = "实体ID不能为空!") String entityId, + @NotNull(message = "实体类型不能为空!") @IsEnum(message = "实体类型格式错误!", enumClass = AddressEntityType.class) Integer entityType, + @NotNull(message = "地址类型不能为空!") @IsEnum(message = "地址类型格式错误!", enumClass = AddressType.class) Integer addressType) { + + Wrapper
queryWrapper = Wrappers.lambdaQuery(Address.class) + .eq(Address::getEntityId, entityId).eq(Address::getEntityType, entityType) + .eq(Address::getAddressType, addressType) + .eq(Address::getIsDefault, Boolean.TRUE); + Address address = addressService.getOne(queryWrapper); + + return InvokeResultBuilder.success(address == null ? null : new AddressSelectorBo(address)); + } + + /** + * 支付方式 + */ + @ApiOperation("支付方式") + @GetMapping("/paytype") + public InvokeResult> selector(@Valid PayTypeSelectorVo vo) { + + PageResult pageResult = payTypeService.selector(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(PayTypeSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载支付方式 + */ + @ApiOperation("加载支付方式") + @PostMapping("/paytype/load") + public InvokeResult> loadPayType( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> payTypeService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(PayTypeSelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 物流公司 + */ + @ApiOperation("物流公司") + @GetMapping("/logistics/company") + public InvokeResult> selector( + @Valid QueryLogisticsCompanySelectorVo vo) { + + PageResult pageResult = logisticsCompanyService.selector(getPageIndex(vo), + getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(LogisticsCompanySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载物流公司 + */ + @ApiOperation("加载物流公司") + @PostMapping("/logistics/company/load") + public InvokeResult> loadLogisticsCompany( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> logisticsCompanyService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(LogisticsCompanySelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/CustomerController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/CustomerController.java new file mode 100644 index 0000000..31f561a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/CustomerController.java @@ -0,0 +1,180 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.customer.GetCustomerBo; +import com.lframework.xingyun.basedata.bo.customer.QueryCustomerBo; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.excel.customer.CustomerImportListener; +import com.lframework.xingyun.basedata.excel.customer.CustomerImportModel; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.vo.customer.CreateCustomerVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo; +import com.lframework.xingyun.basedata.vo.customer.UpdateCustomerVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 客户管理 + * + * @author zmj + */ +@Api(tags = "客户管理") +@Validated +@RestController +@RequestMapping("/basedata/customer") +public class CustomerController extends DefaultBaseController { + + @Autowired + private CustomerService customerService; + + /** + * 客户列表 + */ + @ApiOperation("客户列表") + @HasPermission({"base-data:customer:query", "base-data:customer:add", + "base-data:customer:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryCustomerVo vo) { + + PageResult pageResult = customerService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryCustomerBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询客户 + */ + @ApiOperation("查询客户") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:customer:query", "base-data:customer:add", + "base-data:customer:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + Customer data = customerService.findById(id); + if (data == null) { + throw new DefaultClientException("客户不存在!"); + } + + GetCustomerBo result = new GetCustomerBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用客户 + */ + @ApiOperation("批量停用客户") + @HasPermission({"base-data:customer:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的客户!") @RequestBody List ids) { + + customerService.batchUnable(ids); + + for (String id : ids) { + customerService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用客户 + */ + @ApiOperation("批量启用客户") + @HasPermission({"base-data:customer:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的客户!") @RequestBody List ids) { + + customerService.batchEnable(ids); + + for (String id : ids) { + customerService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增客户 + */ + @ApiOperation("新增客户") + @HasPermission({"base-data:customer:add"}) + @PostMapping + public InvokeResult create(@Valid CreateCustomerVo vo) { + + customerService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改客户 + */ + @ApiOperation("修改客户") + @HasPermission({"base-data:customer:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateCustomerVo vo) { + + customerService.update(vo); + + customerService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:customer:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("客户导入模板", CustomerImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:customer:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + CustomerImportListener listener = new CustomerImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, CustomerImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/LogisticsCompanyController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/LogisticsCompanyController.java new file mode 100644 index 0000000..05d3ae5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/LogisticsCompanyController.java @@ -0,0 +1,158 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.basedata.bo.logistics.company.GetLogisticsCompanyBo; +import com.lframework.xingyun.basedata.bo.logistics.company.QueryLogisticsCompanyBo; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.service.logistics.LogisticsCompanyService; +import com.lframework.xingyun.basedata.vo.logistics.company.CreateLogisticsCompanyVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanyVo; +import com.lframework.xingyun.basedata.vo.logistics.company.UpdateLogisticsCompanyVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 物流公司管理 + * + * @author zmj + */ +@Api(tags = "物流公司管理") +@Validated +@RestController +@RequestMapping("/basedata/logistics/company") +public class LogisticsCompanyController extends DefaultBaseController { + + @Autowired + private LogisticsCompanyService logisticsCompanyService; + + /** + * 物流公司列表 + */ + @ApiOperation("物流公司列表") + @HasPermission({"base-data:logistics-company:query", "base-data:logistics-company:add", + "base-data:logistics-company:modify"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryLogisticsCompanyVo vo) { + + PageResult pageResult = logisticsCompanyService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryLogisticsCompanyBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询物流公司 + */ + @ApiOperation("查询物流公司") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:logistics-company:query", "base-data:logistics-company:add", + "base-data:logistics-company:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + LogisticsCompany data = logisticsCompanyService.findById(id); + if (data == null) { + throw new DefaultClientException("物流公司不存在!"); + } + + GetLogisticsCompanyBo result = new GetLogisticsCompanyBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用物流公司 + */ + @ApiOperation("批量停用物流公司") + @HasPermission({"base-data:logistics-company:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的物流公司!") @RequestBody List ids) { + + logisticsCompanyService.batchUnable(ids); + + for (String id : ids) { + logisticsCompanyService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用物流公司 + */ + @ApiOperation("批量启用物流公司") + @HasPermission({"base-data:logistics-company:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的物流公司!") @RequestBody List ids) { + + logisticsCompanyService.batchEnable(ids); + + for (String id : ids) { + logisticsCompanyService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增物流公司 + */ + @ApiOperation("新增物流公司") + @HasPermission({"base-data:logistics-company:add"}) + @PostMapping + public InvokeResult create(@Valid CreateLogisticsCompanyVo vo) { + + logisticsCompanyService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改物流公司 + */ + @ApiOperation("修改物流公司") + @HasPermission({"base-data:logistics-company:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateLogisticsCompanyVo vo) { + + logisticsCompanyService.update(vo); + + logisticsCompanyService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/MemberController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/MemberController.java new file mode 100644 index 0000000..39efc04 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/MemberController.java @@ -0,0 +1,178 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.member.GetMemberBo; +import com.lframework.xingyun.basedata.bo.member.QueryMemberBo; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.excel.member.MemberImportListener; +import com.lframework.xingyun.basedata.excel.member.MemberImportModel; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.vo.member.CreateMemberVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberVo; +import com.lframework.xingyun.basedata.vo.member.UpdateMemberVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 会员管理 + * + * @author zmj + */ +@Api(tags = "会员管理") +@Validated +@RestController +@RequestMapping("/basedata/member") +public class MemberController extends DefaultBaseController { + + @Autowired + private MemberService memberService; + + /** + * 会员列表 + */ + @ApiOperation("会员列表") + @HasPermission({"base-data:member:query", "base-data:member:add", "base-data:member:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryMemberVo vo) { + + PageResult pageResult = memberService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryMemberBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询会员 + */ + @ApiOperation("查询会员") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:member:query", "base-data:member:add", "base-data:member:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + Member data = memberService.findById(id); + if (data == null) { + throw new DefaultClientException("会员不存在!"); + } + + GetMemberBo result = new GetMemberBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用会员 + */ + @ApiOperation("批量停用会员") + @HasPermission({"base-data:member:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的会员!") @RequestBody List ids) { + + memberService.batchUnable(ids); + + for (String id : ids) { + memberService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用会员 + */ + @ApiOperation("批量启用会员") + @HasPermission({"base-data:member:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的会员!") @RequestBody List ids) { + + memberService.batchEnable(ids); + + for (String id : ids) { + memberService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增会员 + */ + @ApiOperation("新增会员") + @HasPermission({"base-data:member:add"}) + @PostMapping + public InvokeResult create(@Valid CreateMemberVo vo) { + + String id = memberService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改会员 + */ + @ApiOperation("修改会员") + @HasPermission({"base-data:member:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateMemberVo vo) { + + memberService.update(vo); + + memberService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:member:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("会员导入模板", MemberImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:member:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + MemberImportListener listener = new MemberImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, MemberImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/PayTypeController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/PayTypeController.java new file mode 100644 index 0000000..8c9e3e8 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/PayTypeController.java @@ -0,0 +1,115 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.basedata.bo.paytype.GetPayTypeBo; +import com.lframework.xingyun.basedata.bo.paytype.QueryPayTypeBo; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.vo.paytype.CreatePayTypeVo; +import com.lframework.xingyun.basedata.vo.paytype.QueryPayTypeVo; +import com.lframework.xingyun.basedata.vo.paytype.UpdatePayTypeVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 支付方式管理 + * + * @author zmj + */ +@Api(tags = "支付方式管理") +@Validated +@RestController +@RequestMapping("/basedata/paytype") +public class PayTypeController extends DefaultBaseController { + + @Autowired + private PayTypeService payTypeService; + + /** + * 支付方式列表 + */ + @ApiOperation("支付方式列表") + @HasPermission({"base-data:pay-type:query", "base-data:pay-type:add", + "base-data:pay-type:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryPayTypeVo vo) { + + PageResult pageResult = payTypeService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryPayTypeBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询支付方式 + */ + @ApiOperation("查询支付方式") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:pay-type:query", "base-data:pay-type:add", + "base-data:pay-type:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + PayType data = payTypeService.findById(id); + if (data == null) { + throw new DefaultClientException("支付方式不存在!"); + } + + GetPayTypeBo result = new GetPayTypeBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增支付方式 + */ + @ApiOperation("新增支付方式") + @HasPermission({"base-data:pay-type:add"}) + @PostMapping + public InvokeResult create(@Valid CreatePayTypeVo vo) { + + payTypeService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改支付方式 + */ + @ApiOperation("修改支付方式") + @HasPermission({"base-data:pay-type:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdatePayTypeVo vo) { + + payTypeService.update(vo); + + payTypeService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductBrandController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductBrandController.java new file mode 100644 index 0000000..3e62db8 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductBrandController.java @@ -0,0 +1,183 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.product.brand.GetProductBrandBo; +import com.lframework.xingyun.basedata.bo.product.brand.QueryProductBrandBo; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.excel.product.brand.ProductBrandImportListener; +import com.lframework.xingyun.basedata.excel.product.brand.ProductBrandImportModel; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.vo.product.brand.CreateProductBrandVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandVo; +import com.lframework.xingyun.basedata.vo.product.brand.UpdateProductBrandVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 品牌管理 + * + * @author zmj + */ +@Api(tags = "品牌管理") +@Validated +@RestController +@RequestMapping("/basedata/product/brand") +public class ProductBrandController extends DefaultBaseController { + + @Autowired + private ProductBrandService productBrandService; + + /** + * 品牌列表 + */ + @ApiOperation("品牌列表") + @HasPermission({"base-data:product:brand:query", "base-data:product:brand:add", + "base-data:product:brand:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryProductBrandVo vo) { + + PageResult pageResult = productBrandService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryProductBrandBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + + /** + * 查询品牌 + */ + @ApiOperation("查询品牌") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:product:brand:query", "base-data:product:brand:add", + "base-data:product:brand:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + ProductBrand data = productBrandService.findById(id); + if (data == null) { + throw new DefaultClientException("品牌不存在!"); + } + + GetProductBrandBo result = new GetProductBrandBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用品牌 + */ + @ApiOperation("批量停用品牌") + @HasPermission({"base-data:product:brand:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的品牌!") @RequestBody List ids) { + + productBrandService.batchUnable(ids); + + for (String id : ids) { + productBrandService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用品牌 + */ + @ApiOperation("批量启用品牌") + @HasPermission({"base-data:product:brand:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的品牌!") @RequestBody List ids) { + + productBrandService.batchEnable(ids); + + for (String id : ids) { + productBrandService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增品牌 + */ + @ApiOperation("新增品牌") + @HasPermission({"base-data:product:brand:add"}) + @PostMapping + public InvokeResult create(@Valid CreateProductBrandVo vo) { + + productBrandService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改品牌 + */ + @ApiOperation("修改品牌") + @HasPermission({"base-data:product:brand:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateProductBrandVo vo) { + + productBrandService.update(vo); + + productBrandService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:product:brand:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("品牌导入模板", ProductBrandImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:product:brand:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + ProductBrandImportListener listener = new ProductBrandImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, ProductBrandImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductCategoryController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductCategoryController.java new file mode 100644 index 0000000..e2e454d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductCategoryController.java @@ -0,0 +1,202 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.product.category.GetProductCategoryBo; +import com.lframework.xingyun.basedata.bo.product.category.ProductCategoryTreeBo; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.enums.ProductCategoryNodeType; +import com.lframework.xingyun.basedata.excel.product.category.ProductCategoryImportListener; +import com.lframework.xingyun.basedata.excel.product.category.ProductCategoryImportModel; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.vo.product.category.CreateProductCategoryVo; +import com.lframework.xingyun.basedata.vo.product.category.UpdateProductCategoryVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 类目管理 + * + * @author zmj + */ +@Api(tags = "类目管理") +@Validated +@RestController +@RequestMapping("/basedata/product/category") +public class ProductCategoryController extends DefaultBaseController { + + @Autowired + private ProductCategoryService productCategoryService; + + @Autowired + private RecursionMappingService recursionMappingService; + + /** + * 类目列表 + */ + @ApiOperation("类目列表") + @HasPermission({"base-data:product:category:query", "base-data:product:category:add", + "base-data:product:category:modify"}) + @GetMapping("/query") + public InvokeResult> query() { + + List datas = productCategoryService.getAllProductCategories(); + if (CollectionUtil.isEmpty(datas)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List results = datas.stream().map(ProductCategoryTreeBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 查询类目 + */ + @ApiOperation("查询类目") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:product:category:query", "base-data:product:category:add", + "base-data:product:category:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + ProductCategory data = productCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("类目不存在!"); + } + + GetProductCategoryBo result = new GetProductCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用类目 + */ + @ApiOperation("批量停用类目") + @HasPermission({"base-data:product:category:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的类目!") @RequestBody List ids) { + + productCategoryService.batchUnable(ids); + return InvokeResultBuilder.success(); + } + + /** + * 批量启用类目 + */ + @ApiOperation("批量启用类目") + @HasPermission({"base-data:product:category:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的类目!") @RequestBody List ids) { + + productCategoryService.batchEnable(ids); + + for (String id : ids) { + productCategoryService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增类目 + */ + @ApiOperation("新增类目") + @HasPermission({"base-data:product:category:add"}) + @PostMapping + public InvokeResult create(@Valid CreateProductCategoryVo vo) { + + productCategoryService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改类目 + */ + @ApiOperation("修改类目") + @HasPermission({"base-data:product:category:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateProductCategoryVo vo) { + + productCategoryService.update(vo); + + productCategoryService.cleanCacheByKey(vo.getId()); + + ProductCategory data = productCategoryService.findById(vo.getId()); + if (!vo.getAvailable()) { + if (data.getAvailable()) { + //如果是停用 子节点全部停用 + List childrenIds = recursionMappingService.getNodeChildIds(data.getId(), + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (!CollectionUtil.isEmpty(childrenIds)) { + for (String childrenId : childrenIds) { + productCategoryService.cleanCacheByKey(childrenId); + } + } + } + } else { + if (!data.getAvailable()) { + //如果是启用 父节点全部启用 + List parentIds = recursionMappingService.getNodeParentIds(data.getId(), + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (!CollectionUtil.isEmpty(parentIds)) { + for (String parentId : parentIds) { + productCategoryService.cleanCacheByKey(parentId); + } + } + } + } + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:product:category:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("类目导入模板", ProductCategoryImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:product:category:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + ProductCategoryImportListener listener = new ProductCategoryImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, ProductCategoryImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductController.java new file mode 100644 index 0000000..d33c77a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductController.java @@ -0,0 +1,150 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.product.info.GetProductBo; +import com.lframework.xingyun.basedata.bo.product.info.QueryProductBo; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.excel.product.ProductImportListener; +import com.lframework.xingyun.basedata.excel.product.ProductImportModel; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyRelationService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.vo.product.info.CreateProductVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductVo; +import com.lframework.xingyun.basedata.vo.product.info.UpdateProductVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 商品管理 + * + * @author zmj + */ +@Api(tags = "商品管理") +@Validated +@RestController +@RequestMapping("/basedata/product") +public class ProductController extends DefaultBaseController { + + @Autowired + private ProductService productService; + + @Autowired + private ProductBundleService productBundleService; + + @Autowired + private ProductPropertyRelationService productPropertyRelationService; + + /** + * 商品列表 + */ + @ApiOperation("商品列表") + @HasPermission({"base-data:product:info:query", "base-data:product:info:add", + "base-data:product:info:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryProductVo vo) { + + PageResult pageResult = productService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryProductBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 商品详情 + */ + @ApiOperation("商品详情") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:product:info:query", "base-data:product:info:add", + "base-data:product:info:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + Product data = productService.findById(id); + + GetProductBo result = new GetProductBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增商品 + */ + @ApiOperation("新增商品") + @HasPermission({"base-data:product:info:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateProductVo vo) { + + productService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改商品 + */ + @ApiOperation("修改商品") + @HasPermission({"base-data:product:info:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateProductVo vo) { + + productService.update(vo); + + productService.cleanCacheByKey(vo.getId()); + + productPropertyRelationService.cleanCacheByKey(vo.getId()); + + productBundleService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:product:info:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("商品导入模板", ProductImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:product:info:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + ProductImportListener listener = new ProductImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, ProductImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyController.java new file mode 100644 index 0000000..5eb32d5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyController.java @@ -0,0 +1,201 @@ +package com.lframework.xingyun.basedata.controller; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.threads.DefaultRunnable; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.basedata.bo.product.property.GetProductPropertyBo; +import com.lframework.xingyun.basedata.bo.product.property.ProductPropertyModelorBo; +import com.lframework.xingyun.basedata.bo.product.property.QueryProductPropertyBo; +import com.lframework.xingyun.basedata.dto.product.property.ProductPropertyModelorDto; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.entity.ProductPropertyRelation; +import com.lframework.xingyun.basedata.service.product.ProductPropertyRelationService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyService; +import com.lframework.xingyun.basedata.vo.product.property.CreateProductPropertyVo; +import com.lframework.xingyun.basedata.vo.product.property.QueryProductPropertyVo; +import com.lframework.xingyun.basedata.vo.product.property.UpdateProductPropertyVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 属性管理 + * + * @author zmj + */ +@Api(tags = "属性管理") +@Validated +@RestController +@RequestMapping("/basedata/product/property") +public class ProductPropertyController extends DefaultBaseController { + + @Autowired + private ProductPropertyService productPropertyService; + + @Autowired + private ProductPropertyRelationService productPropertyRelationService; + + /** + * 属性列表 + */ + @ApiOperation("属性列表") + @HasPermission({"base-data:product:property:query", "base-data:product:property:add", + "base-data:product:property:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryProductPropertyVo vo) { + + PageResult pageResult = productPropertyService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryProductPropertyBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询属性 + */ + @ApiOperation("查询属性") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:product:property:query", "base-data:product:property:add", + "base-data:product:property:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + ProductProperty data = productPropertyService.findById(id); + if (data == null) { + throw new DefaultClientException("属性不存在!"); + } + + GetProductPropertyBo result = new GetProductPropertyBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用属性 + */ + @ApiOperation("批量停用属性") + @HasPermission({"base-data:product:property:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的属性!") @RequestBody List ids) { + + productPropertyService.batchUnable(ids); + + for (String id : ids) { + productPropertyService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用属性 + */ + @ApiOperation("批量启用属性") + @HasPermission({"base-data:product:property:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的属性!") @RequestBody List ids) { + + productPropertyService.batchEnable(ids); + + for (String id : ids) { + productPropertyService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增属性 + */ + @ApiOperation("新增属性") + @HasPermission({"base-data:product:property:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateProductPropertyVo vo) { + + productPropertyService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改属性 + */ + @ApiOperation("修改属性") + @HasPermission({"base-data:product:property:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateProductPropertyVo vo) { + + productPropertyService.update(vo); + + productPropertyService.cleanCacheByKey(vo.getId()); + + ThreadUtil.execAsync(new DefaultRunnable((() -> { + Wrapper relationWrapper = Wrappers.lambdaQuery( + ProductPropertyRelation.class).select(ProductPropertyRelation::getProductId) + .eq(ProductPropertyRelation::getPropertyId, vo.getId()) + .groupBy(ProductPropertyRelation::getProductId); + List relations = productPropertyRelationService.list( + relationWrapper); + + productPropertyRelationService.cleanCacheByKeys( + relations.stream().map(ProductPropertyRelation::getProductId).collect( + Collectors.toList())); + }))); + + return InvokeResultBuilder.success(); + } + + /** + * 属性模型 + */ + @ApiOperation("属性模型") + @ApiImplicitParam(value = "类目ID", name = "categoryId", paramType = "query", required = true) + @GetMapping("/modelor/category") + public InvokeResult> getModelorByCategory( + @NotBlank(message = "类目ID不能为空!") String categoryId) { + + List datas = productPropertyService.getModelorByCategoryId( + categoryId); + + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(ProductPropertyModelorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyItemController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyItemController.java new file mode 100644 index 0000000..97ba132 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ProductPropertyItemController.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.basedata.bo.product.property.item.GetProductPropertyItemBo; +import com.lframework.xingyun.basedata.bo.product.property.item.QueryProductPropertyItemBo; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import com.lframework.xingyun.basedata.service.product.ProductPropertyItemService; +import com.lframework.xingyun.basedata.vo.product.property.item.CreateProductPropertyItemVo; +import com.lframework.xingyun.basedata.vo.product.property.item.QueryProductPropertyItemVo; +import com.lframework.xingyun.basedata.vo.product.property.item.UpdateProductPropertyItemVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 属性值管理 + * + * @author zmj + */ +@Api(tags = "属性值管理") +@Validated +@RestController +@RequestMapping("/basedata/product/property/item") +public class ProductPropertyItemController extends DefaultBaseController { + + @Autowired + private ProductPropertyItemService productPropertyItemService; + + /** + * 属性值列表 + */ + @ApiOperation("属性值列表") + @HasPermission({"base-data:product:property-item:query", "base-data:product:property-item:add", + "base-data:product:property-item:modify"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryProductPropertyItemVo vo) { + + PageResult pageResult = productPropertyItemService.query(getPageIndex(vo), + getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryProductPropertyItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询属性值 + */ + @ApiOperation("查询属性值") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:product:property-item:query", "base-data:product:property-item:add", + "base-data:product:property-item:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + ProductPropertyItem data = productPropertyItemService.findById(id); + if (data == null) { + throw new DefaultClientException("属性值不存在!"); + } + + GetProductPropertyItemBo result = new GetProductPropertyItemBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增属性值 + */ + @ApiOperation("新增属性值") + @HasPermission({"base-data:product:property-item:add"}) + @PostMapping + public InvokeResult create(@Valid CreateProductPropertyItemVo vo) { + + productPropertyItemService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改属性值 + */ + @ApiOperation("修改属性值") + @HasPermission({"base-data:product:property-item:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateProductPropertyItemVo vo) { + + productPropertyItemService.update(vo); + + productPropertyItemService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ShopController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ShopController.java new file mode 100644 index 0000000..bb44612 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/ShopController.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.shop.GetShopBo; +import com.lframework.xingyun.basedata.bo.shop.QueryShopBo; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.excel.shop.ShopImportListener; +import com.lframework.xingyun.basedata.excel.shop.ShopImportModel; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.vo.shop.CreateShopVo; +import com.lframework.xingyun.basedata.vo.shop.QueryShopVo; +import com.lframework.xingyun.basedata.vo.shop.UpdateShopVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 门店 Controller + * + * @author zmj + */ +@Api(tags = "门店") +@Validated +@RestController +@RequestMapping("/basedata/shop") +public class ShopController extends DefaultBaseController { + + @Autowired + private ShopService shopService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"base-data:shop:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryShopVo vo) { + + PageResult pageResult = shopService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryShopBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:shop:query"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + Shop data = shopService.findById(id); + if (data == null) { + throw new DefaultClientException("门店不存在!"); + } + + GetShopBo result = new GetShopBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"base-data:shop:add"}) + @PostMapping + public InvokeResult create(@Valid CreateShopVo vo) { + + shopService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"base-data:shop:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateShopVo vo) { + + shopService.update(vo); + + shopService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:shop:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("门店导入模板", ShopImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:shop:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + ShopImportListener listener = new ShopImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, ShopImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/StoreCenterController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/StoreCenterController.java new file mode 100644 index 0000000..c0ac2c8 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/StoreCenterController.java @@ -0,0 +1,181 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.storecenter.GetStoreCenterBo; +import com.lframework.xingyun.basedata.bo.storecenter.QueryStoreCenterBo; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.excel.storecenter.StoreCenterImportListener; +import com.lframework.xingyun.basedata.excel.storecenter.StoreCenterImportModel; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.vo.storecenter.CreateStoreCenterVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterVo; +import com.lframework.xingyun.basedata.vo.storecenter.UpdateStoreCenterVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 仓库管理 + * + * @author zmj + */ +@Api(tags = "仓库管理") +@Validated +@RestController +@RequestMapping("/basedata/storecenter") +public class StoreCenterController extends DefaultBaseController { + + @Autowired + private StoreCenterService storeCenterService; + + /** + * 仓库列表 + */ + @ApiOperation("仓库列表") + @HasPermission({"base-data:store-center:query", "base-data:store-center:add", + "base-data:store-center:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryStoreCenterVo vo) { + + PageResult pageResult = storeCenterService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryStoreCenterBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询仓库 + */ + @ApiOperation("查询仓库") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:store-center:query", "base-data:store-center:add", + "base-data:store-center:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + StoreCenter data = storeCenterService.findById(id); + if (data == null) { + throw new DefaultClientException("仓库不存在!"); + } + + GetStoreCenterBo result = new GetStoreCenterBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用仓库 + */ + @ApiOperation("批量停用仓库") + @HasPermission({"base-data:store-center:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的仓库!") @RequestBody List ids) { + + storeCenterService.batchUnable(ids); + + for (String id : ids) { + storeCenterService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用仓库 + */ + @ApiOperation("批量启用仓库") + @HasPermission({"base-data:store-center:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的仓库!") @RequestBody List ids) { + + storeCenterService.batchEnable(ids); + + for (String id : ids) { + storeCenterService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增仓库 + */ + @ApiOperation("新增仓库") + @HasPermission({"base-data:store-center:add"}) + @PostMapping + public InvokeResult create(@Valid CreateStoreCenterVo vo) { + + storeCenterService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改仓库 + */ + @ApiOperation("修改仓库") + @HasPermission({"base-data:store-center:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateStoreCenterVo vo) { + + storeCenterService.update(vo); + + storeCenterService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:store-center:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("仓库导入模板", StoreCenterImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:store-center:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + StoreCenterImportListener listener = new StoreCenterImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, StoreCenterImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/SupplierController.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/SupplierController.java new file mode 100644 index 0000000..ec45a25 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/controller/SupplierController.java @@ -0,0 +1,181 @@ +package com.lframework.xingyun.basedata.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.basedata.bo.supplier.GetSupplierBo; +import com.lframework.xingyun.basedata.bo.supplier.QuerySupplierBo; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.excel.supplier.SupplierImportListener; +import com.lframework.xingyun.basedata.excel.supplier.SupplierImportModel; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.basedata.vo.supplier.CreateSupplierVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierVo; +import com.lframework.xingyun.basedata.vo.supplier.UpdateSupplierVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 供应商管理 + * + * @author zmj + */ +@Api(tags = "供应商管理") +@Validated +@RestController +@RequestMapping("/basedata/supplier") +public class SupplierController extends DefaultBaseController { + + @Autowired + private SupplierService supplierService; + + /** + * 供应商列表 + */ + @ApiOperation("供应商列表") + @HasPermission({"base-data:supplier:query", "base-data:supplier:add", + "base-data:supplier:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySupplierVo vo) { + + PageResult pageResult = supplierService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QuerySupplierBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询供应商 + */ + @ApiOperation("查询供应商") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"base-data:supplier:query", "base-data:supplier:add", + "base-data:supplier:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + Supplier data = supplierService.findById(id); + if (data == null) { + throw new DefaultClientException("供应商不存在!"); + } + + GetSupplierBo result = new GetSupplierBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用供应商 + */ + @ApiOperation("批量停用供应商") + @HasPermission({"base-data:supplier:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的供应商!") @RequestBody List ids) { + + supplierService.batchUnable(ids); + + for (String id : ids) { + supplierService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用供应商 + */ + @ApiOperation("批量启用供应商") + @HasPermission({"base-data:supplier:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的供应商!") @RequestBody List ids) { + + supplierService.batchEnable(ids); + + for (String id : ids) { + supplierService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增供应商 + */ + @ApiOperation("新增供应商") + @HasPermission({"base-data:supplier:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSupplierVo vo) { + + supplierService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改供应商 + */ + @ApiOperation("修改供应商") + @HasPermission({"base-data:supplier:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSupplierVo vo) { + + supplierService.update(vo); + + supplierService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"base-data:supplier:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("供应商导入模板", SupplierImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"base-data:supplier:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + SupplierImportListener listener = new SupplierImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, SupplierImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/ProductPropertyRelationDto.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/ProductPropertyRelationDto.java new file mode 100644 index 0000000..ad50910 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/ProductPropertyRelationDto.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.dto.product; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.ColumnType; +import java.io.Serializable; +import lombok.Data; + +@Data +public class ProductPropertyRelationDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "ProductPropertyRelationDto"; + + /** + * ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 属性ID + */ + private String propertyId; + + /** + * 属性值ID + */ + private String propertyItemId; + + /** + * 字段类型 + */ + private ColumnType propertyColumnType; + + /** + * 属性名称 + */ + private String propertyName; + + /** + * 属性值 + */ + private String propertyText; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/property/ProductPropertyModelorDto.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/property/ProductPropertyModelorDto.java new file mode 100644 index 0000000..498227d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/dto/product/property/ProductPropertyModelorDto.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.basedata.dto.product.property; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.ColumnDataType; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.PropertyType; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class ProductPropertyModelorDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 是否必填 + */ + private Boolean isRequired; + + /** + * 可选项,当columnType != CUSTOM时 不为空 + */ + private List items; + + /** + * 显示值 当columnType != CUSTOM时,此值为items项ID 当columnType == CUSTOM时,此值为录入值 + */ + private String text; + + /** + * 录入类型 + */ + private ColumnType columnType; + + /** + * 数据类型 + */ + private ColumnDataType columnDataType; + + /** + * 属性类别 + */ + private PropertyType propertyType; + + @Data + public static class ProductPropertyItemModelorDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Address.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Address.java new file mode 100644 index 0000000..2083bb0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Address.java @@ -0,0 +1,119 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2023-03-26 + */ +@Data +@TableName("base_data_address") +public class Address extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "Address"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 实体ID + */ + private String entityId; + + /** + * 实体类型 + */ + private AddressEntityType entityType; + + /** + * 地址类型 + */ + private AddressType addressType; + + /** + * 姓名 + */ + private String name; + + /** + * 手机号 + */ + private String telephone; + + /** + * 省 + */ + private String provinceId; + + /** + * 市 + */ + private String cityId; + + /** + * 区 + */ + private String districtId; + + /** + * 详细地址 + */ + private String address; + + /** + * 是否默认地址 + */ + private Boolean isDefault; + + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Customer.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Customer.java new file mode 100644 index 0000000..9e55217 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Customer.java @@ -0,0 +1,158 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.SettleType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-10 + */ +@Data +@TableName("base_data_customer") +public class Customer extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "CustomerDto"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 助记码 + */ + private String mnemonicCode; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 电子邮箱 + */ + private String email; + + /** + * 邮编 + */ + private String zipCode; + + /** + * 传真 + */ + private String fax; + + /** + * 地区ID + */ + private String cityId; + + /** + * 地址 + */ + private String address; + + /** + * 结账方式 + */ + private SettleType settleType; + + /** + * 统一社会信用代码 + */ + private String creditCode; + + /** + * 纳税人识别号 + */ + private String taxIdentifyNo; + + /** + * 开户银行 + */ + private String bankName; + + /** + * 户名 + */ + private String accountName; + + /** + * 银行账号 + */ + private String accountNo; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/LogisticsCompany.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/LogisticsCompany.java new file mode 100644 index 0000000..f5063f5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/LogisticsCompany.java @@ -0,0 +1,106 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2023-03-26 + */ +@Data +@TableName("base_data_logistics_company") +public class LogisticsCompany extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "LogisticsCompany"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 地区ID + */ + private String cityId; + + /** + * 地址 + */ + private String address; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Member.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Member.java new file mode 100644 index 0000000..8a42dba --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Member.java @@ -0,0 +1,124 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-11 + */ +@Data +@TableName("base_data_member") +public class Member extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "Member"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 性别 + */ + private Gender gender; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 电子邮箱 + */ + private String email; + + /** + * 出生日期 + */ + private LocalDate birthday; + + /** + * 入会日期 + */ + private LocalDate joinDay; + + /** + * 所属门店 + */ + private String shopId; + + /** + * 所属导购 + */ + private String guiderId; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/PayType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/PayType.java new file mode 100644 index 0000000..0ec2172 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/PayType.java @@ -0,0 +1,91 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-30 + */ +@Data +@TableName("base_data_pay_type") +public class PayType extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "PayType"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 是否记录内容 + */ + private Boolean recText; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Product.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Product.java new file mode 100644 index 0000000..8c3ed0c --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Product.java @@ -0,0 +1,144 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.ProductType; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 商品 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +@Data +@TableName("base_data_product") +public class Product extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "Product"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 简称 + */ + private String shortName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 商品类型 + */ + private ProductType productType; + + /** + * 进项税率(%) + */ + private BigDecimal taxRate; + + /** + * 销项税率(%) + */ + private BigDecimal saleTaxRate; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 重量(kg) + */ + private BigDecimal weight; + + /** + * 体积(cm3) + */ + private BigDecimal volume; + + /** + * 状态 + */ + private Boolean available; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBrand.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBrand.java new file mode 100644 index 0000000..0529ac2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBrand.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-06 + */ +@Data +@TableName("base_data_product_brand") +public class ProductBrand extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ProductBrand"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 简称 + */ + private String shortName; + + /** + * logo + */ + private String logo; + + /** + * 简介 + */ + private String introduction; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBundle.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBundle.java new file mode 100644 index 0000000..f33e513 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductBundle.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 组合商品 + *

+ * + * @author zmj + * @since 2023-05-25 + */ +@Data +@TableName("base_data_product_bundle") +public class ProductBundle extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ProductBundle"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 主商品ID + */ + private String mainProductId; + + /** + * 单品ID + */ + private String productId; + + /** + * 包含数量 + */ + private Integer bundleNum; + + /** + * 销售价 + */ + private BigDecimal salePrice; + + /** + * 零售价 + */ + private BigDecimal retailPrice; + + + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategory.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategory.java new file mode 100644 index 0000000..91ab6f1 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategory.java @@ -0,0 +1,90 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-05 + */ +@Data +@TableName("base_data_product_category") +public class ProductCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ProductCategory"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + private String parentId; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategoryProperty.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategoryProperty.java new file mode 100644 index 0000000..50fec93 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductCategoryProperty.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-05 + */ +@Data +@TableName("base_data_product_category_property") +public class ProductCategoryProperty extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ProductCategoryPropertyDto"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 商品属性ID + */ + private String propertyId; + + /** + * 商品类目ID + */ + private String categoryId; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductProperty.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductProperty.java new file mode 100644 index 0000000..c39483d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductProperty.java @@ -0,0 +1,108 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.ColumnDataType; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.PropertyType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-30 + */ +@Data +@TableName("base_data_product_property") +public class ProductProperty extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ProductProperty"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 是否必填 + */ + private Boolean isRequired; + + /** + * 录入类型 + */ + private ColumnType columnType; + + /** + * 数据类型 + */ + private ColumnDataType columnDataType; + + /** + * 属性类别 + */ + private PropertyType propertyType; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyItem.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyItem.java new file mode 100644 index 0000000..fe8591d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyItem.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-08-08 + */ +@Data +@TableName("base_data_product_property_item") +public class ProductPropertyItem extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "ProductPropertyItem"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 属性ID + */ + private String propertyId; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyRelation.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyRelation.java new file mode 100644 index 0000000..5571e20 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPropertyRelation.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-08-05 + */ +@Data +@TableName("base_data_product_property_relation") +public class ProductPropertyRelation extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 商品属性ID + */ + private String propertyId; + + /** + * 属性值ID + */ + private String propertyItemId; + + /** + * 商品属性值 + */ + private String propertyText; + + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPurchase.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPurchase.java new file mode 100644 index 0000000..112289c --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductPurchase.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-11 + */ +@Data +@TableName("base_data_product_purchase") +public class ProductPurchase extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 采购价 + */ + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductRetail.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductRetail.java new file mode 100644 index 0000000..fc744fb --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductRetail.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-11 + */ +@Data +@TableName("base_data_product_retail") +public class ProductRetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 零售价 + */ + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductSale.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductSale.java new file mode 100644 index 0000000..f51ed01 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/ProductSale.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-11 + */ +@Data +@TableName("base_data_product_sale") +public class ProductSale extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 销售价 + */ + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Shop.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Shop.java new file mode 100644 index 0000000..85f2f1d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Shop.java @@ -0,0 +1,101 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 门店 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_shop") +public class Shop extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "Shop"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 所属部门ID + */ + private String deptId; + + /** + * 经度 + */ + private BigDecimal lng; + + /** + * 纬度 + */ + private BigDecimal lat; + + /** + * 备注 + */ + private String description; + + /** + * 状态 + */ + private Boolean available; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/StoreCenter.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/StoreCenter.java new file mode 100644 index 0000000..58185e7 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/StoreCenter.java @@ -0,0 +1,110 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-07 + */ +@Data +@TableName("base_data_store_center") +public class StoreCenter extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "StoreCenter"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系人手机号码 + */ + private String telephone; + + /** + * 地区ID + */ + private String cityId; + + /** + * 地址 + */ + private String address; + + /** + * 仓库人数 + */ + private Integer peopleNum; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Supplier.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Supplier.java new file mode 100644 index 0000000..490d647 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/entity/Supplier.java @@ -0,0 +1,167 @@ +package com.lframework.xingyun.basedata.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.enums.SettleType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-11 + */ +@Data +@TableName("base_data_supplier") +public class Supplier extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "Supplier"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 助记码 + */ + private String mnemonicCode; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 电子邮箱 + */ + private String email; + + /** + * 邮编 + */ + private String zipCode; + + /** + * 传真 + */ + private String fax; + + /** + * 地区ID + */ + private String cityId; + + /** + * 地址 + */ + private String address; + + /** + * 送货周期(天) + */ + private Integer deliveryCycle; + + /** + * 经营方式 + */ + private ManageType manageType; + + /** + * 结账方式 + */ + private SettleType settleType; + + /** + * 统一社会信用代码 + */ + private String creditCode; + + /** + * 纳税人识别号 + */ + private String taxIdentifyNo; + + /** + * 开户银行 + */ + private String bankName; + + /** + * 户名 + */ + private String accountName; + + /** + * 银行账号 + */ + private String accountNo; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressEntityType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressEntityType.java new file mode 100644 index 0000000..effdf8b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressEntityType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum AddressEntityType implements BaseEnum { + SC(1, "仓库"), CUSTOMER(2, "客户"), SUPPLIER(3, "供应商"), MEMBER(4, "会员"), SHOP(5, "门店"); + + @EnumValue + private final Integer code; + + private final String desc; + + AddressEntityType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressType.java new file mode 100644 index 0000000..6dbf702 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/AddressType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum AddressType implements BaseEnum { + DELIVERY(1, "发货地址"), RECEIVE(2, "收货地址"); + + @EnumValue + private final Integer code; + + private final String desc; + + AddressType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/BaseDataOpLogType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/BaseDataOpLogType.java new file mode 100644 index 0000000..c1663ef --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/BaseDataOpLogType.java @@ -0,0 +1,7 @@ +package com.lframework.xingyun.basedata.enums; + +public interface BaseDataOpLogType { + + // 基础信息 + int BASE_DATA = 1000; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnDataType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnDataType.java new file mode 100644 index 0000000..add247a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnDataType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ColumnDataType implements BaseEnum { + INT(1, "整数型"), FLOAT(2, "浮点型"), STRING(3, "字符型"), DATE(4, "日期型"), TIME(5, "时间型"), DATE_TIME(6, + "日期时间型"); + + @EnumValue + private final Integer code; + + private final String desc; + + ColumnDataType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnType.java new file mode 100644 index 0000000..ac92313 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ColumnType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ColumnType implements BaseEnum { + MULTIPLE(1, "多选"), SINGLE(2, "单选"), CUSTOM(3, "手动录入"); + + @EnumValue + private final Integer code; + + private final String desc; + + ColumnType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/InvoiceType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/InvoiceType.java new file mode 100644 index 0000000..e639ebb --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/InvoiceType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum InvoiceType implements BaseEnum { + NORMAL(1, "增值税普通发票"), SPECIAL(2, "增值税专用发票"), NORMAL_OR_SPECIAL(3, "增值税专用发票或增值税普通发票"), + ; + + @EnumValue + private final Integer code; + + private final String desc; + + InvoiceType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ManageType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ManageType.java new file mode 100644 index 0000000..e4e23ea --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ManageType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ManageType implements BaseEnum { + DISTRIBUTION(1, "经销"); + + @EnumValue + private final Integer code; + + private final String desc; + + ManageType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductCategoryNodeType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductCategoryNodeType.java new file mode 100644 index 0000000..437a0ad --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductCategoryNodeType.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.basedata.enums; + +import com.lframework.xingyun.template.core.enums.NodeType; +import java.io.Serializable; +import org.springframework.stereotype.Component; + +@Component +public final class ProductCategoryNodeType implements NodeType, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public Integer getCode() { + + return 2; + } + + @Override + public String getDesc() { + + return "商品类目"; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductType.java new file mode 100644 index 0000000..5dfea32 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/ProductType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ProductType implements BaseEnum { + NORMAL(1, "普通商品"), BUNDLE(2, "组合商品"); + + @EnumValue + private final Integer code; + + private final String desc; + + ProductType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/PropertyType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/PropertyType.java new file mode 100644 index 0000000..919ba4d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/PropertyType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum PropertyType implements BaseEnum { + COMMON(1, "通用属性"), APPOINT(2, "指定类目属性"), NONE(3, "无"); + + @EnumValue + private final Integer code; + + private final String desc; + + PropertyType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/SettleType.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/SettleType.java new file mode 100644 index 0000000..d7fc2e9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/SettleType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleType implements BaseEnum { + ARBITRARILY(1, "任意指定"), CASH_ON_DELIVERY(2, "货到付款"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/TaxRate.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/TaxRate.java new file mode 100644 index 0000000..5b35c5e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/enums/TaxRate.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum TaxRate implements BaseEnum { + RATE17(17, "17%"), RATE11(11, "11%"), RATE6(6, "6%"), RATE3(3, "3%"), RATE0(0, "0%"), FREE(-1, + "免税"); + + @EnumValue + private final Integer code; + + private final String desc; + + TaxRate(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressExportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressExportModel.java new file mode 100644 index 0000000..c6af8e9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressExportModel.java @@ -0,0 +1,134 @@ +package com.lframework.xingyun.basedata.excel.address; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import lombok.Data; + +@Data +public class AddressExportModel extends BaseBo
implements ExcelModel { + + /** + * 实体名称 + */ + @ExcelProperty("实体名称") + private String entityName; + + /** + * 实体类型 + */ + @ExcelProperty("实体类型") + private String entityType; + + /** + * 地址类型 + */ + @ExcelProperty("地址类型") + private String addressType; + + /** + * 姓名 + */ + @ExcelProperty("姓名") + private String name; + + /** + * 联系电话 + */ + @ExcelProperty("联系电话") + private String telephone; + + /** + * 省 + */ + @ExcelProperty("省") + private String provinceName; + + /** + * 市 + */ + @ExcelProperty("市") + private String cityName; + + /** + * 区 + */ + @ExcelProperty("区") + private String districtName; + + /** + * 详细地址 + */ + @ExcelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ExcelProperty("是否默认地址") + private String isDefault; + + public AddressExportModel() { + + } + + public AddressExportModel(Address dto) { + + super(dto); + } + + @Override + protected void afterInit(Address dto) { + if (dto.getEntityType() == AddressEntityType.SC) { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getEntityId()); + this.entityName = sc.getName(); + } else if (dto.getEntityType() == AddressEntityType.CUSTOMER) { + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getEntityId()); + this.entityName = customer.getName(); + } else if (dto.getEntityType() == AddressEntityType.SUPPLIER) { + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getEntityId()); + this.entityName = supplier.getName(); + } else if (dto.getEntityType() == AddressEntityType.MEMBER) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getEntityId()); + this.entityName = member.getName(); + } else if (dto.getEntityType() == AddressEntityType.SHOP) { + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + Shop shop = shopService.findById(dto.getEntityId()); + this.entityName = shop.getName(); + } + + this.entityType = dto.getEntityType().getDesc(); + this.addressType = dto.getAddressType().getDesc(); + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + DicCityDto province = dicCityService.findById(dto.getProvinceId()); + this.provinceName = province.getName(); + + DicCityDto city = dicCityService.findById(dto.getCityId()); + this.cityName = city.getName(); + + DicCityDto district = dicCityService.findById(dto.getDistrictId()); + this.districtName = district.getName(); + + this.isDefault = dto.getIsDefault() ? "是" : "否"; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportListener.java new file mode 100644 index 0000000..eb1c2c5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportListener.java @@ -0,0 +1,192 @@ +package com.lframework.xingyun.basedata.excel.address; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import com.lframework.xingyun.basedata.service.address.AddressService; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.basedata.vo.address.CreateAddressVo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AddressImportListener extends ExcelImportListener { + + @Override + protected void doInvoke(AddressImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getEntityCode())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“实体编号”不能为空"); + } + AddressEntityType entityType = EnumUtil.getByDesc(AddressEntityType.class, + data.getEntityType()); + if (entityType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实体类型”只能填写“" + CollectionUtil.join( + EnumUtil.getDescs(AddressEntityType.class), "、") + "”"); + } + data.setEntityTypeEnum(entityType); + if (entityType == AddressEntityType.SC) { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(StoreCenter.class) + .eq(StoreCenter::getCode, data.getEntityCode()); + StoreCenter sc = storeCenterService.getOne(queryWrapper); + if (sc == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实体编号”不存在"); + } + data.setEntityId(sc.getId()); + } else if (entityType == AddressEntityType.CUSTOMER) { + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Customer.class) + .eq(Customer::getCode, data.getEntityCode()); + Customer customer = customerService.getOne(queryWrapper); + if (customer == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实体编号”不存在"); + } + data.setEntityId(customer.getId()); + } else if (entityType == AddressEntityType.SUPPLIER) { + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Supplier.class) + .eq(Supplier::getCode, data.getEntityCode()); + Supplier supplier = supplierService.getOne(queryWrapper); + if (supplier == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实体编号”不存在"); + } + data.setEntityId(supplier.getId()); + } else if (entityType == AddressEntityType.MEMBER) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getCode, data.getEntityCode()); + Member member = memberService.getOne(queryWrapper); + if (member == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实体编号”不存在"); + } + data.setEntityId(member.getId()); + } else if (entityType == AddressEntityType.SHOP) { + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Shop.class) + .eq(Shop::getCode, data.getEntityCode()); + Shop shop = shopService.getOne(queryWrapper); + if (shop == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实体编号”不存在"); + } + data.setEntityId(shop.getId()); + } + AddressType addressType = EnumUtil.getByDesc(AddressType.class, + data.getAddressType()); + if (addressType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地址类型”只能填写“" + CollectionUtil.join( + EnumUtil.getDescs(AddressType.class), "、") + "”"); + } + data.setAddressTypeEnum(addressType); + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“姓名”不能为空"); + } + if (StringUtil.isBlank(data.getTelephone())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“联系电话”不能为空"); + } + if (StringUtil.isBlank(data.getCity())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”不能为空"); + } + String[] arr = data.getCity().split("/"); + if (arr.length != 3) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”格式错误,应为省/市/区(县),例如:北京市/市辖区/东城区"); + } + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List allCitys = dicCityService.getAll(); + DicCityDto province = allCitys.stream() + .filter(t -> StringUtil.isEmpty(t.getParentId()) && t.getName().equals(arr[0])) + .findFirst().orElse(null); + if (province == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,省份不存在"); + } + DicCityDto city = allCitys.stream() + .filter(t -> province.getId().equals(t.getParentId()) && t.getName().equals(arr[1])) + .findFirst().orElse(null); + if (city == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,市不存在"); + } + DicCityDto area = allCitys.stream() + .filter(t -> city.getId().equals(t.getParentId()) && t.getName().equals(arr[2])) + .findFirst().orElse(null); + if (area == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,区(县)不存在"); + } + + data.setAreaId(area.getId()); + if (StringUtil.isBlank(data.getAddress())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“详细地址”不能为空"); + } + if (StringUtil.isBlank(data.getIsDefault())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“是否默认地址”不能为空"); + } + + if (!"是".equals(data.getIsDefault()) && !"否".equals(data.getIsDefault())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“是否默认地址”只能填写“是、否”"); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + AddressService addressService = ApplicationUtil.getBean(AddressService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + AddressImportModel data = datas.get(i); + CreateAddressVo createAddressVo = new CreateAddressVo(); + createAddressVo.setEntityId(data.getEntityId()); + createAddressVo.setEntityType(data.getEntityTypeEnum().getCode()); + createAddressVo.setAddressType(data.getAddressTypeEnum().getCode()); + createAddressVo.setName(data.getName()); + createAddressVo.setTelephone(data.getTelephone()); + createAddressVo.setCityId(data.getAreaId()); + createAddressVo.setAddress(data.getAddress()); + createAddressVo.setIsDefault("是".equals(data.getIsDefault())); + + try { + addressService.create(createAddressVo); + } catch (Exception e) { + throw new DefaultClientException( + "第" + (i + 1) + "行新增失败,失败原因:" + e.getMessage()); + } + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportModel.java new file mode 100644 index 0000000..103f1c5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/address/AddressImportModel.java @@ -0,0 +1,93 @@ +package com.lframework.xingyun.basedata.excel.address; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import lombok.Data; + +@Data +public class AddressImportModel implements ExcelModel { + + /** + * 实体编号 + */ + @ExcelRequired + @ExcelProperty("实体编号") + private String entityCode; + + /** + * 实体ID + */ + @ExcelIgnore + private String entityId; + + /** + * 实体类型 + */ + @ExcelRequired + @ExcelProperty("实体类型") + private String entityType; + + /** + * 实体类型枚举 + */ + @ExcelIgnore + private AddressEntityType entityTypeEnum; + + /** + * 地址类型 + */ + @ExcelRequired + @ExcelProperty("地址类型") + private String addressType; + + /** + * 地址类型枚举 + */ + @ExcelIgnore + private AddressType addressTypeEnum; + + /** + * 姓名 + */ + @ExcelRequired + @ExcelProperty("姓名") + private String name; + + /** + * 联系电话 + */ + @ExcelRequired + @ExcelProperty("联系电话") + private String telephone; + + /** + * 地区 + */ + @ExcelRequired + @ExcelProperty("地区") + private String city; + + /** + * 地区ID + */ + @ExcelIgnore + private String areaId; + + /** + * 详细地址 + */ + @ExcelRequired + @ExcelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ExcelRequired + @ExcelProperty("是否默认地址") + private String isDefault; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportListener.java new file mode 100644 index 0000000..3a74ced --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportListener.java @@ -0,0 +1,160 @@ +package com.lframework.xingyun.basedata.excel.customer; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.enums.SettleType; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CustomerImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(CustomerImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(Customer.class) + .eq(Customer::getCode, data.getCode()); + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + if (customerService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + if (StringUtil.isBlank(data.getMnemonicCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“助记码”不能为空"); + } + if (StringUtil.isBlank(data.getSettleType())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“结账方式”不能为空"); + } + SettleType settleType = EnumUtil.getByDesc(SettleType.class, data.getSettleType()); + if (settleType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“结账方式”只能填写“" + + CollectionUtil.join( + EnumUtil.getDescs(SettleType.class), "、") + "”"); + } + data.setSettleTypeEnum(settleType); + + if (!StringUtil.isBlank(data.getCity())) { + String[] arr = data.getCity().split("/"); + if (arr.length != 3) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“地区”格式错误,应为省/市/区(县),例如:北京市/市辖区/东城区"); + } + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List allCitys = dicCityService.getAll(); + DicCityDto province = allCitys.stream() + .filter(t -> StringUtil.isEmpty(t.getParentId()) && t.getName().equals(arr[0])) + .findFirst().orElse(null); + if (province == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,省份不存在"); + } + DicCityDto city = allCitys.stream() + .filter(t -> province.getId().equals(t.getParentId()) && t.getName().equals(arr[1])) + .findFirst().orElse(null); + if (city == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,市不存在"); + } + DicCityDto area = allCitys.stream() + .filter(t -> city.getId().equals(t.getParentId()) && t.getName().equals(arr[2])) + .findFirst().orElse(null); + if (area == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,区(县)不存在"); + } + + data.setAreaId(area.getId()); + } + + if (!StringUtil.isEmpty(data.getEmail())) { + if (!RegUtil.isMatch(PatternPool.EMAIL, data.getEmail())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“电子邮箱”格式有误"); + } + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + CustomerImportModel data = datas.get(i); + + Customer record = new Customer(); + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + record.setMnemonicCode(data.getMnemonicCode()); + record.setContact(data.getContact()); + record.setTelephone(data.getTelephone()); + record.setEmail(data.getEmail()); + record.setZipCode(data.getZipCode()); + record.setFax(data.getFax()); + record.setCityId(data.getAreaId()); + record.setAddress(data.getAddress()); + record.setSettleType(data.getSettleTypeEnum()); + record.setCreditCode(data.getCreditCode()); + record.setTaxIdentifyNo(data.getTaxIdentifyNo()); + record.setBankName(data.getBankName()); + record.setAccountName(data.getAccountName()); + record.setAccountNo(data.getAccountNo()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + record.setAvailable(Boolean.TRUE); + + customerService.save(record); + data.setId(record.getId()); + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportModel.java new file mode 100644 index 0000000..373cab2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/customer/CustomerImportModel.java @@ -0,0 +1,136 @@ +package com.lframework.xingyun.basedata.excel.customer; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.enums.SettleType; +import lombok.Data; + +@Data +public class CustomerImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 助记码 + */ + @ExcelRequired + @ExcelProperty("助记码") + private String mnemonicCode; + + /** + * 联系人 + */ + @ExcelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ExcelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ExcelProperty("电子邮箱") + private String email; + + /** + * 邮编 + */ + @ExcelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ExcelProperty("传真") + private String fax; + + /** + * 地区 + */ + @ExcelProperty("地区") + private String city; + + /** + * 地区ID + */ + @ExcelIgnore + private String areaId; + + /** + * 地址 + */ + @ExcelProperty("地址") + private String address; + + /** + * 结账方式 + */ + @ExcelRequired + @ExcelProperty("结账方式") + private String settleType; + + /** + * 结账方式枚举 + */ + @ExcelIgnore + private SettleType settleTypeEnum; + + /** + * 统一社会信用代码 + */ + @ExcelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ExcelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ExcelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ExcelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ExcelProperty("银行账号") + private String accountNo; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportListener.java new file mode 100644 index 0000000..cad50ba --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportListener.java @@ -0,0 +1,154 @@ +package com.lframework.xingyun.basedata.excel.member; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.xingyun.template.core.service.UserService; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class MemberImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(MemberImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getCode, data.getCode()); + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + if (memberService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + if (StringUtil.isBlank(data.getGender())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“性别”不能为空"); + } + + Gender gender = EnumUtil.getByDesc(Gender.class, data.getGender()); + if (gender == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“性别”只能填写“" + CollectionUtil.join( + EnumUtil.getDescs(Gender.class), "、") + "”"); + } + data.setGenderEnum(gender); + + if (!StringUtil.isEmpty(data.getEmail())) { + if (!RegUtil.isMatch(PatternPool.EMAIL, data.getEmail())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“电子邮箱”格式有误"); + } + } + + if (!StringUtil.isEmpty(data.getShopCode())) { + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Shop.class) + .eq(Shop::getCode, data.getShopCode()); + Shop shop = shopService.getOne(queryWrapper); + if (shop == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“所属门店编号”不存在"); + } + data.setShopId(shop.getId()); + } + + if (!StringUtil.isEmpty(data.getGuiderCode())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto guider = userService.findByCode(data.getGuiderCode()); + if (guider == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“所属导购编号”不存在"); + } + data.setGuiderId(guider.getId()); + } + + if (data.getJoinDay() == null) { + data.setJoinDay(new Date()); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + MemberImportModel data = datas.get(i); + + Member record = new Member(); + record.setId(IdUtil.getId()); + + if (!StringUtil.isBlank(data.getTelephone())) { + Wrapper checkWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getTelephone, data.getTelephone()) + .ne(Member::getId, record.getId()); + if (memberService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + (i + 1) + "行“联系电话”重复,请重新输入"); + } + } + + record.setCode(data.getCode()); + record.setName(data.getName()); + record.setGender(data.getGenderEnum()); + record.setTelephone(data.getTelephone()); + record.setEmail(data.getEmail()); + record.setBirthday(DateUtil.toLocalDate(data.getBirthday())); + record.setJoinDay(DateUtil.toLocalDate(data.getJoinDay())); + record.setShopId(data.getShopId()); + record.setGuiderId(data.getGuiderId()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + record.setAvailable(Boolean.TRUE); + + data.setId(record.getId()); + + memberService.save(record); + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportModel.java new file mode 100644 index 0000000..dd5e7ad --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/member/MemberImportModel.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.basedata.excel.member; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.util.Date; +import lombok.Data; + +@Data +public class MemberImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 性别 + */ + @ExcelRequired + @ExcelProperty("性别") + private String gender; + + /** + * 性别 + */ + @ExcelIgnore + private Gender genderEnum; + + /** + * 联系电话 + */ + @ExcelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ExcelProperty("电子邮箱") + private String email; + + /** + * 出生日期 + */ + @ExcelProperty("出生日期") + private Date birthday; + + /** + * 入会日期 + */ + @ExcelProperty("入会日期") + private Date joinDay; + + /** + * 所属门店ID + */ + @ExcelIgnore + private String shopId; + + /** + * 所属门店编号 + */ + @ExcelProperty("所属门店编号") + private String shopCode; + + /** + * 所属导购ID + */ + @ExcelIgnore + private String guiderId; + + /** + * 所属导购编号 + */ + @ExcelProperty("所属导购编号") + private String guiderCode; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportListener.java new file mode 100644 index 0000000..f209fdf --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportListener.java @@ -0,0 +1,274 @@ +package com.lframework.xingyun.basedata.excel.product; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductRetailService; +import com.lframework.xingyun.basedata.service.product.ProductSaleService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.vo.product.purchase.CreateProductPurchaseVo; +import com.lframework.xingyun.basedata.vo.product.retail.CreateProductRetailVo; +import com.lframework.xingyun.basedata.vo.product.sale.CreateProductSaleVo; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ProductImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(ProductImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getCode, data.getCode()); + ProductService productService = ApplicationUtil.getBean(ProductService.class); + if (productService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getCode, data.getCode()); + Product product = productService.getOne(queryWrapper); + + if (StringUtil.isBlank(data.getSkuCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“SKU编号”不能为空"); + } + + LambdaQueryWrapper checkSkuCodeWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getSkuCode, data.getSkuCode()); + if (product != null) { + checkSkuCodeWrapper.ne(Product::getId, product.getId()); + if (product.getProductType() != ProductType.NORMAL) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行商品类型必须为" + + ProductType.NORMAL.getDesc() + ",请检查"); + } + } + + if (productService.count(checkSkuCodeWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“SKU编号”重复,请检查"); + } + + if (StringUtil.isBlank(data.getCategoryCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“类目编号”不能为空"); + } + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + Wrapper queryProductCategoryWrapper = Wrappers.lambdaQuery( + ProductCategory.class).eq(ProductCategory::getCode, data.getCategoryCode()); + ProductCategory productCategory = productCategoryService.getOne(queryProductCategoryWrapper); + if (productCategory == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“类目编号”不存在,请检查"); + } + + if (StringUtil.isBlank(data.getBrandCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“品牌编号”不能为空"); + } + data.setCategoryId(productCategory.getId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean( + ProductBrandService.class); + Wrapper queryProductBrandWrapper = Wrappers.lambdaQuery( + ProductBrand.class).eq(ProductBrand::getCode, data.getBrandCode()); + ProductBrand productBrand = productBrandService.getOne(queryProductBrandWrapper); + if (productBrand == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“品牌编号”不存在,请检查"); + } + data.setBrandId(productBrand.getId()); + + if (data.getTaxRate() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“进项税率(%)”不能为空"); + } + + if (NumberUtil.lt(data.getTaxRate(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“进项税率(%)”不允许小于0"); + } + + if (!NumberUtil.isNumberPrecision(data.getTaxRate(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“进项税率(%)”必须为整数"); + } + + if (data.getSaleTaxRate() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销项税率(%)”不能为空"); + } + + if (NumberUtil.lt(data.getSaleTaxRate(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销项税率(%)”不允许小于0"); + } + + if (!NumberUtil.isNumberPrecision(data.getSaleTaxRate(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销项税率(%)”必须为整数"); + } + + if (data.getPurchasePrice() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价(元)”不能为空"); + } + + if (!NumberUtil.isNumberPrecision(data.getPurchasePrice(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价(元)”最多允许2位小数"); + } + if (NumberUtil.lt(data.getPurchasePrice(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价(元)”不允许小于0"); + } + + if (data.getSalePrice() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销售价(元)”不能为空"); + } + + if (!NumberUtil.isNumberPrecision(data.getSalePrice(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销售价(元)”最多允许2位小数"); + } + if (NumberUtil.lt(data.getSalePrice(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销售价(元)”不允许小于0"); + } + + if (data.getRetailPrice() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“零售价(元)”不能为空"); + } + + if (!NumberUtil.isNumberPrecision(data.getRetailPrice(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“零售价(元)”最多允许2位小数"); + } + if (NumberUtil.lt(data.getRetailPrice(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“零售价(元)”不允许小于0"); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + ProductImportModel data = datas.get(i); + + Wrapper checkSkuCodeWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getSkuCode, data.getSkuCode()).ne(Product::getCode, data.getCode()); + if (productService.count(checkSkuCodeWrapper) > 0) { + throw new DefaultClientException("第" + (i + 1) + "行“商品SKU编号”重复,请重新输入"); + } + + Product record = new Product(); + + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + if (StringUtil.isNotBlank(data.getShortName())) { + record.setShortName(data.getShortName()); + } + record.setSkuCode(data.getSkuCode()); + record.setExternalCode(data.getExternalCode()); + record.setCategoryId(data.getCategoryId()); + record.setBrandId(data.getBrandId()); + if (data.getTaxRate() != null) { + record.setTaxRate(data.getTaxRate()); + } + if (data.getSaleTaxRate() != null) { + record.setSaleTaxRate(data.getSaleTaxRate()); + } + record.setSpec(data.getSpec()); + record.setUnit(data.getUnit()); + record.setProductType(ProductType.NORMAL); + + record.setAvailable(Boolean.TRUE); + + productService.save(record); + data.setId(record.getId()); + + if (data.getPurchasePrice() != null) { + ProductPurchaseService productPurchaseService = ApplicationUtil.getBean( + ProductPurchaseService.class); + CreateProductPurchaseVo createProductPurchaseVo = new CreateProductPurchaseVo(); + createProductPurchaseVo.setId(data.getId()); + createProductPurchaseVo.setPrice(data.getPurchasePrice()); + + productPurchaseService.create(createProductPurchaseVo); + } + + if (data.getSalePrice() != null) { + ProductSaleService productSaleService = ApplicationUtil.getBean(ProductSaleService.class); + CreateProductSaleVo createProductSaleVo = new CreateProductSaleVo(); + createProductSaleVo.setId(data.getId()); + createProductSaleVo.setPrice(data.getSalePrice()); + + productSaleService.create(createProductSaleVo); + } + + if (data.getRetailPrice() != null) { + ProductRetailService productRetailService = ApplicationUtil.getBean( + ProductRetailService.class); + CreateProductRetailVo createProductRetailVo = new CreateProductRetailVo(); + createProductRetailVo.setId(data.getId()); + createProductRetailVo.setPrice(data.getRetailPrice()); + + productRetailService.create(createProductRetailVo); + } + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportModel.java new file mode 100644 index 0000000..bb0c6de --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/ProductImportModel.java @@ -0,0 +1,124 @@ +package com.lframework.xingyun.basedata.excel.product; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class ProductImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 简称 + */ + @ExcelProperty("简称") + private String shortName; + + /** + * SKU编号 + */ + @ExcelRequired + @ExcelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ExcelProperty("外部编号") + private String externalCode; + + /** + * 类目ID + */ + @ExcelIgnore + private String categoryId; + + /** + * 类目编号 + */ + @ExcelRequired + @ExcelProperty("类目编号") + private String categoryCode; + + /** + * 品牌ID + */ + @ExcelIgnore + private String brandId; + + /** + * 品牌编号 + */ + @ExcelRequired + @ExcelProperty("品牌编号") + private String brandCode; + + /** + * 进项税率(%) + */ + @ExcelRequired + @ExcelProperty("进项税率(%)") + private BigDecimal taxRate; + + /** + * 销项税率(%) + */ + @ExcelRequired + @ExcelProperty("销项税率(%)") + private BigDecimal saleTaxRate; + + /** + * 规格 + */ + @ExcelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ExcelProperty("单位") + private String unit; + + /** + * 采购价 + */ + @ExcelRequired + @ExcelProperty("采购价(元)") + private BigDecimal purchasePrice; + + /** + * 销售价 + */ + @ExcelRequired + @ExcelProperty("销售价(元)") + private BigDecimal salePrice; + + /** + * 零售价 + */ + @ExcelRequired + @ExcelProperty("零售价(元)") + private BigDecimal retailPrice; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportListener.java new file mode 100644 index 0000000..d15d704 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportListener.java @@ -0,0 +1,94 @@ +package com.lframework.xingyun.basedata.excel.product.brand; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ProductBrandImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(ProductBrandImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(ProductBrand.class) + .eq(ProductBrand::getCode, data.getCode()); + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + if (productBrandService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + ProductBrandImportModel data = datas.get(i); + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductBrand.class) + .eq(ProductBrand::getName, data.getName()).ne(ProductBrand::getCode, data.getCode()); + if (productBrandService.count(checkNameWrapper) > 0) { + throw new DefaultClientException( + "第" + (i + 1) + "行“名称”重复,请重新输入"); + } + + ProductBrand record = new ProductBrand(); + + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + record.setShortName(data.getShortName()); + record.setIntroduction(StringUtil.isBlank(data.getIntroduction()) ? StringPool.EMPTY_STR + : data.getIntroduction()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + record.setAvailable(Boolean.TRUE); + + productBrandService.save(record); + data.setId(record.getId()); + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportModel.java new file mode 100644 index 0000000..2d96935 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/brand/ProductBrandImportModel.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.excel.product.brand; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import lombok.Data; + +@Data +public class ProductBrandImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 简称 + */ + @ExcelProperty("简称") + private String shortName; + + /** + * 简介 + */ + @ExcelProperty("简介") + private String introduction; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportListener.java new file mode 100644 index 0000000..1bf3248 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportListener.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.basedata.excel.product.category; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ProductCategoryImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(ProductCategoryImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getCode, data.getCode()); + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + if (productCategoryService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + if (!StringUtil.isBlank(data.getParentCode())) { + Wrapper queryParentWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getCode, data.getParentCode()); + ProductCategory parent = productCategoryService.getOne(queryParentWrapper); + if (parent == null) { + // 检查是不是新导入的 + if (this.datas.stream().noneMatch(t -> t.getCode().equals(data.getParentCode()))) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“上级类目编号”不存在"); + } + } + + // 不允许改变上级类目 + Wrapper queryWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getCode, data.getCode()); + ProductCategory productCategory = productCategoryService.getOne(queryWrapper); + if (productCategory != null) { + ProductCategory parentCategory = StringUtil.isBlank(productCategory.getParentId()) ? null + : productCategoryService.getById(productCategory.getParentId()); + if (parentCategory == null || !parentCategory.getCode().equals(data.getParentCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“上级类目编号”有误,不允许修改类目的归属关系"); + } + } + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + ProductCategoryImportModel data = datas.get(i); + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getName, data.getName()) + .ne(ProductCategory::getCode, data.getCode()); + if (productCategoryService.count(checkNameWrapper) > 0) { + throw new DefaultClientException( + "第" + (i + 1) + "行“名称”重复,请重新输入"); + } + + ProductCategory record = new ProductCategory(); + + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + if (!StringUtil.isBlank(data.getParentCode())) { + Wrapper queryParentWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getCode, data.getParentCode()); + ProductCategory parent = productCategoryService.getOne(queryParentWrapper); + if (parent == null) { + throw new DefaultClientException("第" + (i + 1) + "行“上级类目编号”不存在"); + } + if (record.getId().equals(parent.getId())) { + throw new DefaultClientException( + "第" + (i + 1) + "行“上级类目编号”与“编号”相同,请重新输入"); + } + record.setParentId(parent.getId()); + } + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + //这里要与上级类目的状态保持一致 + Boolean available = Boolean.TRUE; + if (StringUtil.isNotBlank(record.getParentId())) { + ProductCategory parentCategory = productCategoryService.findById(record.getParentId()); + available = parentCategory.getAvailable(); + } + record.setAvailable(available); + + productCategoryService.save(record); + productCategoryService.saveRecursion(record.getId(), record.getParentId()); + data.setId(record.getId()); + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportModel.java new file mode 100644 index 0000000..982928e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/product/category/ProductCategoryImportModel.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.basedata.excel.product.category; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import lombok.Data; + +@Data +public class ProductCategoryImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 上级类目编号 + */ + @ExcelProperty("上级类目编号") + private String parentCode; + + /** + * 上级类目ID + */ + @ExcelIgnore + private String parentId; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportListener.java new file mode 100644 index 0000000..d672eae --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportListener.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.basedata.excel.shop; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.template.core.dto.DeptDto; +import com.lframework.xingyun.template.core.service.DeptService; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ShopImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(ShopImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(Shop.class) + .eq(Shop::getCode, data.getCode()); + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + if (shopService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + if (!StringUtil.isBlank(data.getDeptCode())) { + DeptService deptService = ApplicationUtil.getBean(DeptService.class); + DeptDto dept = deptService.findByCode(data.getDeptCode()); + if (dept == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“所属部门编号”不存在"); + } + data.setDeptId(dept.getId()); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + ShopService shopService = ApplicationUtil.getBean(ShopService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + ShopImportModel data = datas.get(i); + + Shop record = new Shop(); + + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + record.setDeptId(data.getDeptId()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + record.setAvailable(Boolean.TRUE); + + shopService.save(record); + + data.setId(record.getId()); + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportModel.java new file mode 100644 index 0000000..efdc865 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/shop/ShopImportModel.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.basedata.excel.shop; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import lombok.Data; + +@Data +public class ShopImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 所属部门编号 + */ + @ExcelProperty("所属部门编号") + private String deptCode; + + /** + * 所属部门ID + */ + @ExcelIgnore + private String deptId; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportListener.java new file mode 100644 index 0000000..7fcf1d5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportListener.java @@ -0,0 +1,131 @@ +package com.lframework.xingyun.basedata.excel.storecenter; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class StoreCenterImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(StoreCenterImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(StoreCenter.class) + .eq(StoreCenter::getCode, data.getCode()); + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + if (storeCenterService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + if (!StringUtil.isBlank(data.getCity())) { + String[] arr = data.getCity().split("/"); + if (arr.length != 3) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“地区”格式错误,应为省/市/区(县),例如:北京市/市辖区/东城区"); + } + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List allCitys = dicCityService.getAll(); + DicCityDto province = allCitys.stream() + .filter(t -> StringUtil.isEmpty(t.getParentId()) && t.getName().equals(arr[0])) + .findFirst().orElse(null); + if (province == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,省份不存在"); + } + DicCityDto city = allCitys.stream() + .filter(t -> province.getId().equals(t.getParentId()) && t.getName().equals(arr[1])) + .findFirst().orElse(null); + if (city == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,市不存在"); + } + DicCityDto area = allCitys.stream() + .filter(t -> city.getId().equals(t.getParentId()) && t.getName().equals(arr[2])) + .findFirst().orElse(null); + if (area == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,区(县)不存在"); + } + + data.setAreaId(area.getId()); + } + + if (data.getPeopleNum() != null) { + if (data.getPeopleNum() < 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“仓库人数”不允许小于0"); + } + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + StoreCenterImportModel data = datas.get(i); + + StoreCenter record = new StoreCenter(); + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + record.setContact(data.getContact()); + record.setTelephone(data.getTelephone()); + record.setCityId(data.getAreaId()); + record.setAddress(data.getAddress()); + record.setPeopleNum(data.getPeopleNum()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + record.setAvailable(Boolean.TRUE); + + storeCenterService.save(record); + data.setId(record.getId()); + + this.setSuccessProcessByIndex(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportModel.java new file mode 100644 index 0000000..57559a1 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/storecenter/StoreCenterImportModel.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.basedata.excel.storecenter; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import lombok.Data; + +@Data +public class StoreCenterImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 联系人 + */ + @ExcelProperty("联系人") + private String contact; + + /** + * 联系人手机号码 + */ + @ExcelProperty("联系人手机号码") + private String telephone; + + /** + * 地区 + */ + @ExcelProperty("地区") + private String city; + + /** + * 仓库地址 + */ + @ExcelProperty("仓库地址") + private String address; + + /** + * 仓库人数 + */ + @ExcelProperty("仓库人数") + private Integer peopleNum; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 地区的ID + */ + @ExcelIgnore + private String areaId; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportListener.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportListener.java new file mode 100644 index 0000000..48537c5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportListener.java @@ -0,0 +1,184 @@ +package com.lframework.xingyun.basedata.excel.supplier; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.enums.SettleType; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SupplierImportListener extends ExcelImportListener { + + private List checkList = new ArrayList<>(); + + @Override + protected void doInvoke(SupplierImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”不能为空"); + } + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“编号”必须由字母、数字、“-_.”组成,长度不能超过20位"); + } + if (checkList.contains(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”与第" + (checkList.indexOf(data.getCode()) + 1) + "行重复"); + } + checkList.add(data.getCode()); + Wrapper checkWrapper = Wrappers.lambdaQuery(Supplier.class) + .eq(Supplier::getCode, data.getCode()); + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + if (supplierService.count(checkWrapper) > 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“编号”已存在"); + } + if (StringUtil.isBlank(data.getName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“名称”不能为空"); + } + if (StringUtil.isBlank(data.getMnemonicCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“助记码”不能为空"); + } + if (StringUtil.isBlank(data.getSettleType())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“结账方式”不能为空"); + } + SettleType settleType = EnumUtil.getByDesc(SettleType.class, data.getSettleType()); + if (settleType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“结账方式”只能填写“" + + CollectionUtil.join( + EnumUtil.getDescs(SettleType.class), "、") + "”"); + } + data.setSettleTypeEnum(settleType); + + if (StringUtil.isBlank(data.getManageType())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“经营方式”不能为空"); + } + ManageType manageType = EnumUtil.getByDesc(ManageType.class, data.getManageType()); + if (manageType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“经营方式”只能填写“" + + CollectionUtil.join( + EnumUtil.getDescs(ManageType.class), "、") + "”"); + } + data.setManageTypeEnum(manageType); + + if (!StringUtil.isBlank(data.getCity())) { + String[] arr = data.getCity().split("/"); + if (arr.length != 3) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + + "行“地区”格式错误,应为省/市/区(县),例如:北京市/市辖区/东城区"); + } + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List allCitys = dicCityService.getAll(); + DicCityDto province = allCitys.stream() + .filter(t -> StringUtil.isEmpty(t.getParentId()) && t.getName().equals(arr[0])) + .findFirst().orElse(null); + if (province == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,省份不存在"); + } + DicCityDto city = allCitys.stream() + .filter(t -> province.getId().equals(t.getParentId()) && t.getName().equals(arr[1])) + .findFirst().orElse(null); + if (city == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,市不存在"); + } + DicCityDto area = allCitys.stream() + .filter(t -> city.getId().equals(t.getParentId()) && t.getName().equals(arr[2])) + .findFirst().orElse(null); + if (area == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“地区”错误,区(县)不存在"); + } + + data.setAreaId(area.getId()); + } + + if (!StringUtil.isEmpty(data.getEmail())) { + if (!RegUtil.isMatch(PatternPool.EMAIL, data.getEmail())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“电子邮箱”格式有误"); + } + } + + if (data.getDeliveryCycle() != null) { + if (data.getDeliveryCycle() <= 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“送货周期(天)”必须大于0"); + } + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + SupplierImportModel data = datas.get(i); + + Supplier record = new Supplier(); + + record.setId(IdUtil.getId()); + + record.setCode(data.getCode()); + record.setName(data.getName()); + record.setMnemonicCode(data.getMnemonicCode()); + record.setContact(data.getContact()); + record.setTelephone(data.getTelephone()); + record.setEmail(data.getEmail()); + record.setZipCode(data.getZipCode()); + record.setFax(data.getFax()); + record.setCityId(data.getAreaId()); + record.setAddress(data.getAddress()); + record.setDeliveryCycle(data.getDeliveryCycle()); + record.setManageType(data.getManageTypeEnum()); + record.setSettleType(data.getSettleTypeEnum()); + record.setCreditCode(data.getCreditCode()); + record.setTaxIdentifyNo(data.getTaxIdentifyNo()); + record.setBankName(data.getBankName()); + record.setAccountName(data.getAccountName()); + record.setAccountNo(data.getAccountNo()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + record.setAvailable(Boolean.TRUE); + + supplierService.save(record); + data.setId(record.getId()); + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportModel.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportModel.java new file mode 100644 index 0000000..06c8247 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/excel/supplier/SupplierImportModel.java @@ -0,0 +1,156 @@ +package com.lframework.xingyun.basedata.excel.supplier; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.enums.SettleType; +import lombok.Data; + +@Data +public class SupplierImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 编号 + */ + @ExcelRequired + @ExcelProperty("编号") + private String code; + + /** + * 名称 + */ + @ExcelRequired + @ExcelProperty("名称") + private String name; + + /** + * 助记码 + */ + @ExcelRequired + @ExcelProperty("助记码") + private String mnemonicCode; + + /** + * 联系人 + */ + @ExcelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ExcelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ExcelProperty("电子邮箱") + private String email; + + /** + * 邮编 + */ + @ExcelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ExcelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ExcelProperty("地区") + private String city; + + /** + * 地区ID + */ + @ExcelIgnore + private String areaId; + + /** + * 地址 + */ + @ExcelProperty("地址") + private String address; + + /** + * 送货周期(天) + */ + @ExcelProperty("送货周期(天)") + private Integer deliveryCycle; + + /** + * 经营方式 + */ + @ExcelRequired + @ExcelProperty("经营方式") + private String manageType; + + /** + * 经营方式枚举 + */ + @ExcelIgnore + private ManageType manageTypeEnum; + + /** + * 结账方式 + */ + @ExcelRequired + @ExcelProperty(value = "结账方式") + private String settleType; + + /** + * 结账方式枚举 + */ + @ExcelIgnore + private SettleType settleTypeEnum; + + /** + * 统一社会信用代码 + */ + @ExcelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ExcelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ExcelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ExcelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ExcelProperty("银行账号") + private String accountNo; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/address/AddressServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/address/AddressServiceImpl.java new file mode 100644 index 0000000..3bf1371 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/address/AddressServiceImpl.java @@ -0,0 +1,164 @@ +package com.lframework.xingyun.basedata.impl.address; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.xingyun.basedata.mappers.AddressMapper; +import com.lframework.xingyun.basedata.service.address.AddressService; +import com.lframework.xingyun.basedata.vo.address.AddressSelectorVo; +import com.lframework.xingyun.basedata.vo.address.CreateAddressVo; +import com.lframework.xingyun.basedata.vo.address.QueryAddressVo; +import com.lframework.xingyun.basedata.vo.address.UpdateAddressVo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import com.lframework.xingyun.template.core.annotations.OpLog; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class AddressServiceImpl extends BaseMpServiceImpl + implements AddressService { + + @Autowired + private DicCityService dicCityService; + + @Override + public PageResult
query(Integer pageIndex, Integer pageSize, QueryAddressVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List
datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List
query(QueryAddressVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult
selector(Integer pageIndex, Integer pageSize, AddressSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List
datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = Address.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public Address findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增地址,ID:{}, 编号:{}", params = {"#_result", + "#vo.code"}, autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateAddressVo vo) { + + if (vo.getIsDefault()) { + Wrapper
checkWrapper = Wrappers.lambdaQuery(Address.class) + .eq(Address::getEntityId, vo.getEntityId()) + .eq(Address::getAddressType, vo.getAddressType()).eq(Address::getIsDefault, Boolean.TRUE); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("实体已存在默认地址,不允许再新增默认地址!"); + } + } + + Address data = new Address(); + data.setId(IdUtil.getId()); + data.setEntityId(vo.getEntityId()); + data.setEntityType(EnumUtil.getByCode(AddressEntityType.class, vo.getEntityType())); + data.setAddressType(EnumUtil.getByCode(AddressType.class, vo.getAddressType())); + data.setName(vo.getName()); + data.setTelephone(vo.getTelephone()); + DicCityDto district = dicCityService.findById(vo.getCityId()); + data.setDistrictId(district.getId()); + DicCityDto city = dicCityService.findById(district.getParentId()); + data.setCityId(city.getId()); + DicCityDto province = dicCityService.findById(city.getParentId()); + data.setProvinceId(province.getId()); + data.setAddress(vo.getAddress()); + data.setIsDefault(vo.getIsDefault()); + + getBaseMapper().insert(data); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改地址,ID:{}, 编号:{}", params = {"#vo.id", + "#vo.code"}, autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateAddressVo vo) { + + Address data = getBaseMapper().selectById(vo.getId()); + if (data == null) { + throw new DefaultClientException("地址不存在!"); + } + if (vo.getIsDefault()) { + Wrapper
checkWrapper = Wrappers.lambdaQuery(Address.class) + .eq(Address::getEntityId, vo.getEntityId()) + .eq(Address::getAddressType, vo.getAddressType()).eq(Address::getIsDefault, Boolean.TRUE) + .ne(Address::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("实体已存在默认地址,不允许再新增默认地址!"); + } + } + data.setEntityId(vo.getEntityId()); + data.setEntityType(EnumUtil.getByCode(AddressEntityType.class, vo.getEntityType())); + data.setAddressType(EnumUtil.getByCode(AddressType.class, vo.getAddressType())); + data.setName(vo.getName()); + data.setTelephone(vo.getTelephone()); + DicCityDto district = dicCityService.findById(vo.getCityId()); + data.setDistrictId(district.getId()); + DicCityDto city = dicCityService.findById(district.getParentId()); + data.setCityId(city.getId()); + DicCityDto province = dicCityService.findById(city.getParentId()); + data.setProvinceId(province.getId()); + data.setAddress(vo.getAddress()); + data.setIsDefault(vo.getIsDefault()); + + getBaseMapper().updateAllColumnById(data); + } + + @Override + public Address getDefaultAddress(String entityId, Integer entityType, Integer addressType) { + Wrapper
queryWrapper = Wrappers.lambdaQuery(Address.class) + .eq(Address::getEntityId, entityId).eq(Address::getEntityType, entityType) + .eq(Address::getAddressType, addressType).eq(Address::getIsDefault, Boolean.TRUE); + return this.getOne(queryWrapper); + } + + @CacheEvict(value = Address.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/customer/CustomerServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/customer/CustomerServiceImpl.java new file mode 100644 index 0000000..9698a0d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/customer/CustomerServiceImpl.java @@ -0,0 +1,240 @@ +package com.lframework.xingyun.basedata.impl.customer; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.xingyun.basedata.enums.SettleType; +import com.lframework.xingyun.basedata.mappers.CustomerMapper; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.vo.customer.CreateCustomerVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerSelectorVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo; +import com.lframework.xingyun.basedata.vo.customer.UpdateCustomerVo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CustomerServiceImpl extends BaseMpServiceImpl implements + CustomerService { + + @Autowired + private DicCityService dicCityService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryCustomerVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryCustomerVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = Customer.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public Customer findById(String id) { + + return getBaseMapper().selectById(id); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, QueryCustomerSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用客户,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Customer.class) + .set(Customer::getAvailable, Boolean.FALSE).in(Customer::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用客户,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Customer.class) + .set(Customer::getAvailable, Boolean.TRUE).in(Customer::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增客户,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateCustomerVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(Customer.class).eq(Customer::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Customer data = new Customer(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getMnemonicCode())) { + data.setMnemonicCode(vo.getMnemonicCode()); + } + if (!StringUtil.isBlank(vo.getContact())) { + data.setContact(vo.getContact()); + } + if (!StringUtil.isBlank(vo.getTelephone())) { + data.setTelephone(vo.getTelephone()); + } + if (!StringUtil.isBlank(vo.getEmail())) { + data.setEmail(vo.getEmail()); + } + if (!StringUtil.isBlank(vo.getZipCode())) { + data.setZipCode(vo.getZipCode()); + } + if (!StringUtil.isBlank(vo.getFax())) { + data.setFax(vo.getFax()); + } + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + data.setCityId(vo.getCityId()); + } + } + if (!StringUtil.isBlank(vo.getAddress())) { + data.setAddress(vo.getAddress()); + } + data.setSettleType(EnumUtil.getByCode(SettleType.class, vo.getSettleType())); + if (!StringUtil.isBlank(vo.getCreditCode())) { + data.setCreditCode(vo.getCreditCode()); + } + if (!StringUtil.isBlank(vo.getTaxIdentifyNo())) { + data.setTaxIdentifyNo(vo.getTaxIdentifyNo()); + } + if (!StringUtil.isBlank(vo.getBankName())) { + data.setBankName(vo.getBankName()); + } + if (!StringUtil.isBlank(vo.getAccountName())) { + data.setAccountName(vo.getAccountName()); + } + if (!StringUtil.isBlank(vo.getAccountNo())) { + data.setAccountNo(vo.getAccountNo()); + } + data.setAvailable(Boolean.TRUE); + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改客户,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateCustomerVo vo) { + + Customer data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("客户不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(Customer.class).eq(Customer::getCode, vo.getCode()) + .ne(Customer::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Customer.class) + .set(Customer::getCode, vo.getCode()).set(Customer::getName, vo.getName()) + .set(Customer::getMnemonicCode, !StringUtil.isBlank(vo.getMnemonicCode()) ? vo.getMnemonicCode() : null) + .set(Customer::getContact, !StringUtil.isBlank(vo.getContact()) ? vo.getContact() : null) + .set(Customer::getTelephone, !StringUtil.isBlank(vo.getTelephone()) ? vo.getTelephone() : null) + .set(Customer::getAddress, !StringUtil.isBlank(vo.getAddress()) ? vo.getAddress() : null) + .set(Customer::getEmail, !StringUtil.isBlank(vo.getEmail()) ? vo.getEmail() : null) + .set(Customer::getZipCode, !StringUtil.isBlank(vo.getZipCode()) ? vo.getZipCode() : null) + .set(Customer::getFax, !StringUtil.isBlank(vo.getFax()) ? vo.getFax() : null) + .set(Customer::getAddress, !StringUtil.isBlank(vo.getAddress()) ? vo.getAddress() : null) + .set(Customer::getCreditCode, !StringUtil.isBlank(vo.getCreditCode()) ? vo.getCreditCode() : null) + .set(Customer::getTaxIdentifyNo, + !StringUtil.isBlank(vo.getTaxIdentifyNo()) ? vo.getTaxIdentifyNo() : null) + .set(Customer::getBankName, !StringUtil.isBlank(vo.getBankName()) ? vo.getBankName() : null) + .set(Customer::getAccountName, !StringUtil.isBlank(vo.getAccountName()) ? vo.getAccountName() : null) + .set(Customer::getAccountNo, !StringUtil.isBlank(vo.getAccountNo()) ? vo.getAccountNo() : null) + .set(Customer::getAvailable, vo.getAvailable()).set(Customer::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(Customer::getId, vo.getId()); + + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + updateWrapper.set(Customer::getCityId, vo.getCityId()); + } + } else { + updateWrapper.set(Customer::getCityId, null); + } + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = Customer.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/logistics/LogisticsCompanyServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/logistics/LogisticsCompanyServiceImpl.java new file mode 100644 index 0000000..84e4066 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/logistics/LogisticsCompanyServiceImpl.java @@ -0,0 +1,211 @@ +package com.lframework.xingyun.basedata.impl.logistics; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.mappers.LogisticsCompanyMapper; +import com.lframework.xingyun.basedata.service.logistics.LogisticsCompanyService; +import com.lframework.xingyun.basedata.vo.logistics.company.CreateLogisticsCompanyVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanySelectorVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanyVo; +import com.lframework.xingyun.basedata.vo.logistics.company.UpdateLogisticsCompanyVo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class LogisticsCompanyServiceImpl extends + BaseMpServiceImpl implements + LogisticsCompanyService { + + @Autowired + private DicCityService dicCityService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryLogisticsCompanyVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryLogisticsCompanyVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = LogisticsCompany.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public LogisticsCompany findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用物流公司,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(LogisticsCompany.class) + .set(LogisticsCompany::getAvailable, Boolean.FALSE).in(LogisticsCompany::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用物流公司,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(LogisticsCompany.class) + .set(LogisticsCompany::getAvailable, Boolean.TRUE).in(LogisticsCompany::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增物流公司,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateLogisticsCompanyVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(LogisticsCompany.class) + .eq(LogisticsCompany::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LogisticsCompany data = new LogisticsCompany(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getContact())) { + data.setContact(vo.getContact()); + } + if (!StringUtil.isBlank(vo.getTelephone())) { + data.setTelephone(vo.getTelephone()); + } + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + data.setCityId(vo.getCityId()); + } + } + if (!StringUtil.isBlank(vo.getAddress())) { + data.setAddress(vo.getAddress()); + } + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改物流公司,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateLogisticsCompanyVo vo) { + + LogisticsCompany data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("物流公司不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(LogisticsCompany.class) + .eq(LogisticsCompany::getCode, vo.getCode()) + .ne(LogisticsCompany::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + LogisticsCompany.class) + .set(LogisticsCompany::getCode, vo.getCode()).set(LogisticsCompany::getName, vo.getName()) + .set(LogisticsCompany::getContact, + !StringUtil.isBlank(vo.getContact()) ? vo.getContact() : null) + .set(LogisticsCompany::getTelephone, + !StringUtil.isBlank(vo.getTelephone()) ? vo.getTelephone() : null) + .set(LogisticsCompany::getAddress, + !StringUtil.isBlank(vo.getAddress()) ? vo.getAddress() : null) + .set(LogisticsCompany::getAvailable, vo.getAvailable()) + .set(LogisticsCompany::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(LogisticsCompany::getId, vo.getId()); + + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + updateWrapper.set(LogisticsCompany::getCityId, vo.getCityId()); + } + } else { + updateWrapper.set(LogisticsCompany::getCityId, null); + } + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + QueryLogisticsCompanySelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @CacheEvict(value = LogisticsCompany.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/member/MemberServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/member/MemberServiceImpl.java new file mode 100644 index 0000000..388eb37 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/member/MemberServiceImpl.java @@ -0,0 +1,217 @@ +package com.lframework.xingyun.basedata.impl.member; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.mappers.MemberMapper; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.vo.member.CreateMemberVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberSelectorVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberVo; +import com.lframework.xingyun.basedata.vo.member.UpdateMemberVo; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class MemberServiceImpl extends BaseMpServiceImpl implements + MemberService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryMemberVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryMemberVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = Member.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public Member findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用会员,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Member.class) + .set(Member::getAvailable, Boolean.FALSE) + .in(Member::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用会员,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Member.class) + .set(Member::getAvailable, Boolean.TRUE) + .in(Member::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增会员,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateMemberVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + checkWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getTelephone, vo.getTelephone()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("手机号重复,请重新输入!"); + } + } + + Member data = new Member(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setGender(EnumUtil.getByCode(Gender.class, vo.getGender())); + if (!StringUtil.isBlank(vo.getTelephone())) { + data.setTelephone(vo.getTelephone()); + } + if (!StringUtil.isBlank(vo.getEmail())) { + data.setEmail(vo.getEmail()); + } + if (vo.getBirthday() != null) { + data.setBirthday(vo.getBirthday()); + } + if (vo.getJoinDay() != null) { + data.setJoinDay(vo.getJoinDay()); + } + if (!StringUtil.isBlank(vo.getShopId())) { + data.setShopId(vo.getShopId()); + } + if (!StringUtil.isBlank(vo.getGuiderId())) { + data.setGuiderId(vo.getGuiderId()); + } + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改会员,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateMemberVo vo) { + + Member data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("会员不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getCode, vo.getCode()) + .ne(Member::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + checkWrapper = Wrappers.lambdaQuery(Member.class) + .eq(Member::getTelephone, vo.getTelephone()) + .ne(Member::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("手机号重复,请重新输入!"); + } + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Member.class) + .set(Member::getCode, vo.getCode()).set(Member::getName, vo.getName()) + .set(Member::getGender, EnumUtil.getByCode(Gender.class, vo.getGender())) + .set(Member::getTelephone, + !StringUtil.isBlank(vo.getTelephone()) ? vo.getTelephone() : null) + .set(Member::getEmail, !StringUtil.isBlank(vo.getEmail()) ? vo.getEmail() : null) + .set(Member::getBirthday, vo.getBirthday() != null ? vo.getBirthday() : null) + .set(Member::getJoinDay, vo.getJoinDay() != null ? vo.getJoinDay() : null) + .set(Member::getShopId, !StringUtil.isBlank(vo.getShopId()) ? vo.getShopId() : null) + .set(Member::getGuiderId, + !StringUtil.isBlank(vo.getGuiderId()) ? vo.getGuiderId() : null) + .set(Member::getAvailable, vo.getAvailable()).set(Member::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(Member::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + QueryMemberSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @CacheEvict(value = Member.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/paytype/PayTypeServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/paytype/PayTypeServiceImpl.java new file mode 100644 index 0000000..bf349bd --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/paytype/PayTypeServiceImpl.java @@ -0,0 +1,153 @@ +package com.lframework.xingyun.basedata.impl.paytype; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.mappers.PayTypeMapper; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.vo.paytype.CreatePayTypeVo; +import com.lframework.xingyun.basedata.vo.paytype.PayTypeSelectorVo; +import com.lframework.xingyun.basedata.vo.paytype.QueryPayTypeVo; +import com.lframework.xingyun.basedata.vo.paytype.UpdatePayTypeVo; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PayTypeServiceImpl extends BaseMpServiceImpl + implements PayTypeService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryPayTypeVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryPayTypeVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, PayTypeSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = PayType.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public PayType findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增支付方式,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreatePayTypeVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(PayType.class) + .eq(PayType::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(PayType.class) + .eq(PayType::getName, vo.getName()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + PayType data = new PayType(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + data.setRecText(vo.getRecText()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改支付方式,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdatePayTypeVo vo) { + + PayType data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("支付方式不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(PayType.class) + .eq(PayType::getCode, vo.getCode()).ne(PayType::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(PayType.class) + .eq(PayType::getName, vo.getName()).ne(PayType::getId, vo.getId()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(PayType.class) + .set(PayType::getCode, vo.getCode()).set(PayType::getName, vo.getName()) + .set(PayType::getAvailable, vo.getAvailable()).set(PayType::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(PayType::getRecText, vo.getRecText()) + .eq(PayType::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = PayType.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBrandServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBrandServiceImpl.java new file mode 100644 index 0000000..032842d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBrandServiceImpl.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.mappers.ProductBrandMapper; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.vo.product.brand.CreateProductBrandVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandSelectorVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandVo; +import com.lframework.xingyun.basedata.vo.product.brand.UpdateProductBrandVo; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductBrandServiceImpl extends BaseMpServiceImpl + implements ProductBrandService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryProductBrandVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryProductBrandVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, QueryProductBrandSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = ProductBrand.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public ProductBrand findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用商品品牌,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductBrand.class) + .set(ProductBrand::getAvailable, Boolean.FALSE).in(ProductBrand::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用商品品牌,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductBrand.class) + .set(ProductBrand::getAvailable, Boolean.TRUE).in(ProductBrand::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增商品品牌,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductBrandVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(ProductBrand.class) + .eq(ProductBrand::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductBrand.class) + .eq(ProductBrand::getName, vo.getName()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + ProductBrand data = new ProductBrand(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setShortName(StringUtil.isBlank(vo.getShortName()) ? StringPool.EMPTY_STR : vo.getShortName()); + data.setIntroduction(StringUtil.isBlank(vo.getIntroduction()) ? StringPool.EMPTY_STR : vo.getIntroduction()); + data.setAvailable(Boolean.TRUE); + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + if (!StringUtil.isBlank(vo.getLogo())) { + data.setLogo(vo.getLogo()); + } + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改商品品牌,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductBrandVo vo) { + + ProductBrand data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("品牌不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(ProductBrand.class) + .eq(ProductBrand::getCode, vo.getCode()).ne(ProductBrand::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductBrand.class) + .eq(ProductBrand::getName, vo.getName()).ne(ProductBrand::getId, vo.getId()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(ProductBrand.class) + .set(ProductBrand::getCode, vo.getCode()).set(ProductBrand::getName, vo.getName()) + .set(ProductBrand::getShortName, + StringUtil.isBlank(vo.getShortName()) ? StringPool.EMPTY_STR : vo.getShortName()) + .set(ProductBrand::getLogo, StringUtil.isBlank(vo.getLogo()) ? null : vo.getLogo()) + .set(ProductBrand::getIntroduction, + StringUtil.isBlank(vo.getIntroduction()) ? StringPool.EMPTY_STR : vo.getIntroduction()) + .set(ProductBrand::getAvailable, vo.getAvailable()).set(ProductBrand::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(ProductBrand::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = ProductBrand.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBundleServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBundleServiceImpl.java new file mode 100644 index 0000000..6aec307 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductBundleServiceImpl.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.mappers.ProductBundleMapper; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class ProductBundleServiceImpl extends BaseMpServiceImpl + implements ProductBundleService { + + @Cacheable(value = ProductBundle.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null or #result.isEmpty()") + @Override + public List getByMainProductId(String id) { + Wrapper queryWrapper = Wrappers.lambdaQuery(ProductBundle.class) + .eq(ProductBundle::getMainProductId, id); + return this.list(queryWrapper); + } + + @CacheEvict(value = ProductBundle.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryPropertyServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryPropertyServiceImpl.java new file mode 100644 index 0000000..3cef55c --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryPropertyServiceImpl.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductCategoryProperty; +import com.lframework.xingyun.basedata.mappers.ProductCategoryPropertyMapper; +import com.lframework.xingyun.basedata.service.product.ProductCategoryPropertyService; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductCategoryPropertyServiceImpl + extends BaseMpServiceImpl + implements ProductCategoryPropertyService { + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(String categoryId, String propertyId) { + + ProductCategoryProperty record = new ProductCategoryProperty(); + record.setId(IdUtil.getId()); + record.setPropertyId(propertyId); + record.setCategoryId(categoryId); + + getBaseMapper().insert(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByPropertyId(String propertyId) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery( + ProductCategoryProperty.class) + .eq(ProductCategoryProperty::getPropertyId, propertyId); + getBaseMapper().delete(deleteWrapper); + } + + @Override + public List getByPropertyId(String propertyId) { + + return getBaseMapper().getByPropertyId(propertyId); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryServiceImpl.java new file mode 100644 index 0000000..7b59837 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductCategoryServiceImpl.java @@ -0,0 +1,253 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.enums.ProductCategoryNodeType; +import com.lframework.xingyun.basedata.mappers.ProductCategoryMapper; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.vo.product.category.CreateProductCategoryVo; +import com.lframework.xingyun.basedata.vo.product.category.QueryProductCategorySelectorVo; +import com.lframework.xingyun.basedata.vo.product.category.UpdateProductCategoryVo; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductCategoryServiceImpl extends + BaseMpServiceImpl + implements ProductCategoryService { + + @Autowired + private RecursionMappingService recursionMappingService; + + @Override + public List getAllProductCategories() { + + return getBaseMapper().getAllProductCategories(); + } + + @Cacheable(value = ProductCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public ProductCategory findById(String id) { + + return getBaseMapper().selectById(id); + } + + @Override + public List selector(QueryProductCategorySelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用商品类目,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + List batchIds = new ArrayList<>(); + for (String id : ids) { + List nodeChildIds = recursionMappingService.getNodeChildIds(id, + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (CollectionUtil.isEmpty(nodeChildIds)) { + continue; + } + + batchIds.addAll(nodeChildIds); + } + + batchIds.addAll(ids); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductCategory.class) + .set(ProductCategory::getAvailable, Boolean.FALSE).in(ProductCategory::getId, batchIds); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用商品类目,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + List batchIds = new ArrayList<>(); + for (String id : ids) { + List nodeParentIds = recursionMappingService.getNodeParentIds(id, + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (CollectionUtil.isEmpty(nodeParentIds)) { + continue; + } + + batchIds.addAll(nodeParentIds); + } + + batchIds.addAll(ids); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductCategory.class) + .set(ProductCategory::getAvailable, Boolean.TRUE).in(ProductCategory::getId, batchIds); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增商品类目,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductCategoryVo vo) { + + //查询Code是否重复 + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + //查询Name是否重复 + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getName, vo.getName()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + //如果parentId不为空,查询上级类目是否存在 + if (!StringUtil.isBlank(vo.getParentId())) { + Wrapper checkParentWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getId, vo.getParentId()); + if (getBaseMapper().selectCount(checkParentWrapper) == 0) { + throw new DefaultClientException("上级类目不存在,请检查!"); + } + } + + ProductCategory data = new ProductCategory(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getParentId())) { + data.setParentId(vo.getParentId()); + } + data.setAvailable(Boolean.TRUE); + data.setDescription(vo.getDescription()); + + getBaseMapper().insert(data); + + this.saveRecursion(data.getId(), data.getParentId()); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改商品类目,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductCategoryVo vo) { + + ProductCategory data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("类目不存在!"); + } + + //查询Code是否重复 + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getCode, vo.getCode()).ne(ProductCategory::getId, data.getId()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + //查询Name是否重复 + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductCategory.class) + .eq(ProductCategory::getName, vo.getName()).ne(ProductCategory::getId, data.getId()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductCategory.class) + .set(ProductCategory::getCode, vo.getCode()).set(ProductCategory::getName, vo.getName()) + .set(ProductCategory::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(ProductCategory::getAvailable, vo.getAvailable()) + .eq(ProductCategory::getId, data.getId()); + + getBaseMapper().update(updateWrapper); + + if (!vo.getAvailable()) { + if (data.getAvailable()) { + //如果是停用 子节点全部停用 + List childrenIds = recursionMappingService.getNodeChildIds(data.getId(), + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (!CollectionUtil.isEmpty(childrenIds)) { + this.batchUnable(childrenIds); + } + } + } else { + if (!data.getAvailable()) { + //如果是启用 父节点全部启用 + List parentIds = recursionMappingService.getNodeParentIds(data.getId(), + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (!CollectionUtil.isEmpty(parentIds)) { + this.batchEnable(parentIds); + } + } + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + /** + * 保存递归信息 + * + * @param categoryId + * @param parentId + */ + @Override + public void saveRecursion(String categoryId, String parentId) { + + if (!StringUtil.isBlank(parentId)) { + List parentIds = recursionMappingService.getNodeParentIds(parentId, + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (CollectionUtil.isEmpty(parentIds)) { + parentIds = new ArrayList<>(); + } + parentIds.add(parentId); + + recursionMappingService.saveNode(categoryId, + ApplicationUtil.getBean(ProductCategoryNodeType.class), + parentIds); + } else { + recursionMappingService.saveNode(categoryId, + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + } + } + + @CacheEvict(value = ProductCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyItemServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyItemServiceImpl.java new file mode 100644 index 0000000..510f42e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyItemServiceImpl.java @@ -0,0 +1,155 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import com.lframework.xingyun.basedata.mappers.ProductPropertyItemMapper; +import com.lframework.xingyun.basedata.service.product.ProductPropertyItemService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyService; +import com.lframework.xingyun.basedata.vo.product.property.item.CreateProductPropertyItemVo; +import com.lframework.xingyun.basedata.vo.product.property.item.QueryProductPropertyItemVo; +import com.lframework.xingyun.basedata.vo.product.property.item.UpdateProductPropertyItemVo; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductPropertyItemServiceImpl extends BaseMpServiceImpl + implements ProductPropertyItemService { + + @Autowired + private ProductPropertyService productPropertyService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryProductPropertyItemVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryProductPropertyItemVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public List getByPropertyId(String propertyId) { + + return getBaseMapper().getByPropertyId(propertyId); + } + + @Cacheable(value = ProductPropertyItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public ProductPropertyItem findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增商品属性值,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductPropertyItemVo vo) { + + ProductProperty property = productPropertyService.findById(vo.getPropertyId()); + if (ObjectUtil.isNull(property)) { + throw new DefaultClientException("属性不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(ProductPropertyItem.class) + .eq(ProductPropertyItem::getPropertyId, vo.getPropertyId()) + .eq(ProductPropertyItem::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductPropertyItem.class) + .eq(ProductPropertyItem::getPropertyId, vo.getPropertyId()) + .eq(ProductPropertyItem::getName, vo.getName()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + ProductPropertyItem data = new ProductPropertyItem(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setPropertyId(vo.getPropertyId()); + data.setAvailable(Boolean.TRUE); + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改商品属性值,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductPropertyItemVo vo) { + + ProductPropertyItem data = this.findById(vo.getId()); + if (data == null) { + throw new DefaultClientException("属性值不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(ProductPropertyItem.class) + .eq(ProductPropertyItem::getPropertyId, data.getPropertyId()) + .eq(ProductPropertyItem::getCode, vo.getCode()).ne(ProductPropertyItem::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductPropertyItem.class) + .eq(ProductPropertyItem::getPropertyId, data.getPropertyId()) + .eq(ProductPropertyItem::getName, vo.getName()).ne(ProductPropertyItem::getId, vo.getId()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductPropertyItem.class) + .set(ProductPropertyItem::getCode, vo.getCode()).set(ProductPropertyItem::getName, vo.getName()) + .set(ProductPropertyItem::getAvailable, vo.getAvailable()).eq(ProductPropertyItem::getId, vo.getId()) + .set(ProductPropertyItem::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = ProductPropertyItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyRelationServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyRelationServiceImpl.java new file mode 100644 index 0000000..e08f220 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyRelationServiceImpl.java @@ -0,0 +1,198 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.dto.product.ProductPropertyRelationDto; +import com.lframework.xingyun.basedata.entity.ProductCategoryProperty; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import com.lframework.xingyun.basedata.entity.ProductPropertyRelation; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.mappers.ProductPropertyRelationMapper; +import com.lframework.xingyun.basedata.service.product.ProductCategoryPropertyService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyItemService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyRelationService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.vo.product.property.realtion.CreateProductPropertyRelationVo; +import java.io.Serializable; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductPropertyRelationServiceImpl extends + BaseMpServiceImpl + implements ProductPropertyRelationService { + + @Autowired + private ProductPropertyService productPropertyService; + + @Autowired + private ProductPropertyItemService productPropertyItemService; + + @Autowired + private ProductService productService; + + @Autowired + private ProductCategoryPropertyService productCategoryPropertyService; + + @Cacheable(value = ProductPropertyRelationDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #productId", unless = "#result == null or #result.size() == 0") + @Override + public List getByProductId(String productId) { + + return getBaseMapper().getByProductId(productId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setMultipleToSimple(String propertyId) { + + List datas = getBaseMapper().getByPropertyId(propertyId); + if (!CollectionUtil.isEmpty(datas)) { + + Set checkSet = new HashSet<>(); + for (ProductPropertyRelationDto data : datas) { + if (checkSet.stream() + .anyMatch(t -> t.getProductId().equals(data.getProductId()) && t.getPropertyId() + .equals(data.getPropertyId()))) { + getBaseMapper().deleteById(data.getId()); + } else { + checkSet.add(data); + } + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setCommonToAppoint(String propertyId) { + + List categoryList = productCategoryPropertyService.getByPropertyId( + propertyId); + for (ProductCategoryProperty productCategoryPropertyDto : categoryList) { + getBaseMapper().setCommonToAppoint(propertyId, productCategoryPropertyDto.getCategoryId()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setAppointToCommon(String propertyId) { + + List propertyItems = productPropertyItemService.getByPropertyId( + propertyId); + if (!CollectionUtil.isEmpty(propertyItems)) { + ProductPropertyItem propertyItem = propertyItems.get(0); + + List productIds = productService.getIdNotInProductProperty(propertyId); + if (!CollectionUtil.isEmpty(productIds)) { + for (String productId : productIds) { + ProductPropertyRelation data = new ProductPropertyRelation(); + data.setId(IdUtil.getId()); + data.setProductId(productId); + data.setPropertyId(propertyItem.getPropertyId()); + data.setPropertyItemId(propertyItem.getId()); + + getBaseMapper().insert(data); + } + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateAppointCategoryId(String propertyId) { + + List propertyItems = productPropertyItemService.getByPropertyId( + propertyId); + if (!CollectionUtil.isEmpty(propertyItems)) { + ProductPropertyItem propertyItem = propertyItems.get(0); + + Wrapper deleteWrapper = Wrappers.lambdaQuery( + ProductPropertyRelation.class) + .eq(ProductPropertyRelation::getPropertyId, propertyId); + getBaseMapper().delete(deleteWrapper); + + List categoryList = productCategoryPropertyService.getByPropertyId( + propertyId); + for (ProductCategoryProperty productCategoryPropertyDto : categoryList) { + List productIds = productService.getIdByCategoryId( + productCategoryPropertyDto.getCategoryId()); + if (!CollectionUtil.isEmpty(productIds)) { + for (String productId : productIds) { + ProductPropertyRelation data = new ProductPropertyRelation(); + data.setId(IdUtil.getId()); + data.setProductId(productId); + data.setPropertyId(propertyItem.getPropertyId()); + data.setPropertyItemId(propertyItem.getId()); + + getBaseMapper().insert(data); + } + } + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductPropertyRelationVo vo) { + + ProductProperty productProperty = productPropertyService.findById(vo.getPropertyId()); + if (productProperty == null) { + throw new DefaultClientException("商品属性不存在!"); + } + + ProductPropertyRelation data = new ProductPropertyRelation(); + data.setId(IdUtil.getId()); + data.setProductId(vo.getProductId()); + data.setPropertyId(productProperty.getId()); + + if (productProperty.getColumnType() != ColumnType.CUSTOM) { + ProductPropertyItem propertyItem = productPropertyItemService.findById( + vo.getPropertyItemId()); + + if (propertyItem == null) { + throw new DefaultClientException("属性值不存在!"); + } + Assert.isTrue(propertyItem.getPropertyId().equals(productProperty.getId())); + + data.setPropertyItemId(propertyItem.getId()); + + } else { + if (StringUtil.isBlank(vo.getPropertyText())) { + throw new DefaultClientException("属性值文本不存在!"); + } + + data.setPropertyText(vo.getPropertyText()); + } + + getBaseMapper().insert(data); + + return data.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByProductId(String productId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery( + ProductPropertyRelation.class).eq(ProductPropertyRelation::getProductId, productId); + getBaseMapper().delete(deleteWrapper); + } + + @CacheEvict(value = ProductPropertyRelationDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyServiceImpl.java new file mode 100644 index 0000000..6fadfae --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPropertyServiceImpl.java @@ -0,0 +1,370 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.dto.product.property.ProductPropertyModelorDto; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.ProductCategoryProperty; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.enums.ColumnDataType; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.ProductCategoryNodeType; +import com.lframework.xingyun.basedata.enums.PropertyType; +import com.lframework.xingyun.basedata.mappers.ProductPropertyMapper; +import com.lframework.xingyun.basedata.service.product.ProductCategoryPropertyService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyRelationService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyService; +import com.lframework.xingyun.basedata.vo.product.property.CreateProductPropertyVo; +import com.lframework.xingyun.basedata.vo.product.property.QueryProductPropertyVo; +import com.lframework.xingyun.basedata.vo.product.property.UpdateProductPropertyVo; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductPropertyServiceImpl extends + BaseMpServiceImpl + implements ProductPropertyService { + + @Autowired + private ProductCategoryService productCategoryService; + + @Autowired + private RecursionMappingService recursionMappingService; + + @Autowired + private ProductCategoryPropertyService productCategoryPropertyService; + + @Autowired + private ProductPropertyRelationService productPropertyRelationService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryProductPropertyVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryProductPropertyVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = ProductProperty.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public ProductProperty findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用商品属性,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductProperty.class) + .set(ProductProperty::getAvailable, Boolean.FALSE).in(ProductProperty::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用商品属性,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ProductProperty.class) + .set(ProductProperty::getAvailable, Boolean.TRUE).in(ProductProperty::getId, ids); + getBaseMapper().update(updateWrapper); + } + + private List calcCategoryIds(List categoryIds) { + + if (CollectionUtil.isEmpty(categoryIds)) { + return CollectionUtil.emptyList(); + } + + //先整理categoryId,因为可能父级类目和子级类目全传过来了 + Set childCategoryIds = new HashSet<>(); + + for (String categoryId : categoryIds) { + + List children = recursionMappingService.getNodeChildIds(categoryId, + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + if (!CollectionUtil.isEmpty(children)) { + childCategoryIds.addAll(children); + } + } + + //如果传过来的categoryId在childCategoryIds中,则表示categoryId和他的父级节点一起传过来了,需要去除 + List results = categoryIds.stream().filter(t -> !childCategoryIds.contains(t)) + .collect(Collectors.toList()); + + return results; + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增商品属性,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductPropertyVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(ProductProperty.class) + .eq(ProductProperty::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductProperty.class) + .eq(ProductProperty::getName, vo.getName()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + if (vo.getPropertyType() == PropertyType.APPOINT.getCode().intValue()) { + //如果是指定类目 + if (CollectionUtil.isEmpty(vo.getCategoryIds())) { + throw new InputErrorException("请选择商品类目!"); + } + + for (String categoryId : vo.getCategoryIds()) { + ProductCategory productCategory = productCategoryService.findById(categoryId); + if (productCategory == null) { + throw new InputErrorException("商品类目数据有误,请检查!"); + } + } + + vo.setCategoryIds(this.calcCategoryIds(vo.getCategoryIds())); + } + + ProductProperty data = new ProductProperty(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setIsRequired(vo.getIsRequired()); + data.setColumnType(EnumUtil.getByCode(ColumnType.class, vo.getColumnType())); + if (data.getColumnType() == ColumnType.CUSTOM) { + if (vo.getColumnDataType() == null) { + throw new InputErrorException("数据类型不能为空!"); + } + + data.setColumnDataType(EnumUtil.getByCode(ColumnDataType.class, vo.getColumnDataType())); + } + data.setPropertyType(EnumUtil.getByCode(PropertyType.class, vo.getPropertyType())); + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + if (data.getPropertyType() == PropertyType.APPOINT) { + for (String categoryId : vo.getCategoryIds()) { + productCategoryPropertyService.create(categoryId, data.getId()); + } + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改商品属性,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductPropertyVo vo) { + + ProductProperty data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("属性不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(ProductProperty.class) + .eq(ProductProperty::getCode, vo.getCode()).ne(ProductProperty::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkNameWrapper = Wrappers.lambdaQuery(ProductProperty.class) + .eq(ProductProperty::getName, vo.getName()).ne(ProductProperty::getId, vo.getId()); + if (getBaseMapper().selectCount(checkNameWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + //如果字段类型是手动录入,那么不允许修改字段类型 + if (data.getColumnType() == ColumnType.CUSTOM) { + if (vo.getColumnType() != ColumnType.CUSTOM.getCode().intValue()) { + throw new InputErrorException("该属性的字段类型为“" + ColumnType.CUSTOM.getDesc() + "”,不允许修改!"); + } + + if (vo.getColumnDataType() == null) { + throw new InputErrorException("请选择数据类型!"); + } + + if (data.getColumnDataType().getCode().intValue() != vo.getColumnDataType()) { + throw new InputErrorException("数据类型不允许修改!"); + } + + if (vo.getPropertyType() != data.getPropertyType().getCode().intValue()) { + throw new InputErrorException("该属性不允许修改属性类别!"); + } + } + + if (data.getColumnType() != ColumnType.CUSTOM + && vo.getColumnType() == ColumnType.CUSTOM.getCode().intValue()) { + //从其他类型更改为手动录入 + throw new InputErrorException("该属性不允许将字段类型修改为“" + ColumnType.CUSTOM.getDesc() + "”!"); + } + + if (data.getPropertyType() != PropertyType.NONE + && vo.getPropertyType() == PropertyType.NONE.getCode() + .intValue()) { + throw new InputErrorException( + "该属性的属性类别为“" + data.getPropertyType().getDesc() + "”,不允许修改为“" + + PropertyType.NONE.getDesc() + "”"); + } + + List oldProductCategoryPropertyList = new ArrayList<>(); + + if (vo.getPropertyType() == PropertyType.APPOINT.getCode().intValue()) { + //如果是指定类目 + if (CollectionUtil.isEmpty(vo.getCategoryIds())) { + throw new InputErrorException("请选择商品类目!"); + } + + for (String categoryId : vo.getCategoryIds()) { + ProductCategory productCategory = productCategoryService.findById(categoryId); + if (productCategory == null) { + throw new InputErrorException("商品类目数据有误,请检查!"); + } + } + + vo.setCategoryIds(this.calcCategoryIds(vo.getCategoryIds())); + } + + if (data.getPropertyType() == PropertyType.APPOINT) { + //删除关系 + oldProductCategoryPropertyList = productCategoryPropertyService.getByPropertyId(data.getId()); + productCategoryPropertyService.deleteByPropertyId(data.getId()); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + ProductProperty.class) + .set(ProductProperty::getCode, vo.getCode()).set(ProductProperty::getName, vo.getName()) + .set(ProductProperty::getIsRequired, vo.getIsRequired()) + .set(ProductProperty::getColumnType, vo.getColumnType()) + .set(ProductProperty::getPropertyType, vo.getPropertyType()) + .set(ProductProperty::getAvailable, vo.getAvailable()).set(ProductProperty::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(ProductProperty::getId, vo.getId()); + if (vo.getColumnType() != ColumnType.CUSTOM.getCode().intValue()) { + updateWrapper.set(ProductProperty::getColumnDataType, null); + } else { + updateWrapper.set(ProductProperty::getColumnDataType, vo.getColumnDataType()); + } + + if (vo.getPropertyType() == PropertyType.APPOINT.getCode().intValue()) { + for (String categoryId : vo.getCategoryIds()) { + productCategoryPropertyService.create(categoryId, data.getId()); + } + } + + getBaseMapper().update(updateWrapper); + + if (vo.getPropertyType() != PropertyType.NONE.getCode().intValue()) { + if (data.getColumnType() == ColumnType.MULTIPLE + && vo.getColumnType() == ColumnType.SINGLE.getCode() + .intValue()) { + //从多选更改为单选 + productPropertyRelationService.setMultipleToSimple(data.getId()); + } + + if (data.getPropertyType() == PropertyType.COMMON + && vo.getPropertyType() == PropertyType.APPOINT.getCode() + .intValue()) { + //从通用改成指定类目 + productPropertyRelationService.setCommonToAppoint(data.getId()); + + } else if (data.getPropertyType() == PropertyType.APPOINT + && vo.getPropertyType() == PropertyType.COMMON.getCode().intValue()) { + //从指定类目改成通用 + productPropertyRelationService.setAppointToCommon(data.getId()); + } else if (data.getPropertyType() == PropertyType.APPOINT + && vo.getPropertyType() == PropertyType.APPOINT.getCode().intValue()) { + List oldCategoryIds = oldProductCategoryPropertyList.stream() + .map(ProductCategoryProperty::getCategoryId).collect(Collectors.toList()); + + boolean isUpdateCategory = CollectionUtil.isEqualList(oldCategoryIds, vo.getCategoryIds()); + if (isUpdateCategory) { + //更改了类目ID + productPropertyRelationService.updateAppointCategoryId(data.getId()); + } + } + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public List getModelorByCategoryId(String categoryId) { + + List parentCategoryIds = recursionMappingService.getNodeParentIds(categoryId, + ApplicationUtil.getBean(ProductCategoryNodeType.class)); + List categoryIds = new ArrayList<>(parentCategoryIds); + categoryIds.add(categoryId); + List datas = getBaseMapper().getModelorByCategoryId(categoryIds); + return datas; + } + + @CacheEvict(value = ProductProperty.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPurchaseServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPurchaseServiceImpl.java new file mode 100644 index 0000000..0ff3e52 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductPurchaseServiceImpl.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.mappers.ProductPurchaseMapper; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.vo.product.purchase.CreateProductPurchaseVo; +import com.lframework.xingyun.basedata.vo.product.purchase.UpdateProductPurchaseVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductPurchaseServiceImpl extends + BaseMpServiceImpl + implements ProductPurchaseService { + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "设置商品采购价,ID:{}, 采购价:{}", params = {"#vo.id", "#vo.price"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductPurchaseVo vo) { + + ProductPurchase data = new ProductPurchase(); + data.setId(IdUtil.getId()); + if (!StringUtil.isBlank(vo.getId())) { + data.setId(vo.getId()); + } + + data.setPrice(vo.getPrice()); + + getBaseMapper().insert(data); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "设置商品采购价,ID:{}, 采购价:{}", params = {"#vo.id", "#vo.price"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductPurchaseVo vo) { + + if (vo.getPrice() == null) { + throw new InputErrorException("采购价不能为空!"); + } + + if (vo.getPrice().doubleValue() < 0D) { + throw new InputErrorException("采购价必须大于0!"); + } + + getBaseMapper().deleteById(vo.getId()); + + CreateProductPurchaseVo createVo = new CreateProductPurchaseVo(); + createVo.setId(vo.getId()); + createVo.setPrice(vo.getPrice()); + + this.create(createVo); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductRetailServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductRetailServiceImpl.java new file mode 100644 index 0000000..965bdfc --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductRetailServiceImpl.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductRetail; +import com.lframework.xingyun.basedata.mappers.ProductRetailMapper; +import com.lframework.xingyun.basedata.service.product.ProductRetailService; +import com.lframework.xingyun.basedata.vo.product.retail.CreateProductRetailVo; +import com.lframework.xingyun.basedata.vo.product.retail.UpdateProductRetailVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductRetailServiceImpl extends BaseMpServiceImpl + implements ProductRetailService { + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "设置商品零售价,ID:{}, 零售价:{}", params = {"#vo.id", "#vo.price"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductRetailVo vo) { + + ProductRetail data = new ProductRetail(); + data.setId(IdUtil.getId()); + if (!StringUtil.isBlank(vo.getId())) { + data.setId(vo.getId()); + } + + data.setPrice(vo.getPrice()); + + getBaseMapper().insert(data); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "设置商品零售价,ID:{}, 零售价:{}", params = {"#vo.id", "#vo.price"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductRetailVo vo) { + + if (vo.getPrice() == null) { + throw new InputErrorException("零售价不能为空!"); + } + + if (vo.getPrice().doubleValue() < 0D) { + throw new InputErrorException("零售价必须大于0!"); + } + + getBaseMapper().deleteById(vo.getId()); + + CreateProductRetailVo createVo = new CreateProductRetailVo(); + createVo.setId(vo.getId()); + createVo.setPrice(vo.getPrice()); + + this.create(createVo); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductSaleServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductSaleServiceImpl.java new file mode 100644 index 0000000..7b9ccee --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductSaleServiceImpl.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.ProductSale; +import com.lframework.xingyun.basedata.mappers.ProductSaleMapper; +import com.lframework.xingyun.basedata.service.product.ProductSaleService; +import com.lframework.xingyun.basedata.vo.product.sale.CreateProductSaleVo; +import com.lframework.xingyun.basedata.vo.product.sale.UpdateProductSaleVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductSaleServiceImpl extends BaseMpServiceImpl + implements ProductSaleService { + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "设置商品销售价,ID:{}, 销售价:{}", params = {"#vo.id", "#vo.price"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductSaleVo vo) { + + ProductSale data = new ProductSale(); + data.setId(IdUtil.getId()); + if (!StringUtil.isBlank(vo.getId())) { + data.setId(vo.getId()); + } + + data.setPrice(vo.getPrice()); + + getBaseMapper().insert(data); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "设置商品销售价,ID:{}, 销售价:{}", params = {"#vo.id", "#vo.price"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductSaleVo vo) { + + if (vo.getPrice() == null) { + throw new InputErrorException("销售价不能为空!"); + } + + if (vo.getPrice().doubleValue() < 0D) { + throw new InputErrorException("销售价必须大于0!"); + } + + getBaseMapper().deleteById(vo.getId()); + + CreateProductSaleVo createVo = new CreateProductSaleVo(); + createVo.setId(vo.getId()); + createVo.setPrice(vo.getPrice()); + + this.create(createVo); + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductServiceImpl.java new file mode 100644 index 0000000..8705262 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/product/ProductServiceImpl.java @@ -0,0 +1,552 @@ +package com.lframework.xingyun.basedata.impl.product; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.JsonUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.ProductCategoryNodeType; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.mappers.ProductMapper; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyItemService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyRelationService; +import com.lframework.xingyun.basedata.service.product.ProductPropertyService; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductRetailService; +import com.lframework.xingyun.basedata.service.product.ProductSaleService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.vo.product.info.CreateProductVo; +import com.lframework.xingyun.basedata.vo.product.info.ProductPropertyRelationVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductSelectorVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductVo; +import com.lframework.xingyun.basedata.vo.product.info.UpdateProductVo; +import com.lframework.xingyun.basedata.vo.product.property.realtion.CreateProductPropertyRelationVo; +import com.lframework.xingyun.basedata.vo.product.purchase.CreateProductPurchaseVo; +import com.lframework.xingyun.basedata.vo.product.purchase.UpdateProductPurchaseVo; +import com.lframework.xingyun.basedata.vo.product.retail.CreateProductRetailVo; +import com.lframework.xingyun.basedata.vo.product.retail.UpdateProductRetailVo; +import com.lframework.xingyun.basedata.vo.product.sale.CreateProductSaleVo; +import com.lframework.xingyun.basedata.vo.product.sale.UpdateProductSaleVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductServiceImpl extends BaseMpServiceImpl implements + ProductService { + + @Autowired + private ProductPurchaseService productPurchaseService; + + @Autowired + private ProductSaleService productSaleService; + + @Autowired + private ProductRetailService productRetailService; + + @Autowired + private RecursionMappingService recursionMappingService; + + @Autowired + private ProductPropertyService productPropertyService; + + @Autowired + private ProductPropertyItemService productPropertyItemService; + + @Autowired + private ProductPropertyRelationService productPropertyRelationService; + + @Autowired + private ProductBundleService productBundleService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryProductVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + QueryProductSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public Integer queryCount(QueryProductVo vo) { + + return getBaseMapper().queryCount(vo); + } + + @Cacheable(value = Product.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public Product findById(String id) { + + return getBaseMapper().selectById(id); + } + + @Override + public List getIdNotInProductProperty(String propertyId) { + + return getBaseMapper().getIdNotInProductProperty(propertyId); + } + + @Override + public List getIdByCategoryId(String categoryId) { + + return getBaseMapper().getIdByCategoryId(categoryId); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用商品,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Product.class) + .set(Product::getAvailable, Boolean.FALSE).in(Product::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用商品,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Product.class) + .set(Product::getAvailable, Boolean.TRUE).in(Product::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增商品,ID:{}, 编号:{}", params = {"#_result", + "#vo.code"}, autoSaveParams = true) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateProductVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(Product.class).eq(Product::getSkuCode, vo.getSkuCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("商品SKU编号重复,请重新输入!"); + } + + Product data = new Product(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (StringUtil.isNotBlank(vo.getShortName())) { + data.setShortName(vo.getShortName()); + } + data.setSkuCode(vo.getSkuCode()); + if (StringUtil.isNotBlank(vo.getExternalCode())) { + data.setExternalCode(vo.getExternalCode()); + } + + data.setBrandId(vo.getBrandId()); + data.setCategoryId(vo.getCategoryId()); + + if (StringUtil.isNotBlank(vo.getSpec())) { + data.setSpec(vo.getSpec()); + } + + if (StringUtil.isNotBlank(vo.getUnit())) { + data.setUnit(vo.getUnit()); + } + + data.setProductType(EnumUtil.getByCode(ProductType.class, vo.getProductType())); + data.setTaxRate(vo.getTaxRate()); + data.setSaleTaxRate(vo.getSaleTaxRate()); + data.setWeight(vo.getWeight()); + data.setVolume(vo.getVolume()); + + data.setAvailable(Boolean.TRUE); + + getBaseMapper().insert(data); + + // 组合商品 + if (data.getProductType() == ProductType.BUNDLE) { + if (CollectionUtil.isEmpty(vo.getProductBundles())) { + throw new DefaultClientException("单品数据不能为空!"); + } + + BigDecimal salePrice = vo.getProductBundles().stream().map( + productBundleVo -> NumberUtil.mul(productBundleVo.getBundleNum(), + productBundleVo.getSalePrice())).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(vo.getSalePrice(), salePrice)) { + throw new DefaultClientException("单品的销售价设置错误!"); + } + + BigDecimal retailPrice = vo.getProductBundles().stream().map( + productBundleVo -> NumberUtil.mul(productBundleVo.getBundleNum(), + productBundleVo.getRetailPrice())).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(vo.getRetailPrice(), retailPrice)) { + throw new DefaultClientException("单品的零售价设置错误!"); + } + + List productBundles = vo.getProductBundles().stream().map(productBundleVo -> { + ProductBundle productBundle = new ProductBundle(); + productBundle.setId(IdUtil.getId()); + productBundle.setMainProductId(data.getId()); + productBundle.setProductId(productBundleVo.getProductId()); + productBundle.setBundleNum(productBundleVo.getBundleNum()); + productBundle.setSalePrice(productBundleVo.getSalePrice()); + productBundle.setRetailPrice(productBundleVo.getRetailPrice()); + + return productBundle; + }).collect(Collectors.toList()); + + productBundleService.saveBatch(productBundles); + } + + if (vo.getPurchasePrice() == null) { + throw new DefaultClientException("采购价不能为空!"); + } + + if (vo.getPurchasePrice().doubleValue() < 0D) { + throw new DefaultClientException("采购价不允许小于0!"); + } + + CreateProductPurchaseVo createProductPurchaseVo = new CreateProductPurchaseVo(); + createProductPurchaseVo.setId(data.getId()); + createProductPurchaseVo.setPrice(vo.getPurchasePrice()); + + productPurchaseService.create(createProductPurchaseVo); + + if (vo.getSalePrice() == null) { + throw new DefaultClientException("销售价不能为空!"); + } + + if (vo.getSalePrice().doubleValue() < 0D) { + throw new DefaultClientException("销售价不允许小于0!"); + } + + CreateProductSaleVo createProductSaleVo = new CreateProductSaleVo(); + createProductSaleVo.setId(data.getId()); + createProductSaleVo.setPrice(vo.getSalePrice()); + + productSaleService.create(createProductSaleVo); + + if (vo.getRetailPrice() == null) { + throw new DefaultClientException("零售价不能为空!"); + } + + if (vo.getRetailPrice().doubleValue() < 0D) { + throw new DefaultClientException("零售价不允许小于0!"); + } + + CreateProductRetailVo createProductRetailVo = new CreateProductRetailVo(); + createProductRetailVo.setId(data.getId()); + createProductRetailVo.setPrice(vo.getRetailPrice()); + + productRetailService.create(createProductRetailVo); + + if (!CollectionUtil.isEmpty(vo.getProperties())) { + // 商品和商品属性的关系 + for (ProductPropertyRelationVo property : vo.getProperties()) { + ProductProperty productProperty = productPropertyService.findById(property.getId()); + if (productProperty == null) { + throw new DefaultClientException("商品属性不存在!"); + } + if (productProperty.getColumnType() == ColumnType.SINGLE) { + ProductPropertyItem propertyItem = productPropertyItemService.findById( + property.getText()); + if (propertyItem == null) { + throw new DefaultClientException("商品属性值不存在!"); + } + + CreateProductPropertyRelationVo createProductPropertyRelationVo = new CreateProductPropertyRelationVo(); + createProductPropertyRelationVo.setProductId(data.getId()); + createProductPropertyRelationVo.setPropertyId(productProperty.getId()); + createProductPropertyRelationVo.setPropertyItemId(propertyItem.getId()); + + productPropertyRelationService.create(createProductPropertyRelationVo); + } else if (productProperty.getColumnType() == ColumnType.MULTIPLE) { + + List propertyItemIds = JsonUtil.parseList(property.getText(), String.class); + for (String propertyItemId : propertyItemIds) { + CreateProductPropertyRelationVo createProductPropertyRelationVo = new CreateProductPropertyRelationVo(); + createProductPropertyRelationVo.setProductId(data.getId()); + createProductPropertyRelationVo.setPropertyId(productProperty.getId()); + createProductPropertyRelationVo.setPropertyItemId(propertyItemId); + + productPropertyRelationService.create(createProductPropertyRelationVo); + } + + } else if (productProperty.getColumnType() == ColumnType.CUSTOM) { + + CreateProductPropertyRelationVo createProductPropertyRelationVo = new CreateProductPropertyRelationVo(); + createProductPropertyRelationVo.setProductId(data.getId()); + createProductPropertyRelationVo.setPropertyId(productProperty.getId()); + createProductPropertyRelationVo.setPropertyText(property.getText()); + productPropertyRelationService.create(createProductPropertyRelationVo); + } else { + throw new DefaultClientException("商品属性字段类型不存在!"); + } + } + } + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改商品,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateProductVo vo) { + + Product data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("商品不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getCode, vo.getCode()).ne(Product::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(Product.class).eq(Product::getSkuCode, vo.getSkuCode()) + .ne(Product::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("商品SKU编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Product.class) + .set(Product::getCode, vo.getCode()).set(Product::getName, vo.getName()) + .set(Product::getAvailable, vo.getAvailable()).set(Product::getSkuCode, vo.getSkuCode()) + .set(Product::getExternalCode, + StringUtil.isBlank(vo.getExternalCode()) ? null : vo.getExternalCode()) + .set(Product::getSpec, StringUtil.isBlank(vo.getSpec()) ? null : vo.getSpec()) + .set(Product::getUnit, StringUtil.isBlank(vo.getUnit()) ? null : vo.getUnit()) + .set(Product::getShortName, + StringUtil.isBlank(vo.getShortName()) ? null : vo.getShortName()) + .set(Product::getCategoryId, + StringUtil.isBlank(vo.getCategoryId()) ? null : vo.getCategoryId()) + .set(Product::getBrandId, StringUtil.isBlank(vo.getBrandId()) ? null : vo.getBrandId()) + .set(Product::getTaxRate, vo.getTaxRate()) + .set(Product::getSaleTaxRate, vo.getSaleTaxRate()) + .set(Product::getWeight, vo.getWeight()) + .set(Product::getVolume, vo.getVolume()) + .eq(Product::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + // 组合商品 + if (data.getProductType() == ProductType.BUNDLE) { + if (CollectionUtil.isEmpty(vo.getProductBundles())) { + throw new DefaultClientException("单品数据不能为空!"); + } + + BigDecimal salePrice = vo.getProductBundles().stream().map( + productBundleVo -> NumberUtil.mul(productBundleVo.getBundleNum(), + productBundleVo.getSalePrice())).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(vo.getSalePrice(), salePrice)) { + throw new DefaultClientException("单品的销售价设置错误!"); + } + + BigDecimal retailPrice = vo.getProductBundles().stream().map( + productBundleVo -> NumberUtil.mul(productBundleVo.getBundleNum(), + productBundleVo.getRetailPrice())).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(vo.getRetailPrice(), retailPrice)) { + throw new DefaultClientException("单品的零售价设置错误!"); + } + + Wrapper deleteBundleWrapper = Wrappers.lambdaQuery(ProductBundle.class) + .eq(ProductBundle::getMainProductId, data.getId()); + productBundleService.remove(deleteBundleWrapper); + + List productBundles = vo.getProductBundles().stream().map(productBundleVo -> { + ProductBundle productBundle = new ProductBundle(); + productBundle.setId(IdUtil.getId()); + productBundle.setMainProductId(data.getId()); + productBundle.setProductId(productBundleVo.getProductId()); + productBundle.setBundleNum(productBundleVo.getBundleNum()); + productBundle.setSalePrice(productBundleVo.getSalePrice()); + productBundle.setRetailPrice(productBundleVo.getRetailPrice()); + + return productBundle; + }).collect(Collectors.toList()); + + productBundleService.saveBatch(productBundles); + } + + productPropertyRelationService.deleteByProductId(data.getId()); + if (!CollectionUtil.isEmpty(vo.getProperties())) { + // 商品和商品属性的关系 + for (ProductPropertyRelationVo property : vo.getProperties()) { + ProductProperty productProperty = productPropertyService.findById(property.getId()); + if (productProperty == null) { + throw new DefaultClientException("商品属性不存在!"); + } + if (productProperty.getColumnType() == ColumnType.SINGLE) { + ProductPropertyItem propertyItem = productPropertyItemService.findById( + property.getText()); + if (propertyItem == null) { + throw new DefaultClientException("商品属性值不存在!"); + } + + CreateProductPropertyRelationVo createProductPropertyRelationVo = new CreateProductPropertyRelationVo(); + createProductPropertyRelationVo.setProductId(data.getId()); + createProductPropertyRelationVo.setPropertyId(productProperty.getId()); + createProductPropertyRelationVo.setPropertyItemId(propertyItem.getId()); + + productPropertyRelationService.create(createProductPropertyRelationVo); + } else if (productProperty.getColumnType() == ColumnType.MULTIPLE) { + + List propertyItemIds = JsonUtil.parseList(property.getText(), String.class); + for (String propertyItemId : propertyItemIds) { + CreateProductPropertyRelationVo createProductPropertyRelationVo = new CreateProductPropertyRelationVo(); + createProductPropertyRelationVo.setProductId(data.getId()); + createProductPropertyRelationVo.setPropertyId(productProperty.getId()); + createProductPropertyRelationVo.setPropertyItemId(propertyItemId); + + productPropertyRelationService.create(createProductPropertyRelationVo); + } + + } else if (productProperty.getColumnType() == ColumnType.CUSTOM) { + + CreateProductPropertyRelationVo createProductPropertyRelationVo = new CreateProductPropertyRelationVo(); + createProductPropertyRelationVo.setProductId(data.getId()); + createProductPropertyRelationVo.setPropertyId(productProperty.getId()); + createProductPropertyRelationVo.setPropertyText(property.getText()); + productPropertyRelationService.create(createProductPropertyRelationVo); + } else { + throw new DefaultClientException("商品属性字段类型不存在!"); + } + } + } + + productPurchaseService.removeById(data.getId()); + + if (vo.getPurchasePrice() != null) { + + UpdateProductPurchaseVo updateProductPurchaseVo = new UpdateProductPurchaseVo(); + updateProductPurchaseVo.setId(data.getId()); + updateProductPurchaseVo.setPrice(vo.getPurchasePrice()); + + productPurchaseService.update(updateProductPurchaseVo); + } + + productSaleService.removeById(data.getId()); + + if (vo.getSalePrice() != null) { + UpdateProductSaleVo updateProductSaleVo = new UpdateProductSaleVo(); + updateProductSaleVo.setId(data.getId()); + updateProductSaleVo.setPrice(vo.getSalePrice()); + + productSaleService.update(updateProductSaleVo); + } + + productRetailService.removeById(data.getId()); + if (vo.getRetailPrice() != null) { + UpdateProductRetailVo updateProductRetailVo = new UpdateProductRetailVo(); + updateProductRetailVo.setId(data.getId()); + updateProductRetailVo.setPrice(vo.getRetailPrice()); + + productRetailService.update(updateProductRetailVo); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public List getByCategoryIds(List categoryIds, Integer productType) { + + if (CollectionUtil.isEmpty(categoryIds)) { + return CollectionUtil.emptyList(); + } + + // 根据categoryIds查询所有叶子节点 + List children = new ArrayList<>(); + for (String categoryId : categoryIds) { + children.addAll(recursionMappingService.getNodeChildIds(categoryId, + ApplicationUtil.getBean(ProductCategoryNodeType.class))); + } + + children.addAll(categoryIds); + + children = children.stream().distinct().collect(Collectors.toList()); + + List datas = getBaseMapper().getByCategoryIds(children, productType); + + return datas; + } + + @Override + public List getByBrandIds(List brandIds, Integer productType) { + + if (CollectionUtil.isEmpty(brandIds)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByBrandIds(brandIds, productType); + } + + @CacheEvict(value = Product.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/shop/ShopServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/shop/ShopServiceImpl.java new file mode 100644 index 0000000..161effc --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/shop/ShopServiceImpl.java @@ -0,0 +1,133 @@ +package com.lframework.xingyun.basedata.impl.shop; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.mappers.ShopMapper; +import com.lframework.xingyun.basedata.service.shop.ShopService; +import com.lframework.xingyun.basedata.vo.shop.CreateShopVo; +import com.lframework.xingyun.basedata.vo.shop.QueryShopVo; +import com.lframework.xingyun.basedata.vo.shop.UpdateShopVo; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ShopServiceImpl extends BaseMpServiceImpl implements ShopService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryShopVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryShopVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = Shop.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public Shop findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增门店,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateShopVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(Shop.class).eq(Shop::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Shop data = new Shop(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getDeptId())) { + data.setDeptId(vo.getDeptId()); + } + if (vo.getLng() != null) { + data.setLng(vo.getLng()); + } + if (vo.getLat() != null) { + data.setLat(vo.getLat()); + } + if (!StringUtil.isBlank(vo.getDescription())) { + data.setDescription(vo.getDescription()); + } + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改门店,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateShopVo vo) { + + Shop data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("门店不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(Shop.class).eq(Shop::getCode, vo.getCode()) + .ne(Shop::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Shop.class) + .set(Shop::getCode, vo.getCode()) + .set(Shop::getName, vo.getName()) + .set(Shop::getDeptId, StringUtil.isBlank(vo.getDeptId()) ? null : vo.getDeptId()) + .set(Shop::getLng, vo.getLng() == null ? null : vo.getLng()) + .set(Shop::getLat, vo.getLat() == null ? null : vo.getLat()) + .set(Shop::getAvailable, vo.getAvailable()) + .set(Shop::getDescription, + StringUtil.isBlank(vo.getDescription()) ? null : vo.getDescription()) + .eq(Shop::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = Shop.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/storecenter/StoreCenterServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/storecenter/StoreCenterServiceImpl.java new file mode 100644 index 0000000..43ec42e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/storecenter/StoreCenterServiceImpl.java @@ -0,0 +1,213 @@ +package com.lframework.xingyun.basedata.impl.storecenter; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.mappers.StoreCenterMapper; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.vo.storecenter.CreateStoreCenterVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterSelectorVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterVo; +import com.lframework.xingyun.basedata.vo.storecenter.UpdateStoreCenterVo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StoreCenterServiceImpl extends BaseMpServiceImpl + implements StoreCenterService { + + @Autowired + private DicCityService dicCityService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryStoreCenterVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = StoreCenter.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public StoreCenter findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用仓库,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(StoreCenter.class) + .set(StoreCenter::getAvailable, Boolean.FALSE).in(StoreCenter::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用仓库,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(StoreCenter.class) + .set(StoreCenter::getAvailable, Boolean.TRUE).in(StoreCenter::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增仓库,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateStoreCenterVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(StoreCenter.class) + .eq(StoreCenter::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + StoreCenter data = new StoreCenter(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getContact())) { + data.setContact(vo.getContact()); + } + if (!StringUtil.isBlank(vo.getTelephone())) { + data.setTelephone(vo.getTelephone()); + } + data.setAvailable(Boolean.TRUE); + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + data.setCityId(vo.getCityId()); + } + } + + if (!StringUtil.isBlank(vo.getAddress())) { + data.setAddress(vo.getAddress()); + } + + if (vo.getPeopleNum() != null) { + if (vo.getPeopleNum() < 0) { + throw new InputErrorException("仓库人数不允许小于0!"); + } + data.setPeopleNum(vo.getPeopleNum()); + } + + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改仓库,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateStoreCenterVo vo) { + + StoreCenter data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("仓库不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(StoreCenter.class) + .eq(StoreCenter::getCode, vo.getCode()).ne(StoreCenter::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(StoreCenter.class) + .set(StoreCenter::getCode, vo.getCode()).set(StoreCenter::getName, vo.getName()) + .set(StoreCenter::getContact, !StringUtil.isBlank(vo.getContact()) ? vo.getContact() : null) + .set(StoreCenter::getTelephone, !StringUtil.isBlank(vo.getTelephone()) ? vo.getTelephone() : null) + .set(StoreCenter::getAvailable, vo.getAvailable()) + .set(StoreCenter::getAddress, !StringUtil.isBlank(vo.getAddress()) ? vo.getAddress() : null) + .set(StoreCenter::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(StoreCenter::getId, vo.getId()); + + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + updateWrapper.set(StoreCenter::getCityId, vo.getCityId()); + } + } else { + updateWrapper.set(StoreCenter::getCityId, null); + } + + if (vo.getPeopleNum() != null) { + if (vo.getPeopleNum() < 0) { + throw new InputErrorException("仓库人数不允许小于0!"); + } + updateWrapper.set(StoreCenter::getPeopleNum, vo.getPeopleNum()); + } else { + updateWrapper.set(StoreCenter::getPeopleNum, null); + } + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, QueryStoreCenterSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @CacheEvict(value = StoreCenter.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/supplier/SupplierServiceImpl.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/supplier/SupplierServiceImpl.java new file mode 100644 index 0000000..1dfa6ad --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/impl/supplier/SupplierServiceImpl.java @@ -0,0 +1,246 @@ +package com.lframework.xingyun.basedata.impl.supplier; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.basedata.enums.BaseDataOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.enums.SettleType; +import com.lframework.xingyun.basedata.mappers.SupplierMapper; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.basedata.vo.supplier.CreateSupplierVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierSelectorVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierVo; +import com.lframework.xingyun.basedata.vo.supplier.UpdateSupplierVo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SupplierServiceImpl extends BaseMpServiceImpl implements + SupplierService { + + @Autowired + private DicCityService dicCityService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySupplierVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySupplierVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = Supplier.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public Supplier findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "停用供应商,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Supplier.class) + .set(Supplier::getAvailable, Boolean.FALSE).in(Supplier::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "启用供应商,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(Supplier.class) + .set(Supplier::getAvailable, Boolean.TRUE).in(Supplier::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "新增供应商,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSupplierVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(Supplier.class).eq(Supplier::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Supplier data = new Supplier(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getMnemonicCode())) { + data.setMnemonicCode(vo.getMnemonicCode()); + } + if (!StringUtil.isBlank(vo.getContact())) { + data.setContact(vo.getContact()); + } + if (!StringUtil.isBlank(vo.getTelephone())) { + data.setTelephone(vo.getTelephone()); + } + if (!StringUtil.isBlank(vo.getEmail())) { + data.setEmail(vo.getEmail()); + } + if (!StringUtil.isBlank(vo.getZipCode())) { + data.setZipCode(vo.getZipCode()); + } + if (!StringUtil.isBlank(vo.getFax())) { + data.setFax(vo.getFax()); + } + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + data.setCityId(vo.getCityId()); + } + } + if (!StringUtil.isBlank(vo.getAddress())) { + data.setAddress(vo.getAddress()); + } + if (vo.getDeliveryCycle() != null) { + data.setDeliveryCycle(vo.getDeliveryCycle()); + } + data.setManageType(EnumUtil.getByCode(ManageType.class, vo.getManageType())); + + data.setSettleType(EnumUtil.getByCode(SettleType.class, vo.getSettleType())); + + if (!StringUtil.isBlank(vo.getCreditCode())) { + data.setCreditCode(vo.getCreditCode()); + } + if (!StringUtil.isBlank(vo.getTaxIdentifyNo())) { + data.setTaxIdentifyNo(vo.getTaxIdentifyNo()); + } + if (!StringUtil.isBlank(vo.getBankName())) { + data.setBankName(vo.getBankName()); + } + if (!StringUtil.isBlank(vo.getAccountName())) { + data.setAccountName(vo.getAccountName()); + } + if (!StringUtil.isBlank(vo.getAccountNo())) { + data.setAccountNo(vo.getAccountNo()); + } + data.setAvailable(Boolean.TRUE); + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = BaseDataOpLogType.BASE_DATA, name = "修改供应商,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSupplierVo vo) { + + Supplier data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("供应商不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(Supplier.class).eq(Supplier::getCode, vo.getCode()) + .ne(Supplier::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Supplier.class) + .set(Supplier::getCode, vo.getCode()).set(Supplier::getName, vo.getName()) + .set(Supplier::getMnemonicCode, !StringUtil.isBlank(vo.getMnemonicCode()) ? vo.getMnemonicCode() : null) + .set(Supplier::getContact, !StringUtil.isBlank(vo.getContact()) ? vo.getContact() : null) + .set(Supplier::getTelephone, !StringUtil.isBlank(vo.getTelephone()) ? vo.getTelephone() : null) + .set(Supplier::getEmail, !StringUtil.isBlank(vo.getEmail()) ? vo.getEmail() : null) + .set(Supplier::getZipCode, !StringUtil.isBlank(vo.getZipCode()) ? vo.getZipCode() : null) + .set(Supplier::getFax, !StringUtil.isBlank(vo.getFax()) ? vo.getFax() : null) + .set(Supplier::getAddress, !StringUtil.isBlank(vo.getAddress()) ? vo.getAddress() : null) + .set(Supplier::getDeliveryCycle, vo.getDeliveryCycle()) + .set(Supplier::getCreditCode, !StringUtil.isBlank(vo.getCreditCode()) ? vo.getCreditCode() : null) + .set(Supplier::getTaxIdentifyNo, + !StringUtil.isBlank(vo.getTaxIdentifyNo()) ? vo.getTaxIdentifyNo() : null) + .set(Supplier::getBankName, !StringUtil.isBlank(vo.getBankName()) ? vo.getBankName() : null) + .set(Supplier::getAccountName, !StringUtil.isBlank(vo.getAccountName()) ? vo.getAccountName() : null) + .set(Supplier::getAccountNo, !StringUtil.isBlank(vo.getAccountNo()) ? vo.getAccountNo() : null) + .set(Supplier::getAvailable, vo.getAvailable()).set(Supplier::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(Supplier::getId, vo.getId()); + + if (!StringUtil.isBlank(vo.getCityId())) { + DicCityDto city = dicCityService.findById(vo.getCityId()); + if (!ObjectUtil.isNull(city)) { + updateWrapper.set(Supplier::getCityId, vo.getCityId()); + } + } else { + updateWrapper.set(Supplier::getCityId, null); + } + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, QuerySupplierSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @CacheEvict(value = Supplier.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/AddressMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/AddressMapper.java new file mode 100644 index 0000000..2112480 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/AddressMapper.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.vo.address.AddressSelectorVo; +import com.lframework.xingyun.basedata.vo.address.QueryAddressVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2023-03-26 + */ +public interface AddressMapper extends BaseMapper
{ + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "createTime", alias = "tb", autoParse = true) + }) + List
query(@Param("vo") QueryAddressVo vo); + + /** + * 选择器 + * + * @return + */ + List
selector(@Param("vo") AddressSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/CustomerMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/CustomerMapper.java new file mode 100644 index 0000000..b860b68 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/CustomerMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerSelectorVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-10 + */ +public interface CustomerMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QueryCustomerVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") QueryCustomerSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/LogisticsCompanyMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/LogisticsCompanyMapper.java new file mode 100644 index 0000000..03b94e0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/LogisticsCompanyMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanySelectorVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanyVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 物流公司 Mapper 接口 + *

+ * + * @author zmj + * @since 2023-06-02 + */ +public interface LogisticsCompanyMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QueryLogisticsCompanyVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") QueryLogisticsCompanySelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/MemberMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/MemberMapper.java new file mode 100644 index 0000000..6bfdd72 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/MemberMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.vo.member.QueryMemberSelectorVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface MemberMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QueryMemberVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") QueryMemberSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/PayTypeMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/PayTypeMapper.java new file mode 100644 index 0000000..b2de9a9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/PayTypeMapper.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.vo.paytype.PayTypeSelectorVo; +import com.lframework.xingyun.basedata.vo.paytype.QueryPayTypeVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface PayTypeMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QueryPayTypeVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") PayTypeSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBrandMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBrandMapper.java new file mode 100644 index 0000000..b102495 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBrandMapper.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandSelectorVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-06 + */ +public interface ProductBrandMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + }) + List query(@Param("vo") QueryProductBrandVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") QueryProductBrandSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBundleMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBundleMapper.java new file mode 100644 index 0000000..87a0e7b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductBundleMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductBundle; + +/** + *

+ * 组合商品 Mapper 接口 + *

+ * + * @author zmj + * @since 2023-05-26 + */ +public interface ProductBundleMapper extends BaseMapper { + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryMapper.java new file mode 100644 index 0000000..15bea9a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.vo.product.category.QueryProductCategorySelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-05 + */ +public interface ProductCategoryMapper extends BaseMapper { + + /** + * 查询全部类目信息 + * + * @return + */ + List getAllProductCategories(); + + /** + * 选择器 + * + * @return + */ + List selector(@Param("vo") QueryProductCategorySelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryPropertyMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryPropertyMapper.java new file mode 100644 index 0000000..5608fbf --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductCategoryPropertyMapper.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductCategoryProperty; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-05 + */ +public interface ProductCategoryPropertyMapper extends BaseMapper { + + /** + * 根据属性ID查询 + * + * @param propertyId + * @return + */ + List getByPropertyId(String propertyId); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductMapper.java new file mode 100644 index 0000000..fd6dab8 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductMapper.java @@ -0,0 +1,106 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductSelectorVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface ProductMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + @Sorts({ + @Sort(value = "code", alias = "g", autoParse = true), + @Sort(value = "name", alias = "g", autoParse = true), + @Sort(value = "createTime", alias = "g", autoParse = true), + @Sort(value = "updateTime", alias = "g", autoParse = true), + }) + List query(@Param("vo") QueryProductVo vo); + + /** + * 查询商品品种数 + * + * @param vo + * @return + */ + Integer queryCount(@Param("vo") QueryProductVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List selector(@Param("vo") QueryProductSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Product findById(String id); + + /** + * 查询没有属性的ID + * + * @param propertyId + * @return + */ + List getIdNotInProductProperty(String propertyId); + + /** + * 根据类目ID查询 + * + * @param categoryId + * @return + */ + List getIdByCategoryId(String categoryId); + + /** + * 根据类目ID查询 + * + * @param categoryIds + * @return + */ + List getByCategoryIds(@Param("categoryIds") List categoryIds, + @Param("productType") Integer productType); + + /** + * 根据品牌ID查询 + * + * @param brandIds + * @return + */ + List getByBrandIds(@Param("brandIds") List brandIds, + @Param("productType") Integer productType); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyItemMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyItemMapper.java new file mode 100644 index 0000000..c033362 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyItemMapper.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import com.lframework.xingyun.basedata.vo.product.property.item.QueryProductPropertyItemVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-08-08 + */ +public interface ProductPropertyItemMapper extends BaseMapper { + + /** + * 查询里诶包 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryProductPropertyItemVo vo); + + /** + * 根据属性ID查询 + * + * @param propertyId + * @return + */ + List getByPropertyId(String propertyId); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyMapper.java new file mode 100644 index 0000000..c7b778e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyMapper.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.dto.product.property.ProductPropertyModelorDto; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.vo.product.property.QueryProductPropertyVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.Collection; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface ProductPropertyMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "p", autoParse = true), + @Sort(value = "name", alias = "p", autoParse = true), + }) + List query(@Param("vo") QueryProductPropertyVo vo); + + /** + * 根据商品类目查询 + * + * @param categoryIds + * @return + */ + List getModelorByCategoryId(@Param("categoryIds") Collection categoryIds); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyRelationMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyRelationMapper.java new file mode 100644 index 0000000..c5bdcc1 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPropertyRelationMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.dto.product.ProductPropertyRelationDto; +import com.lframework.xingyun.basedata.entity.ProductPropertyRelation; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-08-05 + */ +public interface ProductPropertyRelationMapper extends BaseMapper { + + /** + * 根据商品ID查询 + * + * @param productId + * @return + */ + List getByProductId(String productId); + + /** + * 根据属性ID查询 + * + * @param propertyId + * @return + */ + List getByPropertyId(String propertyId); + + /** + * 将通用更改为指定类目 + * + * @param propertyId + * @param categoryId + */ + void setCommonToAppoint(@Param("propertyId") String propertyId, @Param("categoryId") String categoryId); + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPurchaseMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPurchaseMapper.java new file mode 100644 index 0000000..44e4ea9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductPurchaseMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductPurchase; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface ProductPurchaseMapper extends BaseMapper { + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductRetailMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductRetailMapper.java new file mode 100644 index 0000000..d10e429 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductRetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductRetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface ProductRetailMapper extends BaseMapper { + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductSaleMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductSaleMapper.java new file mode 100644 index 0000000..a9df969 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ProductSaleMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.ProductSale; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface ProductSaleMapper extends BaseMapper { + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ShopMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ShopMapper.java new file mode 100644 index 0000000..5fa16d9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/ShopMapper.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.vo.shop.QueryShopVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 门店 Mapper 接口 + *

+ * + * @author zmj + */ +public interface ShopMapper extends BaseMapper { + + /** + * 查询列表 + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + @Sort(value = "createTime", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QueryShopVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/StoreCenterMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/StoreCenterMapper.java new file mode 100644 index 0000000..c4582f9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/StoreCenterMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterSelectorVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-07 + */ +public interface StoreCenterMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QueryStoreCenterVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") QueryStoreCenterSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/SupplierMapper.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/SupplierMapper.java new file mode 100644 index 0000000..89419e9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/mappers/SupplierMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierSelectorVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-11 + */ +public interface SupplierMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QuerySupplierVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") QuerySupplierSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/address/AddressService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/address/AddressService.java new file mode 100644 index 0000000..0958d5a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/address/AddressService.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.basedata.service.address; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.basedata.vo.address.AddressSelectorVo; +import com.lframework.xingyun.basedata.vo.address.CreateAddressVo; +import com.lframework.xingyun.basedata.vo.address.QueryAddressVo; +import com.lframework.xingyun.basedata.vo.address.UpdateAddressVo; +import java.util.List; + +/** + * 地址库 Service + * + * @author zmj + */ +public interface AddressService extends BaseMpService
{ + + /** + * 查询列表 + * + * @return + */ + PageResult
query(Integer pageIndex, Integer pageSize, QueryAddressVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List
query(QueryAddressVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult
selector(Integer pageIndex, Integer pageSize, + AddressSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Address findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateAddressVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateAddressVo vo); + + /** + * 查询默认地址 + * + * @param entityId + * @param entityType + * @param addressType + * @return + */ + Address getDefaultAddress(String entityId, Integer entityType, Integer addressType); + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/customer/CustomerService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/customer/CustomerService.java new file mode 100644 index 0000000..3ea471d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/customer/CustomerService.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.basedata.service.customer; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.vo.customer.CreateCustomerVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerSelectorVo; +import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo; +import com.lframework.xingyun.basedata.vo.customer.UpdateCustomerVo; +import java.util.Collection; +import java.util.List; + +public interface CustomerService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryCustomerVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryCustomerVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Customer findById(String id); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, QueryCustomerSelectorVo vo); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateCustomerVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateCustomerVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/logistics/LogisticsCompanyService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/logistics/LogisticsCompanyService.java new file mode 100644 index 0000000..2837874 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/logistics/LogisticsCompanyService.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.basedata.service.logistics; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.vo.logistics.company.CreateLogisticsCompanyVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanySelectorVo; +import com.lframework.xingyun.basedata.vo.logistics.company.QueryLogisticsCompanyVo; +import com.lframework.xingyun.basedata.vo.logistics.company.UpdateLogisticsCompanyVo; +import java.util.Collection; +import java.util.List; + +public interface LogisticsCompanyService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryLogisticsCompanyVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryLogisticsCompanyVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + LogisticsCompany findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateLogisticsCompanyVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateLogisticsCompanyVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + QueryLogisticsCompanySelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/member/MemberService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/member/MemberService.java new file mode 100644 index 0000000..684c95a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/member/MemberService.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.basedata.service.member; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.vo.member.CreateMemberVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberSelectorVo; +import com.lframework.xingyun.basedata.vo.member.QueryMemberVo; +import com.lframework.xingyun.basedata.vo.member.UpdateMemberVo; +import java.util.Collection; +import java.util.List; + +public interface MemberService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryMemberVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryMemberVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Member findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateMemberVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateMemberVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, QueryMemberSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/paytype/PayTypeService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/paytype/PayTypeService.java new file mode 100644 index 0000000..1821fbf --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/paytype/PayTypeService.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.basedata.service.paytype; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.vo.paytype.CreatePayTypeVo; +import com.lframework.xingyun.basedata.vo.paytype.PayTypeSelectorVo; +import com.lframework.xingyun.basedata.vo.paytype.QueryPayTypeVo; +import com.lframework.xingyun.basedata.vo.paytype.UpdatePayTypeVo; +import java.util.List; + +public interface PayTypeService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryPayTypeVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryPayTypeVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + PayTypeSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PayType findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreatePayTypeVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdatePayTypeVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBrandService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBrandService.java new file mode 100644 index 0000000..2395681 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBrandService.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.vo.product.brand.CreateProductBrandVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandSelectorVo; +import com.lframework.xingyun.basedata.vo.product.brand.QueryProductBrandVo; +import com.lframework.xingyun.basedata.vo.product.brand.UpdateProductBrandVo; +import java.util.Collection; +import java.util.List; + +public interface ProductBrandService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryProductBrandVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryProductBrandVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + QueryProductBrandSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ProductBrand findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductBrandVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductBrandVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBundleService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBundleService.java new file mode 100644 index 0000000..92747c2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductBundleService.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import java.util.List; + +public interface ProductBundleService extends BaseMpService { + + /** + * 根据组合商品ID查询 + * @param id + * @return + */ + List getByMainProductId(String id); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryPropertyService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryPropertyService.java new file mode 100644 index 0000000..cea80a9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryPropertyService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductCategoryProperty; +import java.util.List; + +public interface ProductCategoryPropertyService extends BaseMpService { + + /** + * 创建 + * + * @param categoryId + * @param propertyId + * @return + */ + String create(String categoryId, String propertyId); + + /** + * 根据属性ID删除 + * + * @param propertyId + */ + void deleteByPropertyId(String propertyId); + + /** + * 根据属性ID查询 + * + * @param propertyId + * @return + */ + List getByPropertyId(String propertyId); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryService.java new file mode 100644 index 0000000..ca2f418 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductCategoryService.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.vo.product.category.CreateProductCategoryVo; +import com.lframework.xingyun.basedata.vo.product.category.QueryProductCategorySelectorVo; +import com.lframework.xingyun.basedata.vo.product.category.UpdateProductCategoryVo; +import java.util.Collection; +import java.util.List; + +public interface ProductCategoryService extends BaseMpService { + + /** + * 查询全部类目信息 + * + * @return + */ + List getAllProductCategories(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ProductCategory findById(String id); + + /** + * 选择器 + * + * @return + */ + List selector(QueryProductCategorySelectorVo vo); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductCategoryVo vo); + + /** + * 保存关系 + * + * @param categoryId + * @param parentId + */ + void saveRecursion(String categoryId, String parentId); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyItemService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyItemService.java new file mode 100644 index 0000000..22b0e72 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyItemService.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductPropertyItem; +import com.lframework.xingyun.basedata.vo.product.property.item.CreateProductPropertyItemVo; +import com.lframework.xingyun.basedata.vo.product.property.item.QueryProductPropertyItemVo; +import com.lframework.xingyun.basedata.vo.product.property.item.UpdateProductPropertyItemVo; +import java.util.List; + +public interface ProductPropertyItemService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryProductPropertyItemVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryProductPropertyItemVo vo); + + /** + * 根据属性ID查询 + * + * @param propertyId + * @return + */ + List getByPropertyId(String propertyId); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ProductPropertyItem findById(String id); + + /** + * 新增 + * + * @param vo + * @return + */ + String create(CreateProductPropertyItemVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductPropertyItemVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyRelationService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyRelationService.java new file mode 100644 index 0000000..c91bb45 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyRelationService.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.dto.product.ProductPropertyRelationDto; +import com.lframework.xingyun.basedata.entity.ProductPropertyRelation; +import com.lframework.xingyun.basedata.vo.product.property.realtion.CreateProductPropertyRelationVo; +import java.util.List; + +public interface ProductPropertyRelationService extends BaseMpService { + + /** + * 根据商品Id查询 + * + * @param productId + * @return + */ + List getByProductId(String productId); + + /** + * 将多选属性更改为单选属性 + * + * @param propertyId + */ + void setMultipleToSimple(String propertyId); + + /** + * 从通用改为指定类目 + * + * @param propertyId + */ + void setCommonToAppoint(String propertyId); + + /** + * 从指定类目改为通用 + * + * @param propertyId + */ + void setAppointToCommon(String propertyId); + + /** + * 修改指定类目的类目ID + * + * @param propertyId + */ + void updateAppointCategoryId(String propertyId); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductPropertyRelationVo vo); + + /** + * 根据商品Id删除 + * + * @param productId + */ + void deleteByProductId(String productId); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyService.java new file mode 100644 index 0000000..742b7c3 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPropertyService.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.dto.product.property.ProductPropertyModelorDto; +import com.lframework.xingyun.basedata.entity.ProductProperty; +import com.lframework.xingyun.basedata.vo.product.property.CreateProductPropertyVo; +import com.lframework.xingyun.basedata.vo.product.property.QueryProductPropertyVo; +import com.lframework.xingyun.basedata.vo.product.property.UpdateProductPropertyVo; +import java.util.Collection; +import java.util.List; + +public interface ProductPropertyService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryProductPropertyVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryProductPropertyVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ProductProperty findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductPropertyVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductPropertyVo vo); + + /** + * 根据类目ID查询 + * + * @param categoryId + * @return + */ + List getModelorByCategoryId(String categoryId); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPurchaseService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPurchaseService.java new file mode 100644 index 0000000..5e512ad --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductPurchaseService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.vo.product.purchase.CreateProductPurchaseVo; +import com.lframework.xingyun.basedata.vo.product.purchase.UpdateProductPurchaseVo; + +public interface ProductPurchaseService extends BaseMpService { + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductPurchaseVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductPurchaseVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductRetailService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductRetailService.java new file mode 100644 index 0000000..39f0c1b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductRetailService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductRetail; +import com.lframework.xingyun.basedata.vo.product.retail.CreateProductRetailVo; +import com.lframework.xingyun.basedata.vo.product.retail.UpdateProductRetailVo; + +public interface ProductRetailService extends BaseMpService { + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductRetailVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductRetailVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductSaleService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductSaleService.java new file mode 100644 index 0000000..f4ee2a6 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductSaleService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.ProductSale; +import com.lframework.xingyun.basedata.vo.product.sale.CreateProductSaleVo; +import com.lframework.xingyun.basedata.vo.product.sale.UpdateProductSaleVo; + +public interface ProductSaleService extends BaseMpService { + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductSaleVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductSaleVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductService.java new file mode 100644 index 0000000..4c9d4d3 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/product/ProductService.java @@ -0,0 +1,113 @@ +package com.lframework.xingyun.basedata.service.product; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.vo.product.info.CreateProductVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductSelectorVo; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductVo; +import com.lframework.xingyun.basedata.vo.product.info.UpdateProductVo; +import java.util.Collection; +import java.util.List; + +public interface ProductService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryProductVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryProductVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, QueryProductSelectorVo vo); + + /** + * 查询商品品种数 + * + * @param vo + * @return + */ + Integer queryCount(QueryProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Product findById(String id); + + /** + * 查询没有属性的ID + * + * @param propertyId + * @return + */ + List getIdNotInProductProperty(String propertyId); + + /** + * 根据类目ID查询 + * + * @param categoryId + * @return + */ + List getIdByCategoryId(String categoryId); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateProductVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateProductVo vo); + + /** + * 根据类目ID查询 + * + * @param categoryIds + * @return + */ + List getByCategoryIds(List categoryIds, Integer productType); + + /** + * 根据品牌ID查询 + * + * @param brandIds + * @return + */ + List getByBrandIds(List brandIds, Integer productType); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/shop/ShopService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/shop/ShopService.java new file mode 100644 index 0000000..21a8c61 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/shop/ShopService.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.basedata.service.shop; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.Shop; +import com.lframework.xingyun.basedata.vo.shop.CreateShopVo; +import com.lframework.xingyun.basedata.vo.shop.QueryShopVo; +import com.lframework.xingyun.basedata.vo.shop.UpdateShopVo; +import java.util.List; + +/** + * 门店 Service + * + * @author zmj + */ +public interface ShopService extends BaseMpService { + + /** + * 查询列表 + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryShopVo vo); + + /** + * 查询列表 + * @param vo + * @return + */ + List query(QueryShopVo vo); + + /** + * 根据ID查询 + * @param id + * @return + */ + Shop findById(String id); + + /** + * 创建 + * @param vo + * @return + */ + String create(CreateShopVo vo); + + /** + * 修改 + * @param vo + */ + void update(UpdateShopVo vo); + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/storecenter/StoreCenterService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/storecenter/StoreCenterService.java new file mode 100644 index 0000000..9887430 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/storecenter/StoreCenterService.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.basedata.service.storecenter; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.vo.storecenter.CreateStoreCenterVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterSelectorVo; +import com.lframework.xingyun.basedata.vo.storecenter.QueryStoreCenterVo; +import com.lframework.xingyun.basedata.vo.storecenter.UpdateStoreCenterVo; +import java.util.Collection; + +public interface StoreCenterService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryStoreCenterVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + StoreCenter findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateStoreCenterVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateStoreCenterVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, QueryStoreCenterSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/supplier/SupplierService.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/supplier/SupplierService.java new file mode 100644 index 0000000..ea7490e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/service/supplier/SupplierService.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.basedata.service.supplier; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.vo.supplier.CreateSupplierVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierSelectorVo; +import com.lframework.xingyun.basedata.vo.supplier.QuerySupplierVo; +import com.lframework.xingyun.basedata.vo.supplier.UpdateSupplierVo; +import java.util.Collection; +import java.util.List; + +public interface SupplierService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySupplierVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySupplierVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Supplier findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSupplierVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSupplierVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, QuerySupplierSelectorVo vo); +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/AddressSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/AddressSelectorVo.java new file mode 100644 index 0000000..42be251 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/AddressSelectorVo.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.basedata.vo.address; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class AddressSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 实体ID + */ + @ApiModelProperty("实体ID") + private String entityId; + + /** + * 实体类型 + */ + @ApiModelProperty("实体类型") + @IsEnum(message = "实体类型格式错误!", enumClass = AddressEntityType.class) + private Integer entityType; + + /** + * 地址类型 + */ + @ApiModelProperty("地址类型") + @IsEnum(message = "地址类型格式错误!", enumClass = AddressType.class) + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty("手机号") + private String telephone; + + /** + * 详细地址 + */ + @ApiModelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty("是否默认地址") + private Boolean isDefault; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/CreateAddressVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/CreateAddressVo.java new file mode 100644 index 0000000..ab70aa0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/CreateAddressVo.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.basedata.vo.address; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateAddressVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 实体ID + */ + @ApiModelProperty(value = "实体ID", required = true) + @NotBlank(message = "实体ID不能为空!") + private String entityId; + + /** + * 实体类型 + */ + @ApiModelProperty(value = "实体类型", required = true) + @NotNull(message = "实体类型不能为空!") + @IsEnum(message = "实体类型格式错误!", enumClass = AddressEntityType.class) + private Integer entityType; + + /** + * 地址类型 + */ + @ApiModelProperty(value = "地址类型", required = true) + @NotNull(message = "地址类型不能为空!") + @IsEnum(message = "地址类型格式错误!", enumClass = AddressType.class) + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty(value = "姓名", required = true) + @NotBlank(message = "姓名不能为空!") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区ID", required = true) + @NotBlank(message = "地区ID不能为空!") + private String cityId; + + /** + * 详细地址 + */ + @ApiModelProperty(value = "详细地址", required = true) + @NotBlank(message = "详细地址不能为空!") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty(value = "是否默认地址", required = true) + @NotNull(message = "是否默认地址不能为空!") + private Boolean isDefault; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/QueryAddressVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/QueryAddressVo.java new file mode 100644 index 0000000..ea0558d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/QueryAddressVo.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.basedata.vo.address; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryAddressVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 实体类型 + */ + @ApiModelProperty("实体类型") + @IsEnum(message = "实体类型格式错误!", enumClass = AddressEntityType.class) + private Integer entityType; + + /** + * 地址类型 + */ + @ApiModelProperty("地址类型") + @IsEnum(message = "地址类型格式错误!", enumClass = AddressType.class) + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty("手机号") + private String telephone; + + /** + * 详细地址 + */ + @ApiModelProperty("详细地址") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty("是否默认地址") + private Boolean isDefault; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/UpdateAddressVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/UpdateAddressVo.java new file mode 100644 index 0000000..cbff811 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/address/UpdateAddressVo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.basedata.vo.address; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.AddressEntityType; +import com.lframework.xingyun.basedata.enums.AddressType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateAddressVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 实体ID + */ + @ApiModelProperty(value = "实体ID", required = true) + @NotBlank(message = "实体ID不能为空!") + private String entityId; + + /** + * 实体类型 + */ + @ApiModelProperty(value = "实体类型", required = true) + @NotNull(message = "实体类型不能为空!") + @IsEnum(message = "实体类型格式错误!", enumClass = AddressEntityType.class) + private Integer entityType; + + /** + * 地址类型 + */ + @ApiModelProperty(value = "地址类型", required = true) + @NotNull(message = "地址类型不能为空!") + @IsEnum(message = "地址类型格式错误!", enumClass = AddressType.class) + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty(value = "姓名", required = true) + @NotBlank(message = "姓名不能为空!") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty(value = "地区ID", required = true) + @NotBlank(message = "地区ID不能为空!") + private String cityId; + + /** + * 详细地址 + */ + @ApiModelProperty(value = "详细地址", required = true) + @NotBlank(message = "详细地址不能为空!") + private String address; + + /** + * 是否默认地址 + */ + @ApiModelProperty(value = "是否默认地址", required = true) + @NotNull(message = "是否默认地址不能为空!") + private Boolean isDefault; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/CreateCustomerVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/CreateCustomerVo.java new file mode 100644 index 0000000..a4646d1 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/CreateCustomerVo.java @@ -0,0 +1,127 @@ +package com.lframework.xingyun.basedata.vo.customer; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.SettleType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateCustomerVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 助记码 + */ + @ApiModelProperty(value = "助记码", required = true) + @NotBlank(message = "请输入助记码!") + private String mnemonicCode; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + @Email(message = "电子邮箱格式不正确!") + private String email; + + /** + * 邮编 + */ + @ApiModelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ApiModelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 结账方式 + */ + @ApiModelProperty(value = "结账方式", required = true) + @NotNull(message = "请选择结账方式!") + @IsEnum(message = "请选择结账方式!", enumClass = SettleType.class) + private Integer settleType; + + /** + * 统一社会信用代码 + */ + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ApiModelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ApiModelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ApiModelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ApiModelProperty("银行账号") + private String accountNo; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerSelectorVo.java new file mode 100644 index 0000000..f3cb9ff --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.customer; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryCustomerSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerVo.java new file mode 100644 index 0000000..8196419 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/QueryCustomerVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.customer; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryCustomerVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/UpdateCustomerVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/UpdateCustomerVo.java new file mode 100644 index 0000000..fe42f59 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/customer/UpdateCustomerVo.java @@ -0,0 +1,131 @@ +package com.lframework.xingyun.basedata.vo.customer; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateCustomerVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 助记码 + */ + @ApiModelProperty(value = "助记码", required = true) + @NotBlank(message = "请输入助记码!") + private String mnemonicCode; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + @Email(message = "电子邮箱格式不正确!") + private String email; + + /** + * 邮编 + */ + @ApiModelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ApiModelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 统一社会信用代码 + */ + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ApiModelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ApiModelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ApiModelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ApiModelProperty("银行账号") + private String accountNo; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/CreateLogisticsCompanyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/CreateLogisticsCompanyVo.java new file mode 100644 index 0000000..d556f3b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/CreateLogisticsCompanyVo.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.basedata.vo.logistics.company; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateLogisticsCompanyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanySelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanySelectorVo.java new file mode 100644 index 0000000..7fac9d2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanySelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.logistics.company; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryLogisticsCompanySelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanyVo.java new file mode 100644 index 0000000..866d553 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/QueryLogisticsCompanyVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.logistics.company; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryLogisticsCompanyVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/UpdateLogisticsCompanyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/UpdateLogisticsCompanyVo.java new file mode 100644 index 0000000..6009bb9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/logistics/company/UpdateLogisticsCompanyVo.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.basedata.vo.logistics.company; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateLogisticsCompanyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/CreateMemberVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/CreateMemberVo.java new file mode 100644 index 0000000..bc555fb --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/CreateMemberVo.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.basedata.vo.member; + +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDate; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateMemberVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 性别 + */ + @ApiModelProperty(value = "性别", required = true) + @NotNull(message = "请选择性别!") + @IsEnum(message = "请选择性别!", enumClass = Gender.class) + private Integer gender; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + @Email(message = "电子邮箱格式不正确!") + private String email; + + /** + * 出生日期 + */ + @ApiModelProperty("出生日期") + private LocalDate birthday; + + + /** + * 入会日期 + */ + @ApiModelProperty(value = "入会日期", required = true) + @NotNull(message = "入会日期不能为空!") + private LocalDate joinDay; + + /** + * 所属门店ID + */ + @ApiModelProperty("所属门店ID") + private String shopId; + + /** + * 所属导购ID + */ + @ApiModelProperty("所属导购ID") + private String guiderId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberSelectorVo.java new file mode 100644 index 0000000..a6a94a2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.member; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryMemberSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberVo.java new file mode 100644 index 0000000..5273d2b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/QueryMemberVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.member; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryMemberVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/UpdateMemberVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/UpdateMemberVo.java new file mode 100644 index 0000000..7556301 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/member/UpdateMemberVo.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.basedata.vo.member; + +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDate; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateMemberVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 性别 + */ + @ApiModelProperty(value = "性别", required = true) + @NotNull(message = "请选择性别!") + @IsEnum(message = "请选择性别!", enumClass = Gender.class) + private Integer gender; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + @Email(message = "电子邮箱格式不正确!") + private String email; + + /** + * 出生日期 + */ + @ApiModelProperty("出生日期") + private LocalDate birthday; + + /** + * 入会日期 + */ + @ApiModelProperty(value = "入会日期", required = true) + @NotNull(message = "入会日期不能为空!") + private LocalDate joinDay; + + /** + * 所属门店ID + */ + @ApiModelProperty("所属门店ID") + private String shopId; + + /** + * 所属导购ID + */ + @ApiModelProperty("所属导购ID") + private String guiderId; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/CreatePayTypeVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/CreatePayTypeVo.java new file mode 100644 index 0000000..b86cc17 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/CreatePayTypeVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.basedata.vo.paytype; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreatePayTypeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 是否记录内容 + */ + @ApiModelProperty(value = "是否记录内容", required = true) + @NotNull(message = "是否记录内容不能为空!") + private Boolean recText; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/PayTypeSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/PayTypeSelectorVo.java new file mode 100644 index 0000000..3eca80a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/PayTypeSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.paytype; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class PayTypeSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/QueryPayTypeVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/QueryPayTypeVo.java new file mode 100644 index 0000000..3249420 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/QueryPayTypeVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.paytype; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryPayTypeVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/UpdatePayTypeVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/UpdatePayTypeVo.java new file mode 100644 index 0000000..b652eee --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/paytype/UpdatePayTypeVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.basedata.vo.paytype; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdatePayTypeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 是否记录内容 + */ + @ApiModelProperty(value = "是否记录内容", required = true) + @NotNull(message = "是否记录内容不能为空!") + private Boolean recText; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/CreateProductBrandVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/CreateProductBrandVo.java new file mode 100644 index 0000000..6ac4b5c --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/CreateProductBrandVo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.basedata.vo.product.brand; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.UploadUrl; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductBrandVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * logo + */ + @ApiModelProperty("logo") + @UploadUrl(message = "logo文件格式有误!") + private String logo; + + /** + * 简介 + */ + @ApiModelProperty("简介") + private String introduction; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandSelectorVo.java new file mode 100644 index 0000000..df1afba --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.brand; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductBrandSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandVo.java new file mode 100644 index 0000000..cb86e1e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/QueryProductBrandVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.brand; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductBrandVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/UpdateProductBrandVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/UpdateProductBrandVo.java new file mode 100644 index 0000000..19367d5 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/brand/UpdateProductBrandVo.java @@ -0,0 +1,70 @@ +package com.lframework.xingyun.basedata.vo.product.brand; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.UploadUrl; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductBrandVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * logo + */ + @ApiModelProperty("logo") + @UploadUrl(message = "logo文件格式有误!") + private String logo; + + /** + * 简介 + */ + @ApiModelProperty("简介") + private String introduction; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/CreateProductCategoryVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/CreateProductCategoryVo.java new file mode 100644 index 0000000..27fa649 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/CreateProductCategoryVo.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.basedata.vo.product.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/QueryProductCategorySelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/QueryProductCategorySelectorVo.java new file mode 100644 index 0000000..89b1cd4 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/QueryProductCategorySelectorVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.basedata.vo.product.category; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductCategorySelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/UpdateProductCategoryVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/UpdateProductCategoryVo.java new file mode 100644 index 0000000..a00871d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/category/UpdateProductCategoryVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.basedata.vo.product.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/CreateProductVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/CreateProductVo.java new file mode 100644 index 0000000..5debcde --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/CreateProductVo.java @@ -0,0 +1,154 @@ +package com.lframework.xingyun.basedata.vo.product.info; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.ProductType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 简称 + */ + @ApiModelProperty(value = "简称") + private String shortName; + + /** + * 商品SKU编号 + */ + @ApiModelProperty(value = "商品SKU编号", required = true) + @NotBlank(message = "商品SKU编号不能为空!") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + @NotBlank(message = "类目ID不能为空!") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + @NotBlank(message = "品牌ID不能为空!") + private String brandId; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 进项税率(%) + */ + @ApiModelProperty(value = "进项税率(%)") + @Min(value = 0, message = "进项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "进项税率(%)必须为整数!") + private BigDecimal taxRate = BigDecimal.ZERO; + + /** + * 销项税率(%) + */ + @ApiModelProperty(value = "销项税率(%)") + @Min(value = 0, message = "销项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "销项税率(%)必须为整数!") + private BigDecimal saleTaxRate = BigDecimal.ZERO; + + /** + * 商品类型 + */ + @ApiModelProperty(value = "商品类型", required = true) + @NotNull(message = "商品类型不能为空!") + @IsEnum(message = "商品类型格式错误!", enumClass = ProductType.class) + private Integer productType; + + /** + * 重量(kg) + */ + @ApiModelProperty(value = "重量(kg)") + @Digits(integer = 10, fraction = 2, message = "重量最多允许2位小数!") + private BigDecimal weight; + + /** + * 体积(cm3) + */ + @ApiModelProperty(value = "体积(cm3)") + @Digits(integer = 10, fraction = 2, message = "体积最多允许2位小数!") + private BigDecimal volume; + + /** + * 单品 + */ + @ApiModelProperty(value = "单品") + @Valid + private List productBundles; + + /** + * 商品属性 + */ + @ApiModelProperty(value = "商品属性") + @Valid + private List properties; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice = BigDecimal.ZERO; + + /** + * 销售价 + */ + @ApiModelProperty("销售价") + private BigDecimal salePrice; + + /** + * 零售价 + */ + @ApiModelProperty("零售价") + private BigDecimal retailPrice; + + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductBundleVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductBundleVo.java new file mode 100644 index 0000000..5ef188d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductBundleVo.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.basedata.vo.product.info; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ProductBundleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 包含数量 + */ + @ApiModelProperty(value = "包含数量", required = true) + @NotNull(message = "包含数量不能为空!") + @Min(value = 1, message = "包含数量必须大于0!") + private Integer bundleNum; + + /** + * 销售价 + */ + @ApiModelProperty(value = "销售价", required = true) + @NotNull(message = "销售价不能为空!") + @Digits(integer = 10, fraction = 2, message = "销售价最多允许2位小数!") + @DecimalMin(value = "0.01", message = "销售价必须大于0!") + private BigDecimal salePrice; + + /** + * 零售价 + */ + @ApiModelProperty(value = "零售价", required = true) + @NotNull(message = "零售价不能为空!") + @Digits(integer = 10, fraction = 2, message = "零售价最多允许2位小数!") + @DecimalMin(value = "0.01", message = "零售价必须大于0!") + private BigDecimal retailPrice; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductPropertyRelationVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductPropertyRelationVo.java new file mode 100644 index 0000000..ccff937 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/ProductPropertyRelationVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.basedata.vo.product.info; + +import com.lframework.starter.web.vo.BaseVo; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ProductPropertyRelationVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 属性ID + */ + @NotBlank(message = "属性值ID不能为空!") + private String id; + + /** + * 属性值内容 + */ + private String text; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductSelectorVo.java new file mode 100644 index 0000000..0bb4a6c --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductSelectorVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.basedata.vo.product.info; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.basedata.enums.ProductType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryProductSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime startTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime endTime; + + /** + * 商品类型 + */ + @ApiModelProperty("商品类型") + @IsEnum(message = "商品类型格式错误!", enumClass = ProductType.class) + private Integer productType; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductVo.java new file mode 100644 index 0000000..d1be1ee --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/QueryProductVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.basedata.vo.product.info; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.basedata.enums.ProductType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryProductVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 商品类型 + */ + @ApiModelProperty("商品类型") + @IsEnum(message = "商品类型格式错误!", enumClass = ProductType.class) + private Integer productType; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime startTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime endTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/UpdateProductVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/UpdateProductVo.java new file mode 100644 index 0000000..8c6920e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/UpdateProductVo.java @@ -0,0 +1,166 @@ +package com.lframework.xingyun.basedata.vo.product.info; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.ProductType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 简称 + */ + @ApiModelProperty(value = "简称") + private String shortName; + + /** + * 商品SKU编号 + */ + @ApiModelProperty(value = "商品SKU编号", required = true) + @NotBlank(message = "商品SKU编号不能为空!") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + @NotBlank(message = "类目ID不能为空!") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + @NotBlank(message = "品牌ID不能为空!") + private String brandId; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 重量(kg) + */ + @ApiModelProperty(value = "重量(kg)") + @Digits(integer = 10, fraction = 2, message = "重量最多允许2位小数!") + private BigDecimal weight; + + /** + * 体积(cm3) + */ + @ApiModelProperty(value = "体积(cm3)") + @Digits(integer = 10, fraction = 2, message = "体积最多允许2位小数!") + private BigDecimal volume; + + /** + * 进项税率(%) + */ + @ApiModelProperty(value = "进项税率(%)") + @Min(value = 0, message = "进项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "进项税率(%)必须为整数!") + private BigDecimal taxRate = BigDecimal.ZERO; + + /** + * 销项税率(%) + */ + @ApiModelProperty(value = "销项税率(%)") + @Min(value = 0, message = "销项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "销项税率(%)必须为整数!") + private BigDecimal saleTaxRate = BigDecimal.ZERO; + + /** + * 商品类型 + */ + @ApiModelProperty(value = "商品类型", required = true) + @NotNull(message = "商品类型不能为空!") + @IsEnum(message = "商品类型格式错误!", enumClass = ProductType.class) + private Integer productType; + + /** + * 单品 + */ + @ApiModelProperty(value = "单品") + @Valid + private List productBundles; + + /** + * 商品属性 + */ + @ApiModelProperty(value = "商品属性") + @Valid + private List properties; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice = BigDecimal.ZERO; + + /** + * 销售价 + */ + @ApiModelProperty("销售价") + private BigDecimal salePrice; + + /** + * 零售价 + */ + @ApiModelProperty("零售价") + private BigDecimal retailPrice; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态",required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/saleprop/CreateProductSalePropItemRelationVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/saleprop/CreateProductSalePropItemRelationVo.java new file mode 100644 index 0000000..3b4693a --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/info/saleprop/CreateProductSalePropItemRelationVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.basedata.vo.product.info.saleprop; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateProductSalePropItemRelationVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 销售属性值ID + */ + @ApiModelProperty(value = "销售属性值ID", required = true) + @NotEmpty(message = "销售属性值ID不能为空!") + private List salePropItemIds; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/CreateProductPolyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/CreateProductPolyVo.java new file mode 100644 index 0000000..966f15f --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/CreateProductPolyVo.java @@ -0,0 +1,220 @@ +package com.lframework.xingyun.basedata.vo.product.poly; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateProductPolyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品货号 + */ + @ApiModelProperty(value = "商品货号", required = true) + @IsCode + @NotBlank(message = "商品货号不能为空!") + private String code; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称", required = true) + @NotBlank(message = "商品名称不能为空!") + private String name; + + /** + * 商品简称 + */ + @ApiModelProperty("商品简称") + private String shortName; + + /** + * 类目ID + */ + @ApiModelProperty(value = "类目ID", required = true) + @NotBlank(message = "请选择商品类目!") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty(value = "品牌ID", required = true) + @NotBlank(message = "请选择商品品牌!") + private String brandId; + + /** + * 是否多销售属性 + */ + @ApiModelProperty(value = "是否多销售属性", required = true) + @NotNull(message = "请选择是否多销售属性!") + private Boolean multipleSaleProp; + + /** + * 进项税率(%) + */ + @ApiModelProperty(value = "进项税率(%)", required = true) + @NotNull(message = "进项税率(%)不能为空!") + @Min(value = 0, message = "进项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "进项税率(%)必须为整数!") + private BigDecimal taxRate; + + /** + * 销项税率(%) + */ + @ApiModelProperty(value = "销项税率(%)", required = true) + @NotNull(message = "销项税率(%)不能为空!") + @Min(value = 0, message = "销项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "销项税率(%)必须为整数!") + private BigDecimal saleTaxRate; + + /** + * 商品属性 + */ + @ApiModelProperty(value = "商品属性", required = true) + @Valid + private List properties; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty + private List products; + + public void validate() { + + int orderNo = 1; + for (ProductVo product : this.getProducts()) { + if (this.getMultipleSaleProp()) { + if (StringUtil.isBlank(product.getSalePropItemId1())) { + throw new InputErrorException("销售属性1不能为空!"); + } + } + + if (StringUtil.isBlank(product.getCode())) { + throw new InputErrorException("第" + (orderNo) + "行商品编号不能为空!"); + } + + if (!RegUtil.isMatch(PatternPool.PATTERN_CODE, product.getCode())) { + throw new InputErrorException("第" + (orderNo) + "行商品编号必须由字母或数字组成,长度不能超过20位!"); + } + + if (StringUtil.isBlank(product.getName())) { + throw new InputErrorException("第" + (orderNo) + "行商品名称不能为空!"); + } + + if (StringUtil.isBlank(product.getSkuCode())) { + throw new InputErrorException("第" + (orderNo) + "行商品SKU编号不能为空!"); + } + + if (product.getPurchasePrice() == null) { + throw new InputErrorException("第" + (orderNo) + "行商品采购价不能为空!"); + } + + if (product.getSalePrice() == null) { + throw new InputErrorException("第" + (orderNo) + "行商品销售价不能为空!"); + } + + if (product.getRetailPrice() == null) { + throw new InputErrorException("第" + (orderNo) + "行商品零售价不能为空!"); + } + + orderNo++; + } + } + + @Data + public static class PropertyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 属性ID + */ + @NotBlank(message = "属性值ID不能为空!") + private String id; + + /** + * 属性值内容 + */ + private String text; + } + + @Data + public static class ProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 销售属性1ID multipleSaleProp == true时生效 + */ + private String salePropItemId1; + + /** + * 销售属性2ID multipleSaleProp == true时生效 + */ + private String salePropItemId2; + + /** + * 商品编号 + */ + private String code; + + /** + * 商品名称 + */ + private String name; + + /** + * 商品SKU编号 + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 采购价 + */ + private BigDecimal purchasePrice; + + /** + * 销售价 + */ + private BigDecimal salePrice; + + /** + * 零售价 + */ + private BigDecimal retailPrice; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/QueryProductPolyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/QueryProductPolyVo.java new file mode 100644 index 0000000..8a7db85 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/QueryProductPolyVo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.basedata.vo.product.poly; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductPolyVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/UpdateProductPolyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/UpdateProductPolyVo.java new file mode 100644 index 0000000..7086272 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/UpdateProductPolyVo.java @@ -0,0 +1,104 @@ +package com.lframework.xingyun.basedata.vo.product.poly; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductPolyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 商品货号 + */ + @ApiModelProperty(value = "商品货号", required = true) + @IsCode + @NotBlank(message = "商品货号不能为空!") + private String code; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称", required = true) + @NotBlank(message = "商品名称不能为空!") + private String name; + + /** + * 商品简称 + */ + @ApiModelProperty("商品简称") + private String shortName; + + /** + * 类目ID + */ + @ApiModelProperty(value = "类目ID", required = true) + @NotBlank(message = "请选择商品类目!") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty(value = "品牌ID", required = true) + @NotBlank(message = "请选择商品品牌!") + private String brandId; + + /** + * 进项税率(%) + */ + @ApiModelProperty(value = "进项税率(%)", required = true) + @NotNull(message = "进项税率(%)不能为空!") + @Min(value = 0, message = "进项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "进项税率(%)必须为整数!") + private BigDecimal taxRate; + + /** + * 销项税率(%) + */ + @ApiModelProperty(value = "销项税率(%)", required = true) + @NotNull(message = "销项税率(%)不能为空!") + @Min(value = 0, message = "销项税率(%)不允许小于0!") + @Digits(integer = 10, fraction = 0, message = "销项税率(%)必须为整数!") + private BigDecimal saleTaxRate; + + /** + * 商品属性 + */ + @ApiModelProperty(value = "商品属性", required = true) + @Valid + private List properties; + + @Data + public static class PropertyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 属性ID + */ + @NotBlank(message = "属性值ID不能为空!") + private String id; + + /** + * 属性值内容 + */ + private String text; + } +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/property/CreateProductPolyPropertyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/property/CreateProductPolyPropertyVo.java new file mode 100644 index 0000000..1290547 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/property/CreateProductPolyPropertyVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.basedata.vo.product.poly.property; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductPolyPropertyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * polyID + */ + @ApiModelProperty(value = "polyID", required = true) + @NotBlank(message = "polyId不能为空!") + private String polyId; + + /** + * 属性ID + */ + @ApiModelProperty(value = "属性ID", required = true) + @NotBlank(message = "属性ID不能为空!") + private String propertyId; + + /** + * 属性值ID + */ + @ApiModelProperty("属性值ID") + private String propertyItemId; + + /** + * 属性值文本 + */ + @ApiModelProperty("属性值文本") + private String propertyText; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/saleprop/CreateProductPolySalePropGroupVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/saleprop/CreateProductPolySalePropGroupVo.java new file mode 100644 index 0000000..58bdfe2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/poly/saleprop/CreateProductPolySalePropGroupVo.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.basedata.vo.product.poly.saleprop; + +import com.lframework.starter.web.vo.BaseVo; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class CreateProductPolySalePropGroupVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品聚合ID + */ + private String polyId; + + /** + * 销售属性组ID + */ + private List salePropGroupIds; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/CreateProductPropertyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/CreateProductPropertyVo.java new file mode 100644 index 0000000..7659188 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/CreateProductPropertyVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.basedata.vo.product.property; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.ColumnDataType; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.PropertyType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateProductPropertyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 是否必填 + */ + @ApiModelProperty(value = "是否必填", required = true) + @NotNull(message = "请选择是否必填!") + private Boolean isRequired; + + /** + * 录入类型 + */ + @ApiModelProperty(value = "录入类型", required = true) + @NotNull(message = "请选择录入类型!") + @IsEnum(enumClass = ColumnType.class, message = "请选择录入类型!") + private Integer columnType; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + @IsEnum(enumClass = ColumnDataType.class, message = "请选择数据类型!") + private Integer columnDataType; + + /** + * 属性类别 + */ + @ApiModelProperty(value = "属性类别", required = true) + @NotNull(message = "请选择属性类别!") + @IsEnum(enumClass = PropertyType.class, message = "请选择属性类别!") + private Integer propertyType; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private List categoryIds; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/QueryProductPropertyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/QueryProductPropertyVo.java new file mode 100644 index 0000000..a76ee15 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/QueryProductPropertyVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.property; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductPropertyVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/UpdateProductPropertyVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/UpdateProductPropertyVo.java new file mode 100644 index 0000000..98fa4f9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/UpdateProductPropertyVo.java @@ -0,0 +1,91 @@ +package com.lframework.xingyun.basedata.vo.product.property; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.ColumnDataType; +import com.lframework.xingyun.basedata.enums.ColumnType; +import com.lframework.xingyun.basedata.enums.PropertyType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductPropertyVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = false) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 是否必填 + */ + @ApiModelProperty(value = "是否必填", required = true) + @NotNull(message = "请选择是否必填!") + private Boolean isRequired; + + /** + * 录入类型 + */ + @ApiModelProperty(value = "录入类型", required = true) + @NotNull(message = "请选择录入类型!") + @IsEnum(enumClass = ColumnType.class, message = "请选择录入类型!") + private Integer columnType; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + @IsEnum(enumClass = ColumnDataType.class, message = "请选择数据类型!") + private Integer columnDataType; + + /** + * 属性类别 + */ + @ApiModelProperty(value = "属性类别", required = true) + @NotNull(message = "请选择属性类别!") + @IsEnum(enumClass = PropertyType.class, message = "请选择属性类别!") + private Integer propertyType; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private List categoryIds; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/CreateProductPropertyItemVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/CreateProductPropertyItemVo.java new file mode 100644 index 0000000..1371df6 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/CreateProductPropertyItemVo.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.basedata.vo.product.property.item; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductPropertyItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 属性ID + */ + @ApiModelProperty(value = "属性ID", required = true) + @NotBlank(message = "属性ID不能为空!") + private String propertyId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/QueryProductPropertyItemVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/QueryProductPropertyItemVo.java new file mode 100644 index 0000000..d425625 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/QueryProductPropertyItemVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.basedata.vo.product.property.item; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryProductPropertyItemVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 属性ID + */ + @ApiModelProperty(value = "属性ID", required = true) + @NotBlank(message = "属性ID不能为空!") + private String propertyId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/UpdateProductPropertyItemVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/UpdateProductPropertyItemVo.java new file mode 100644 index 0000000..ee5da9d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/item/UpdateProductPropertyItemVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.basedata.vo.product.property.item; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductPropertyItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/realtion/CreateProductPropertyRelationVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/realtion/CreateProductPropertyRelationVo.java new file mode 100644 index 0000000..f045571 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/property/realtion/CreateProductPropertyRelationVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.basedata.vo.product.property.realtion; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductPropertyRelationVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 属性ID + */ + @ApiModelProperty(value = "属性ID", required = true) + @NotBlank(message = "属性ID不能为空!") + private String propertyId; + + /** + * 属性值ID + */ + @ApiModelProperty("属性值ID") + private String propertyItemId; + + /** + * 属性值文本 + */ + @ApiModelProperty("属性值文本") + private String propertyText; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/CreateProductPurchaseVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/CreateProductPurchaseVo.java new file mode 100644 index 0000000..62c1d71 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/CreateProductPurchaseVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import lombok.Data; + +@Data +public class CreateProductPurchaseVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String id; + + /** + * 采购价 + */ + @ApiModelProperty(value = "采购价", required = true) + @NotNull(message = "请输入采购价!") + @Positive(message = "采购价必须大于0!") + @Digits(integer = 20, fraction = 2, message = "采购价最多允许2位小数!") + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/UpdateProductPurchaseVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/UpdateProductPurchaseVo.java new file mode 100644 index 0000000..a0e8ed0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/purchase/UpdateProductPurchaseVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.basedata.vo.product.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import lombok.Data; + +@Data +public class UpdateProductPurchaseVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String id; + + /** + * 采购价 + */ + @ApiModelProperty(value = "采购价", required = true) + @NotNull(message = "请输入采购价!") + @Positive(message = "采购价必须大于0!") + @Digits(integer = 20, fraction = 2, message = "采购价最多允许2位小数!") + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/CreateProductRetailVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/CreateProductRetailVo.java new file mode 100644 index 0000000..f1431a2 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/CreateProductRetailVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.retail; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import lombok.Data; + +@Data +public class CreateProductRetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String id; + + /** + * 零售价 + */ + @ApiModelProperty(value = "零售价", required = true) + @NotNull(message = "请输入零售价!") + @Positive(message = "零售价必须大于0!") + @Digits(integer = 20, fraction = 2, message = "零售价最多允许2位小数!") + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/UpdateProductRetailVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/UpdateProductRetailVo.java new file mode 100644 index 0000000..1cf1e39 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/retail/UpdateProductRetailVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.basedata.vo.product.retail; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import lombok.Data; + +@Data +public class UpdateProductRetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String id; + + /** + * 零售价 + */ + @ApiModelProperty(value = "零售价", required = true) + @NotNull(message = "请输入零售价!") + @Positive(message = "零售价必须大于0!") + @Digits(integer = 20, fraction = 2, message = "零售价最多允许2位小数!") + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/CreateProductSaleVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/CreateProductSaleVo.java new file mode 100644 index 0000000..a3c1c78 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/CreateProductSaleVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import lombok.Data; + +@Data +public class CreateProductSaleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String id; + + /** + * 销售价 + */ + @ApiModelProperty(value = "销售价", required = true) + @NotNull(message = "请输入销售价!") + @Positive(message = "销售价必须大于0!") + @Digits(integer = 20, fraction = 2, message = "销售价最多允许2位小数!") + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/UpdateProductSaleVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/UpdateProductSaleVo.java new file mode 100644 index 0000000..0220a93 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/sale/UpdateProductSaleVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.basedata.vo.product.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import lombok.Data; + +@Data +public class UpdateProductSaleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String id; + + /** + * 销售价 + */ + @ApiModelProperty(value = "销售价", required = true) + @NotNull(message = "请输入销售价!") + @Positive(message = "销售价必须大于0!") + @Digits(integer = 20, fraction = 2, message = "销售价最多允许2位小数!") + private BigDecimal price; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/CreateProductSalePropGroupVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/CreateProductSalePropGroupVo.java new file mode 100644 index 0000000..54fb158 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/CreateProductSalePropGroupVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductSalePropGroupVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupSelectorVo.java new file mode 100644 index 0000000..569086e --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupSelectorVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductSalePropGroupSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 是否过滤空的销售属性组 + */ + @ApiModelProperty("是否过滤空的销售属性组") + private Boolean filterEmpty; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupVo.java new file mode 100644 index 0000000..9a14f15 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/QueryProductSalePropGroupVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductSalePropGroupVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/UpdateProductSalePropGroupVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/UpdateProductSalePropGroupVo.java new file mode 100644 index 0000000..2f95d05 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/UpdateProductSalePropGroupVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductSalePropGroupVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/CreateProductSalePropItemVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/CreateProductSalePropItemVo.java new file mode 100644 index 0000000..9e05474 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/CreateProductSalePropItemVo.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop.item; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateProductSalePropItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 销售属性组ID + */ + @ApiModelProperty(value = "销售属性组ID", required = true) + @NotBlank(message = "GroupID不能为空!") + private String groupId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemSelectorVo.java new file mode 100644 index 0000000..123869f --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemSelectorVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop.item; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryProductSalePropItemSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 销售属性组ID + */ + @ApiModelProperty("销售属性组ID") + private String salePropGroupId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemVo.java new file mode 100644 index 0000000..6975946 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/QueryProductSalePropItemVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop.item; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryProductSalePropItemVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 销售属性组ID + */ + @ApiModelProperty(value = "销售属性组ID", required = true) + @NotBlank(message = "GroupID不能为空!") + private String groupId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/UpdateProductSalePropItemVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/UpdateProductSalePropItemVo.java new file mode 100644 index 0000000..7e4ba76 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/product/saleprop/item/UpdateProductSalePropItemVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.basedata.vo.product.saleprop.item; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateProductSalePropItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/CreateShopVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/CreateShopVo.java new file mode 100644 index 0000000..e97b575 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/CreateShopVo.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.basedata.vo.shop; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateShopVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 所属部门ID + */ + @ApiModelProperty("所属部门ID") + private String deptId; + + /** + * 经度 + */ + @ApiModelProperty("经度") + @TypeMismatch(message = "经度格式有误!") + private BigDecimal lng; + + /** + * 纬度 + */ + @ApiModelProperty("纬度") + @TypeMismatch(message = "纬度格式有误!") + private BigDecimal lat; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/QueryShopVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/QueryShopVo.java new file mode 100644 index 0000000..fd83b64 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/QueryShopVo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.basedata.vo.shop; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryShopVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 所属部门ID + */ + @ApiModelProperty("所属部门ID") + private String deptId; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + private Boolean available; + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/ShopSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/ShopSelectorVo.java new file mode 100644 index 0000000..15e3f3b --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/ShopSelectorVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.basedata.vo.shop; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class ShopSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/UpdateShopVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/UpdateShopVo.java new file mode 100644 index 0000000..063b376 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/shop/UpdateShopVo.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.basedata.vo.shop; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateShopVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 所属部门ID + */ + @ApiModelProperty("所属部门ID") + private String deptId; + + /** + * 经度 + */ + @ApiModelProperty("经度") + @TypeMismatch(message = "经度格式有误!") + private BigDecimal lng; + + /** + * 纬度 + */ + @ApiModelProperty("纬度") + @TypeMismatch(message = "纬度格式有误!") + private BigDecimal lat; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @TypeMismatch(message = "状态格式有误!") + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/CreateStoreCenterVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/CreateStoreCenterVo.java new file mode 100644 index 0000000..53c7d7d --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/CreateStoreCenterVo.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.basedata.vo.storecenter; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateStoreCenterVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系人手机号码 + */ + @ApiModelProperty("联系人手机号码") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 仓库人数 + */ + @ApiModelProperty("仓库人数") + private Integer peopleNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterSelectorVo.java new file mode 100644 index 0000000..16021c0 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.basedata.vo.storecenter; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryStoreCenterSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterVo.java new file mode 100644 index 0000000..c25cb99 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/QueryStoreCenterVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.vo.storecenter; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryStoreCenterVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/UpdateStoreCenterVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/UpdateStoreCenterVo.java new file mode 100644 index 0000000..536e326 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/storecenter/UpdateStoreCenterVo.java @@ -0,0 +1,80 @@ +package com.lframework.xingyun.basedata.vo.storecenter; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateStoreCenterVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系人手机号码 + */ + @ApiModelProperty("联系人手机号码") + private String telephone; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 仓库人数 + */ + @ApiModelProperty("仓库人数") + private Integer peopleNum; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/CreateSupplierVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/CreateSupplierVo.java new file mode 100644 index 0000000..86874d9 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/CreateSupplierVo.java @@ -0,0 +1,144 @@ +package com.lframework.xingyun.basedata.vo.supplier; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.enums.SettleType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Email; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSupplierVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 助记码 + */ + @ApiModelProperty(value = "助记码", required = true) + @NotBlank(message = "请输入助记码!") + private String mnemonicCode; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + @Email(message = "电子邮箱格式不正确!") + private String email; + + /** + * 邮编 + */ + @ApiModelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ApiModelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 送货周期(天) + */ + @ApiModelProperty("送货周期(天)") + @Min(message = "送货周期(天)必须大于0!", value = 1) + private Integer deliveryCycle; + + /** + * 经营方式 + */ + @ApiModelProperty(value = "经营方式", required = true) + @NotNull(message = "请选择经营方式!") + @IsEnum(message = "请选择经营方式!", enumClass = ManageType.class) + private Integer manageType; + + /** + * 结账方式 + */ + @ApiModelProperty(value = "结账方式", required = true) + @NotNull(message = "请选择结账方式!") + @IsEnum(message = "请选择结账方式!", enumClass = SettleType.class) + private Integer settleType; + + /** + * 统一社会信用代码 + */ + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ApiModelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ApiModelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ApiModelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ApiModelProperty("银行账号") + private String accountNo; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierSelectorVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierSelectorVo.java new file mode 100644 index 0000000..fcdc685 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierSelectorVo.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.basedata.vo.supplier; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.basedata.enums.ManageType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySupplierSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 经营方式 + */ + @ApiModelProperty("经营方式") + @IsEnum(message = "经营方式格式不正确!", enumClass = ManageType.class) + private Integer manageType; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierVo.java new file mode 100644 index 0000000..834d487 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/QuerySupplierVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.basedata.vo.supplier; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySupplierVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/UpdateSupplierVo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/UpdateSupplierVo.java new file mode 100644 index 0000000..f5f2b4f --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/vo/supplier/UpdateSupplierVo.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.basedata.vo.supplier; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Email; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSupplierVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 助记码 + */ + @ApiModelProperty(value = "助记码", required = true) + @NotBlank(message = "请输入助记码!") + private String mnemonicCode; + + /** + * 联系人 + */ + @ApiModelProperty("联系人") + private String contact; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 电子邮箱 + */ + @ApiModelProperty("电子邮箱") + @Email(message = "电子邮箱格式不正确!") + private String email; + + /** + * 邮编 + */ + @ApiModelProperty("邮编") + private String zipCode; + + /** + * 传真 + */ + @ApiModelProperty("传真") + private String fax; + + /** + * 地区ID + */ + @ApiModelProperty("地区ID") + private String cityId; + + /** + * 地址 + */ + @ApiModelProperty("地址") + private String address; + + /** + * 送货周期(天) + */ + @ApiModelProperty("送货周期(天)") + @Min(message = "送货周期(天)必须大于0!", value = 1) + private Integer deliveryCycle; + + /** + * 统一社会信用代码 + */ + @ApiModelProperty("统一社会信用代码") + private String creditCode; + + /** + * 纳税人识别号 + */ + @ApiModelProperty("纳税人识别号") + private String taxIdentifyNo; + + /** + * 开户银行 + */ + @ApiModelProperty("开户银行") + private String bankName; + + /** + * 户名 + */ + @ApiModelProperty("户名") + private String accountName; + + /** + * 银行账号 + */ + @ApiModelProperty("银行账号") + private String accountNo; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-basedata/src/main/java/lombok.config b/xingyun-basedata/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-basedata/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-basedata/src/main/resources/mappers/address/AddressMapper.xml b/xingyun-basedata/src/main/resources/mappers/address/AddressMapper.xml new file mode 100644 index 0000000..362e913 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/address/AddressMapper.xml @@ -0,0 +1,65 @@ + + + + + + SELECT + tb.* + FROM base_data_address AS tb + + + + \ No newline at end of file diff --git a/xingyun-basedata/src/main/resources/mappers/customer/CustomerMapper.xml b/xingyun-basedata/src/main/resources/mappers/customer/CustomerMapper.xml new file mode 100644 index 0000000..eaaf558 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/customer/CustomerMapper.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + mnemonic_code, + contact, + telephone, + email, + zip_code, + fax, + city_id, + address, + settle_type, + credit_code, + tax_identify_no, + bank_name, + account_name, + account_no, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM base_data_customer + + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/logistics/LogisticsCompanyMapper.xml b/xingyun-basedata/src/main/resources/mappers/logistics/LogisticsCompanyMapper.xml new file mode 100644 index 0000000..2f2bb02 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/logistics/LogisticsCompanyMapper.xml @@ -0,0 +1,46 @@ + + + + + + SELECT + * + FROM base_data_logistics_company + + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/member/MemberMapper.xml b/xingyun-basedata/src/main/resources/mappers/member/MemberMapper.xml new file mode 100644 index 0000000..a5d03c8 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/member/MemberMapper.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + gender, + telephone, + email, + birthday, + join_day, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM base_data_member + + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/paytype/PayTypeMapper.xml b/xingyun-basedata/src/main/resources/mappers/paytype/PayTypeMapper.xml new file mode 100644 index 0000000..45fe710 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/paytype/PayTypeMapper.xml @@ -0,0 +1,44 @@ + + + + + + SELECT + tb.* + FROM base_data_pay_type AS tb + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductBrandMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductBrandMapper.xml new file mode 100644 index 0000000..a285eca --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductBrandMapper.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + short_name, + logo, + introduction, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM base_data_product_brand + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductCategoryMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductCategoryMapper.xml new file mode 100644 index 0000000..2965796 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductCategoryMapper.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + SELECT + id, + code, + name, + parent_id, + available, + description + FROM base_data_product_category + + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductCategoryPropertyMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductCategoryPropertyMapper.xml new file mode 100644 index 0000000..8aba70f --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductCategoryPropertyMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + SELECT + cp.id, + cp.property_id, + cp.category_id + FROM base_data_product_category_property AS cp + LEFT JOIN base_data_product_property AS p ON p.id = cp.property_id + LEFT JOIN base_data_product_category AS c ON c.id = cp.category_id + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductMapper.xml new file mode 100644 index 0000000..6a225f5 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductMapper.xml @@ -0,0 +1,166 @@ + + + + + + SELECT + g.* + FROM base_data_product AS g + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = g.category_id and rm.node_type = 2 + + + + + + + + + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyItemMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyItemMapper.xml new file mode 100644 index 0000000..58ff2a3 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyItemMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + property_id, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM base_data_product_property_item + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyMapper.xml new file mode 100644 index 0000000..9dcb8d2 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + p.id, + p.code, + p.name, + p.is_required, + p.column_type, + p.column_data_type, + p.property_type, + p.available, + p.description, + p.create_by, + p.create_time, + p.update_by, + p.update_time + FROM base_data_product_property AS p + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyRelationMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyRelationMapper.xml new file mode 100644 index 0000000..e1a8e0b --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductPropertyRelationMapper.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + SELECT + pp.id, + pp.product_id, + p.id AS property_id, + t.id AS property_item_id, + p.column_type AS property_column_type, + p.name AS property_name, + IF(p.column_type = 3, pp.property_text, t.name) AS property_text + FROM base_data_product_property_relation AS pp + INNER JOIN base_data_product_property AS p ON p.id = pp.property_id + LEFT JOIN base_data_product_property_item AS t ON t.id = pp.property_item_id + + + DELETE FROM base_data_product_property_relation WHERE property_id = #{propertyId} AND product_id NOT IN (SELECT id from base_data_product WHERE category_id = #{categoryId}) + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductPurchaseMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductPurchaseMapper.xml new file mode 100644 index 0000000..6255097 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductPurchaseMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductRetailMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductRetailMapper.xml new file mode 100644 index 0000000..fb42450 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductRetailMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/product/ProductSaleMapper.xml b/xingyun-basedata/src/main/resources/mappers/product/ProductSaleMapper.xml new file mode 100644 index 0000000..cea9f93 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/product/ProductSaleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/shop/ShopMapper.xml b/xingyun-basedata/src/main/resources/mappers/shop/ShopMapper.xml new file mode 100644 index 0000000..69592e7 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/shop/ShopMapper.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.dept_id, + tb.lng, + tb.lat, + tb.description, + tb.available, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM tbl_shop AS tb + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/storecenter/StoreCenterMapper.xml b/xingyun-basedata/src/main/resources/mappers/storecenter/StoreCenterMapper.xml new file mode 100644 index 0000000..ebcebdf --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/storecenter/StoreCenterMapper.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + contact, + telephone, + people_num, + city_id, + address, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM base_data_store_center + + + + + + diff --git a/xingyun-basedata/src/main/resources/mappers/supplier/SupplierMapper.xml b/xingyun-basedata/src/main/resources/mappers/supplier/SupplierMapper.xml new file mode 100644 index 0000000..8d9bac9 --- /dev/null +++ b/xingyun-basedata/src/main/resources/mappers/supplier/SupplierMapper.xml @@ -0,0 +1,49 @@ + + + + + + SELECT + * + FROM base_data_supplier + + + + + + diff --git a/xingyun-chart/pom.xml b/xingyun-chart/pom.xml new file mode 100644 index 0000000..d7095ba --- /dev/null +++ b/xingyun-chart/pom.xml @@ -0,0 +1,22 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-chart + 【${project.artifactId}】图表服务层 + + + + com.lframework + xingyun-core + + + + diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthBo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthBo.java new file mode 100644 index 0000000..e0839a3 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.chart.bo; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.chart.dto.OrderChartSameMonthDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class OrderChartSameMonthBo extends BaseBo { + + /** + * 单据总金额 + */ + @ApiModelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 单据总数量 + */ + @ApiModelProperty("单据总数量") + private Integer totalNum; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createDate; + + public OrderChartSameMonthBo() { + + } + + public OrderChartSameMonthBo(OrderChartSameMonthDto dto) { + + super(dto); + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthSumBo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthSumBo.java new file mode 100644 index 0000000..7b632c1 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartSameMonthSumBo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.chart.bo; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.chart.dto.OrderChartSumDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +@Data +public class OrderChartSameMonthSumBo extends BaseBo { + + /** + * 单据总金额 + */ + @ApiModelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 单据数量 + */ + @ApiModelProperty("单据数量") + private Long totalNum; + + /** + * 图表数据 + */ + @ApiModelProperty("图表数据") + private List charts; + + public OrderChartSameMonthSumBo() { + + } + + public OrderChartSameMonthSumBo(OrderChartSumDto dto) { + + super(dto); + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodayBo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodayBo.java new file mode 100644 index 0000000..d35d0f6 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodayBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.chart.bo; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.chart.dto.OrderChartTodayDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class OrderChartTodayBo extends BaseBo { + + /** + * 单据总金额 + */ + @ApiModelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 单据总数量 + */ + @ApiModelProperty("单据总数量") + private Integer totalNum; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createHour; + + public OrderChartTodayBo() { + + } + + public OrderChartTodayBo(OrderChartTodayDto dto) { + + super(dto); + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodaySumBo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodaySumBo.java new file mode 100644 index 0000000..4b80265 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/bo/OrderChartTodaySumBo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.chart.bo; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.chart.dto.OrderChartSumDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +@Data +public class OrderChartTodaySumBo extends BaseBo { + + /** + * 单据总金额 + */ + @ApiModelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 单据数量 + */ + @ApiModelProperty("单据数量") + private Long totalNum; + + /** + * 图表数据 + */ + @ApiModelProperty("图表数据") + private List charts; + + public OrderChartTodaySumBo() { + + } + + public OrderChartTodaySumBo(OrderChartSumDto dto) { + + super(dto); + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/controller/ChartController.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/controller/ChartController.java new file mode 100644 index 0000000..29d5e27 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/controller/ChartController.java @@ -0,0 +1,114 @@ +package com.lframework.xingyun.chart.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.chart.bo.OrderChartSameMonthBo; +import com.lframework.xingyun.chart.bo.OrderChartSameMonthSumBo; +import com.lframework.xingyun.chart.bo.OrderChartTodayBo; +import com.lframework.xingyun.chart.bo.OrderChartTodaySumBo; +import com.lframework.xingyun.chart.dto.OrderChartSameMonthDto; +import com.lframework.xingyun.chart.dto.OrderChartTodayDto; +import com.lframework.xingyun.chart.enums.OrderChartBizType; +import com.lframework.xingyun.chart.service.OrderChartService; +import com.lframework.xingyun.chart.vo.GetOrderChartVo; +import com.lframework.xingyun.chart.vo.QueryOrderChartVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 报表 + * + * @author zmj + */ +@Api(tags = "报表") +@Validated +@RestController +@RequestMapping("/chart") +public class ChartController extends DefaultBaseController { + + @Autowired + private OrderChartService orderChartService; + + /** + * 订单报表 + */ + @ApiOperation("订单报表") + @GetMapping("/order") + public InvokeResult>> orderChart() { + + //当日数据 + Map todayMap = new HashMap<>(2, 1); + //当月数据 + Map sameMonthMap = new HashMap<>(2, 1); + + List orderBizTypes = CollectionUtil.toList(OrderChartBizType.PURCHASE_ORDER.getCode(), + OrderChartBizType.SALE_ORDER.getCode(), OrderChartBizType.RETAIL_OUT_SHEET.getCode()); + todayMap.put("order", getTodayChart(orderBizTypes)); + sameMonthMap.put("order", getSameMonthChart(orderBizTypes)); + + List returnBizTypes = CollectionUtil.toList( + OrderChartBizType.PURCHASE_RETURN.getCode(), + OrderChartBizType.SALE_RETURN.getCode(), OrderChartBizType.RETAIL_RETURN.getCode()); + todayMap.put("returned", getTodayChart(returnBizTypes)); + sameMonthMap.put("returned", getSameMonthChart(returnBizTypes)); + + Map> result = new HashMap<>(2, 1); + result.put("today", todayMap); + result.put("sameMonth", sameMonthMap); + + return InvokeResultBuilder.success(result); + } + + private OrderChartTodaySumBo getTodayChart(List bizTypes) { + + GetOrderChartVo orderSumVo = new GetOrderChartVo(); + orderSumVo.setBizTypes(bizTypes); + // 今日订单汇总数据 + OrderChartTodaySumBo orderSumBo = new OrderChartTodaySumBo( + orderChartService.getTodayChartSum(orderSumVo)); + // 今日订单图表数据 + QueryOrderChartVo chartVo = new QueryOrderChartVo(); + chartVo.setBizTypes(bizTypes); + List charts = orderChartService.queryTodayChart(chartVo); + List chartResults = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(charts)) { + chartResults = charts.stream().map(OrderChartTodayBo::new).collect(Collectors.toList()); + } + orderSumBo.setCharts(chartResults); + + return orderSumBo; + } + + private OrderChartSameMonthSumBo getSameMonthChart(List bizTypes) { + + GetOrderChartVo orderSumVo = new GetOrderChartVo(); + orderSumVo.setBizTypes(bizTypes); + // 当月订单汇总数据 + OrderChartSameMonthSumBo sameMonthOrderSumBo = new OrderChartSameMonthSumBo( + orderChartService.getSameMonthChartSum(orderSumVo)); + // 当月订单图表数据 + QueryOrderChartVo chartVo = new QueryOrderChartVo(); + chartVo.setBizTypes(bizTypes); + List sameMonthCharts = orderChartService.querySameMonthChart(chartVo); + List sameMonthChartResults = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(sameMonthCharts)) { + sameMonthChartResults = sameMonthCharts.stream().map(OrderChartSameMonthBo::new) + .collect(Collectors.toList()); + } + sameMonthOrderSumBo.setCharts(sameMonthChartResults); + + return sameMonthOrderSumBo; + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSameMonthDto.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSameMonthDto.java new file mode 100644 index 0000000..7c9f029 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSameMonthDto.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.chart.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class OrderChartSameMonthDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据总金额 + */ + private BigDecimal totalAmount; + + /** + * 单据总数量 + */ + private Integer totalNum; + + /** + * 创建时间 + */ + private String createDate; +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSumDto.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSumDto.java new file mode 100644 index 0000000..e4a30e0 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartSumDto.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.chart.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class OrderChartSumDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "OrderChartSumDto"; + + private static final long serialVersionUID = 1L; + + /** + * 单据总金额 + */ + private BigDecimal totalAmount; + + /** + * 单据数量 + */ + private Long totalNum; +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartTodayDto.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartTodayDto.java new file mode 100644 index 0000000..b250f6c --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/dto/OrderChartTodayDto.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.chart.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class OrderChartTodayDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据总金额 + */ + private BigDecimal totalAmount; + + /** + * 单据总数量 + */ + private Integer totalNum; + + /** + * 创建时间 + */ + private String createHour; +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/entity/OrderChart.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/entity/OrderChart.java new file mode 100644 index 0000000..545c65d --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/entity/OrderChart.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.chart.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.chart.enums.OrderChartBizType; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-19 + */ +@Data +@TableName("tbl_order_chart") +public class OrderChart extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单据总金额 + */ + private BigDecimal totalAmount; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 创建日期 + */ + private String createDate; + + /** + * 创建时间(小时) + */ + private String createHour; + + /** + * 业务类型 + */ + private OrderChartBizType bizType; +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/enums/OrderChartBizType.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/enums/OrderChartBizType.java new file mode 100644 index 0000000..46abe19 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/enums/OrderChartBizType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.chart.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum OrderChartBizType implements BaseEnum { + PURCHASE_ORDER(0, "采购订单"), PURCHASE_RETURN(1, "采购退单"), SALE_ORDER(2, "销售订单"), SALE_RETURN(3, + "销售退单"), RETAIL_OUT_SHEET(4, "零售出库单"), RETAIL_RETURN(5, "零售退单"); + + @EnumValue + private final Integer code; + + private final String desc; + + OrderChartBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/impl/OrderChartServiceImpl.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/impl/OrderChartServiceImpl.java new file mode 100644 index 0000000..acd31ca --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/impl/OrderChartServiceImpl.java @@ -0,0 +1,149 @@ +package com.lframework.xingyun.chart.impl; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.chart.dto.OrderChartSameMonthDto; +import com.lframework.xingyun.chart.dto.OrderChartSumDto; +import com.lframework.xingyun.chart.dto.OrderChartTodayDto; +import com.lframework.xingyun.chart.entity.OrderChart; +import com.lframework.xingyun.chart.enums.OrderChartBizType; +import com.lframework.xingyun.chart.mappers.OrderChartMapper; +import com.lframework.xingyun.chart.service.OrderChartService; +import com.lframework.xingyun.chart.vo.CreateOrderChartVo; +import com.lframework.xingyun.chart.vo.GetOrderChartVo; +import com.lframework.xingyun.chart.vo.QueryOrderChartVo; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class OrderChartServiceImpl extends BaseMpServiceImpl + implements OrderChartService { + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateOrderChartVo vo) { + + if (vo.getCreateTime() == null) { + vo.setCreateTime(LocalDateTime.now()); + } + + OrderChart record = new OrderChart(); + record.setId(IdUtil.getId()); + record.setTotalAmount(vo.getTotalAmount()); + record.setCreateTime(vo.getCreateTime()); + record.setBizType(EnumUtil.getByCode(OrderChartBizType.class, vo.getBizType())); + record.setCreateDate(DateUtil.formatDate(vo.getCreateTime().toLocalDate())); + record.setCreateHour(DateUtil.format(vo.getCreateTime(), StringPool.DATE_TIME_HOUR_PATTER)); + + getBaseMapper().insert(record); + + return record.getId(); + } + + @Override + public OrderChartSumDto getTodayChartSum(GetOrderChartVo vo) { + + LocalDate now = LocalDate.now(); + + OrderChartSumDto data = getBaseMapper().getChartSum(vo.getBizTypes(), + DateUtil.toLocalDateTime(now), + DateUtil.toLocalDateTimeMax(now)); + if (data == null) { + data = new OrderChartSumDto(); + data.setTotalAmount(BigDecimal.ZERO); + data.setTotalNum(0L); + } + + return data; + } + + @Override + public OrderChartSumDto getSameMonthChartSum(GetOrderChartVo vo) { + + LocalDate startDate = LocalDate.now().withDayOfMonth(1); + LocalDate endDate = startDate.plusMonths(1).minusDays(1); + + OrderChartSumDto data = getBaseMapper().getChartSum(vo.getBizTypes(), + DateUtil.toLocalDateTime(startDate), + DateUtil.toLocalDateTimeMax(endDate)); + if (data == null) { + data = new OrderChartSumDto(); + data.setTotalAmount(BigDecimal.ZERO); + data.setTotalNum(0L); + } + + return data; + } + + @Override + public List queryTodayChart(QueryOrderChartVo vo) { + + LocalDate now = LocalDate.now(); + + List results = getBaseMapper().queryToday(vo.getBizTypes(), + DateUtil.toLocalDateTime(now), + DateUtil.toLocalDateTimeMax(now)); + + int offset = 24; + List newResults = new ArrayList<>(offset); + + for (int i = 0; i < offset; i++) { + LocalTime localTime = LocalTime.of(i, 0, 0); + String filterDateStr = DateUtil.formatDateTime(LocalDateTime.of(now, localTime), + StringPool.DATE_TIME_HOUR_PATTER); + OrderChartTodayDto result = results.stream() + .filter(t -> t.getCreateHour().equals(filterDateStr)) + .findFirst().orElse(null); + if (result == null) { + result = new OrderChartTodayDto(); + result.setCreateHour(filterDateStr); + result.setTotalAmount(BigDecimal.ZERO); + result.setTotalNum(0); + } + + newResults.add(result); + } + + return newResults; + } + + @Override + public List querySameMonthChart(QueryOrderChartVo vo) { + + LocalDate startDate = LocalDate.now().withDayOfMonth(1); + LocalDate endDate = startDate.plusMonths(1).minusDays(1); + + List results = getBaseMapper().querySameMonth(vo.getBizTypes(), + DateUtil.toLocalDateTime(startDate), DateUtil.toLocalDateTimeMax(endDate)); + + LocalDate lastDate = startDate.plusMonths(1).minusDays(1); + int offset = lastDate.getDayOfMonth() - startDate.getDayOfMonth() + 1; + List newResults = new ArrayList<>(offset); + + for (int i = 0; i < offset; i++) { + String filterDateStr = DateUtil.formatDate(startDate.plusDays(i)); + OrderChartSameMonthDto result = results.stream() + .filter(t -> t.getCreateDate().equals(filterDateStr)) + .findFirst().orElse(null); + if (result == null) { + result = new OrderChartSameMonthDto(); + result.setCreateDate(filterDateStr); + result.setTotalAmount(BigDecimal.ZERO); + result.setTotalNum(0); + } + + newResults.add(result); + } + + return newResults; + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/listeners/OrderDataListener.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/listeners/OrderDataListener.java new file mode 100644 index 0000000..f5f35be --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/listeners/OrderDataListener.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.chart.listeners; + +import com.lframework.xingyun.chart.enums.OrderChartBizType; +import com.lframework.xingyun.chart.service.OrderChartService; +import com.lframework.xingyun.chart.vo.CreateOrderChartVo; +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class OrderDataListener implements ApplicationListener { + + @Autowired + private OrderChartService orderChartService; + + @Override + public void onApplicationEvent(ApprovePassOrderEvent event) { + + OrderChartBizType bizType = this.convertBizType(event.getOrderType()); + if (event.getOrderType() == null) { + log.error("orderType={},无法匹配业务类型", event.getOrderType()); + return; + } + + CreateOrderChartVo vo = new CreateOrderChartVo(); + vo.setTotalAmount(event.getTotalAmount()); + vo.setCreateTime(event.getApproveTime()); + vo.setBizType(bizType.getCode()); + + orderChartService.create(vo); + } + + private OrderChartBizType convertBizType(ApprovePassOrderEvent.OrderType orderType) { + + if (orderType == ApprovePassOrderEvent.OrderType.PURCHASE_ORDER) { + return OrderChartBizType.PURCHASE_ORDER; + } + if (orderType == ApprovePassOrderEvent.OrderType.PURCHASE_RETURN) { + return OrderChartBizType.PURCHASE_RETURN; + } + if (orderType == ApprovePassOrderEvent.OrderType.SALE_ORDER) { + return OrderChartBizType.SALE_ORDER; + } + if (orderType == ApprovePassOrderEvent.OrderType.SALE_RETURN) { + return OrderChartBizType.SALE_RETURN; + } + if (orderType == ApprovePassOrderEvent.OrderType.RETAIL_OUT_SHEET) { + return OrderChartBizType.RETAIL_OUT_SHEET; + } + if (orderType == ApprovePassOrderEvent.OrderType.RETAIL_RETURN) { + return OrderChartBizType.RETAIL_RETURN; + } + + return null; + } +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/mappers/OrderChartMapper.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/mappers/OrderChartMapper.java new file mode 100644 index 0000000..58a7979 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/mappers/OrderChartMapper.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.chart.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.chart.dto.OrderChartSameMonthDto; +import com.lframework.xingyun.chart.dto.OrderChartSumDto; +import com.lframework.xingyun.chart.dto.OrderChartTodayDto; +import com.lframework.xingyun.chart.entity.OrderChart; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-19 + */ +public interface OrderChartMapper extends BaseMapper { + + /** + * 汇总数据 + * + * @param bizTypes + * @param startTime + * @param endTime + * @return + */ + OrderChartSumDto getChartSum(@Param("bizTypes") List bizTypes, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + + /** + * 查询列表 + * + * @param bizTypes + * @param startTime + * @param endTime + * @return + */ + List querySameMonth(@Param("bizTypes") List bizTypes, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); + + /** + * 查询当日数据列表 + * + * @param bizTypes + * @param startTime + * @param endTime + * @return + */ + List queryToday(@Param("bizTypes") List bizTypes, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/service/OrderChartService.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/service/OrderChartService.java new file mode 100644 index 0000000..f2ba3a3 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/service/OrderChartService.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.chart.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.chart.dto.OrderChartSameMonthDto; +import com.lframework.xingyun.chart.dto.OrderChartSumDto; +import com.lframework.xingyun.chart.dto.OrderChartTodayDto; +import com.lframework.xingyun.chart.entity.OrderChart; +import com.lframework.xingyun.chart.vo.CreateOrderChartVo; +import com.lframework.xingyun.chart.vo.GetOrderChartVo; +import com.lframework.xingyun.chart.vo.QueryOrderChartVo; +import java.util.List; + +public interface OrderChartService extends BaseMpService { + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateOrderChartVo vo); + + /** + * 查询当日汇总数据 + * + * @param vo + * @return + */ + OrderChartSumDto getTodayChartSum(GetOrderChartVo vo); + + /** + * 查询当月汇总数据 + * + * @param vo + * @return + */ + OrderChartSumDto getSameMonthChartSum(GetOrderChartVo vo); + + /** + * 查询当日数据 + * + * @param vo + * @return + */ + List queryTodayChart(QueryOrderChartVo vo); + + /** + * 查询当月数据 + * + * @param vo + * @return + */ + List querySameMonthChart(QueryOrderChartVo vo); +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/CreateOrderChartVo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/CreateOrderChartVo.java new file mode 100644 index 0000000..491f4a8 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/CreateOrderChartVo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.chart.vo; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.chart.enums.OrderChartBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateOrderChartVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据总金额 + */ + @ApiModelProperty(value = "单据总金额", required = true) + @NotNull(message = "单据总金额不能为空!") + private BigDecimal totalAmount; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型不存在!", enumClass = OrderChartBizType.class) + private Integer bizType; +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/GetOrderChartVo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/GetOrderChartVo.java new file mode 100644 index 0000000..1f6ad89 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/GetOrderChartVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.chart.vo; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class GetOrderChartVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotEmpty(message = "业务类型不能为空!") + private List bizTypes; +} diff --git a/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/QueryOrderChartVo.java b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/QueryOrderChartVo.java new file mode 100644 index 0000000..17dd688 --- /dev/null +++ b/xingyun-chart/src/main/java/com/lframework/xingyun/chart/vo/QueryOrderChartVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.chart.vo; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class QueryOrderChartVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotEmpty(message = "业务类型不能为空!") + private List bizTypes; +} diff --git a/xingyun-chart/src/main/java/lombok.config b/xingyun-chart/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-chart/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-chart/src/main/resources/mappers/OrderChartMapper.xml b/xingyun-chart/src/main/resources/mappers/OrderChartMapper.xml new file mode 100644 index 0000000..03a6246 --- /dev/null +++ b/xingyun-chart/src/main/resources/mappers/OrderChartMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xingyun-common/pom.xml b/xingyun-common/pom.xml new file mode 100644 index 0000000..2d4633e --- /dev/null +++ b/xingyun-common/pom.xml @@ -0,0 +1,22 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-common + 【${project.artifactId}】公共组件服务层 + + + + com.lframework + xingyun-core + + + + \ No newline at end of file diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/MapLocationBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/MapLocationBo.java new file mode 100644 index 0000000..d114bcd --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/MapLocationBo.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.common.bo.components; + +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class MapLocationBo extends BaseBo { + + /** + * 经度 + */ + @ApiModelProperty("经度") + private BigDecimal lng; + + /** + * 纬度 + */ + @ApiModelProperty("纬度") + private BigDecimal lat; +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/OrderTimeLineBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/OrderTimeLineBo.java new file mode 100644 index 0000000..79bb7d4 --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/components/OrderTimeLineBo.java @@ -0,0 +1,67 @@ +package com.lframework.xingyun.common.bo.components; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/10 + */ +@Data +public class OrderTimeLineBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String orderId; + + /** + * 描述内容 + */ + @ApiModelProperty("描述内容") + private String content; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + public OrderTimeLineBo() { + } + + public OrderTimeLineBo(OrderTimeLine dto) { + super(dto); + } + + @Override + protected void afterInit(OrderTimeLine dto) { + + this.bizType = dto.getBizType().getCode(); + } +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/dic/CitySelectorBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/dic/CitySelectorBo.java new file mode 100644 index 0000000..2a28b5c --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/dic/CitySelectorBo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.common.bo.dic; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class CitySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + public CitySelectorBo() { + + } + + public CitySelectorBo(DicCityDto dto) { + + super(dto); + } +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/GetOnlineExcelBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/GetOnlineExcelBo.java new file mode 100644 index 0000000..688dffe --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/GetOnlineExcelBo.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.common.bo.sw.excel; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.core.entity.OnlineExcel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 在线Excel GetBo + *

+ */ +@Data +public class GetOnlineExcelBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public GetOnlineExcelBo() { + + } + + public GetOnlineExcelBo(OnlineExcel dto) { + + super(dto); + } + +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/QueryOnlineExcelBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/QueryOnlineExcelBo.java new file mode 100644 index 0000000..984e600 --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/excel/QueryOnlineExcelBo.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.common.bo.sw.excel; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.core.entity.OnlineExcel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 在线Excel QueryBo + *

+ */ +@Data +public class QueryOnlineExcelBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryOnlineExcelBo() { + + } + + public QueryOnlineExcelBo(OnlineExcel dto) { + + super(dto); + } + +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/GetFileBoxBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/GetFileBoxBo.java new file mode 100644 index 0000000..de6d7ed --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/GetFileBoxBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.common.bo.sw.filebox; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.core.entity.FileBox; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 文件收纳箱 GetBo + *

+ */ +@Data +public class GetFileBoxBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * Url + */ + @ApiModelProperty("Url") + private String url; + + /** + * 上传类型 + */ + @ApiModelProperty("上传类型") + private String contentType; + + @ApiModelProperty("文件类型") + @EnumConvert + private Integer fileType; + + /** + * 文件大小 + */ + @ApiModelProperty("文件大小") + private String fileSize; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + public GetFileBoxBo() { + + } + + public GetFileBoxBo(FileBox dto) { + + super(dto); + } + +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/QueryFileBoxBo.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/QueryFileBoxBo.java new file mode 100644 index 0000000..abf11ea --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/bo/sw/filebox/QueryFileBoxBo.java @@ -0,0 +1,56 @@ +package com.lframework.xingyun.common.bo.sw.filebox; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.core.entity.FileBox; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 文件收纳箱 QueryBo + *

+ */ +@Data +public class QueryFileBoxBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("文件大小") + private String fileSize; + + @ApiModelProperty("文件类型") + @EnumConvert + private Integer fileType; + + @ApiModelProperty("文件路径") + private String filePath; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + public QueryFileBoxBo() { + + } + + public QueryFileBoxBo(FileBox dto) { + + super(dto); + } + +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/SelectorController.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/SelectorController.java new file mode 100644 index 0000000..6d09750 --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/SelectorController.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.common.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.common.bo.dic.CitySelectorBo; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据选择器 + * + * @author zmj + */ +@Api(tags = "数据选择器") +@Validated +@RestController +@RequestMapping("/selector") +public class SelectorController extends DefaultBaseController { + + @Autowired + private DicCityService dicCityService; + + /** + * 城市数据 + */ + @ApiOperation("城市数据") + @GetMapping("/city") + public InvokeResult> dicCity() { + + List datas = dicCityService.getAll(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(CitySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/components/ComponentController.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/components/ComponentController.java new file mode 100644 index 0000000..e844dda --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/components/ComponentController.java @@ -0,0 +1,153 @@ +package com.lframework.xingyun.common.controller.components; + +import cn.hutool.crypto.SecureUtil; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.FileUtil; +import com.lframework.starter.web.bo.ExcelImportBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.service.SysParameterService; +import com.lframework.starter.web.utils.ExcelImportUtil; +import com.lframework.starter.web.utils.HttpUtil; +import com.lframework.starter.web.utils.JsonUtil; +import com.lframework.starter.web.utils.UploadUtil; +import com.lframework.xingyun.common.bo.components.MapLocationBo; +import com.lframework.xingyun.common.bo.components.OrderTimeLineBo; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 公共组件 Controller + */ +@Slf4j +@Api(tags = "公共组件") +@Validated +@RestController +@RequestMapping("/component") +public class ComponentController extends DefaultBaseController { + + @Autowired + private SysParameterService sysParameterService; + + @Autowired + private OrderTimeLineService orderTimeLineService; + + @ApiOperation("查询导入Excel任务") + @GetMapping("/import/task") + public InvokeResult getExcelImportTask(@NotBlank(message = "ID不能为空!") String id) { + + return InvokeResultBuilder.success(ExcelImportUtil.getTask(id)); + } + + @ApiOperation("获取地图Key") + @GetMapping("/map/key") + public InvokeResult getMapKey() { + String key = sysParameterService.findRequiredByKey("tx-map.key"); + + return InvokeResultBuilder.success(key); + } + + @ApiOperation("根据地址查询经纬度") + @GetMapping("/map/location") + public InvokeResult getMapLocation(@NotEmpty(message = "地址不能为空!") String address) { + + String key = sysParameterService.findRequiredByKey("tx-map.key"); + String secret = sysParameterService.findRequiredByKey("tx-map.secret"); + + // 请求腾讯地图WebService Api + // Api文档地址:https://lbs.qq.com/service/webService/webServiceGuide/webServiceGeocoder + String baseUrl = "https://apis.map.qq.com/"; + String uri = "/ws/geocoder/v1/"; + String reqParams = "?address=" + address + "&key=" + key; + + // Api使用签名方式 + // 签名文档:https://lbs.qq.com/faq/serverFaq/webServiceKey + String sign = SecureUtil.md5(uri + reqParams + secret); + Map reqMap = new HashMap<>(); + reqMap.put("address", address); + reqMap.put("key", key); + reqMap.put("sig", sign); + + try { + String resp = HttpUtil.doGet(baseUrl + uri, reqMap); + Map respMap = JsonUtil.parseObject(resp, Map.class); + if (!"0".equals(String.valueOf(respMap.get("status")))) { + throw new DefaultClientException(String.valueOf(respMap.get("message"))); + } + + Map result = (Map) respMap.get("result"); + Map location = (Map) result.get("location"); + MapLocationBo bo = new MapLocationBo(); + bo.setLng(new BigDecimal(String.valueOf(location.get("lng")))); + bo.setLat(new BigDecimal(String.valueOf(location.get("lat")))); + + return InvokeResultBuilder.success(bo); + } catch (ClientException e) { + throw e; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultClientException("解析地址失败,请稍后再试!"); + } + } + + @ApiOperation("单据时间轴") + @ApiImplicitParam(value = "单据ID", name = "orderId", paramType = "query", required = true) + @GetMapping("/timeline/order") + public InvokeResult> getOrderTimeLine( + @NotBlank(message = "单据ID不能为空!") String orderId) { + + List datas = orderTimeLineService.getByOrder(orderId); + List results = datas.stream().map(OrderTimeLineBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("通用上传图片") + @PostMapping("/upload/image") + public InvokeResult uploadImage(MultipartFile file) { + if (!FileUtil.IMG_SUFFIX.contains(FileUtil.getSuffix(file.getOriginalFilename()).toLowerCase())) { + throw new DefaultClientException( + "上传图片仅支持【" + CollectionUtil.join(FileUtil.IMG_SUFFIX, StringPool.STR_SPLIT_CN) + "】格式!"); + } + + String url = UploadUtil.upload(file); + + return InvokeResultBuilder.success(url); + } + + @ApiOperation("通用上传视频") + @PostMapping("/upload/video") + public InvokeResult uploadVideo(MultipartFile file) { + if (!FileUtil.VIDEO_SUFFIX.contains(FileUtil.getSuffix(file.getOriginalFilename()).toLowerCase())) { + throw new DefaultClientException( + "上传视频仅支持【" + CollectionUtil.join(FileUtil.VIDEO_SUFFIX, StringPool.STR_SPLIT_CN) + "】格式!"); + } + + String url = UploadUtil.upload(file); + + return InvokeResultBuilder.success(url); + } +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/FileBoxController.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/FileBoxController.java new file mode 100644 index 0000000..1833891 --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/FileBoxController.java @@ -0,0 +1,124 @@ +package com.lframework.xingyun.common.controller.sw; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.common.bo.sw.filebox.GetFileBoxBo; +import com.lframework.xingyun.common.bo.sw.filebox.QueryFileBoxBo; +import com.lframework.xingyun.core.entity.FileBox; +import com.lframework.xingyun.core.service.FileBoxService; +import com.lframework.xingyun.core.vo.sw.filebox.CreateFileBoxDirVo; +import com.lframework.xingyun.core.vo.sw.filebox.QueryFileBoxVo; +import com.lframework.xingyun.core.vo.sw.filebox.UpdateFileBoxVo; +import com.lframework.xingyun.core.vo.sw.filebox.UploadFileBoxVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 文件收纳箱 Controller + */ +@Api(tags = "文件收纳箱") +@Validated +@RestController +@RequestMapping("/sw/filebox") +public class FileBoxController extends DefaultBaseController { + + @Autowired + private FileBoxService fileBoxService; + + @ApiOperation("创建文件夹") + @PostMapping("/dir") + public InvokeResult createDir(@Valid CreateFileBoxDirVo vo) { + + fileBoxService.createDir(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 上传文件 + */ + @ApiOperation("上传文件") + @PostMapping("/upload") + public InvokeResult upload(@Valid UploadFileBoxVo vo) { + + fileBoxService.upload(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryFileBoxVo vo) { + + PageResult pageResult = fileBoxService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryFileBoxBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + FileBox data = fileBoxService.findById(id); + if (data == null) { + throw new DefaultClientException("文件收纳箱不存在!"); + } + + GetFileBoxBo result = new GetFileBoxBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@Valid UpdateFileBoxVo vo) { + + fileBoxService.update(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public InvokeResult batchDelete(@RequestBody List ids) { + fileBoxService.batchDelete(ids); + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/OnlineExcelController.java b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/OnlineExcelController.java new file mode 100644 index 0000000..496429c --- /dev/null +++ b/xingyun-common/src/main/java/com/lframework/xingyun/common/controller/sw/OnlineExcelController.java @@ -0,0 +1,158 @@ +package com.lframework.xingyun.common.controller.sw; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.xingyun.common.bo.sw.excel.GetOnlineExcelBo; +import com.lframework.xingyun.common.bo.sw.excel.QueryOnlineExcelBo; +import com.lframework.xingyun.core.entity.OnlineExcel; +import com.lframework.xingyun.core.service.OnlineExcelService; +import com.lframework.xingyun.core.vo.sw.excel.BatchSendOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.CreateOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.QueryOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.SendOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.UpdateOnlineExcelContentVo; +import com.lframework.xingyun.core.vo.sw.excel.UpdateOnlineExcelVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 在线Excel Controller + */ +@Api(tags = "在线Excel") +@Validated +@RestController +@RequestMapping("/sw/excel") +public class OnlineExcelController extends DefaultBaseController { + + @Autowired + private OnlineExcelService onlineExcelService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryOnlineExcelVo vo) { + + PageResult pageResult = onlineExcelService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryOnlineExcelBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + OnlineExcel data = onlineExcelService.findById(id); + if (data == null) { + throw new DefaultClientException("在线Excel不存在!"); + } + + GetOnlineExcelBo result = new GetOnlineExcelBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @PostMapping + public InvokeResult create(@Valid CreateOnlineExcelVo vo) { + + onlineExcelService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@Valid UpdateOnlineExcelVo vo) { + + onlineExcelService.update(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("查询内容") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @GetMapping("/content") + public InvokeResult getContent(@NotBlank(message = "id不能为空!") String id) { + + OnlineExcel data = onlineExcelService.findById(id); + if (data == null) { + throw new DefaultClientException("文件不存在!"); + } + + return InvokeResultBuilder.success(data.getContent()); + } + + @ApiOperation("修改内容") + @PutMapping("/content") + public InvokeResult updateContent(@Valid UpdateOnlineExcelContentVo vo) { + + onlineExcelService.updateContent(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("发送文件给他人") + @PostMapping("/send") + public InvokeResult send(@Valid SendOnlineExcelVo vo) { + + if (vo.getUserId().equals(SecurityUtil.getCurrentUser().getId())) { + throw new DefaultClientException("文件不能发送给自己!"); + } + + onlineExcelService.send(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量发送文件给他人") + @PostMapping("/send/batch") + public InvokeResult batchSend(@Valid @RequestBody BatchSendOnlineExcelVo vo) { + + if (vo.getUserId().equals(SecurityUtil.getCurrentUser().getId())) { + throw new DefaultClientException("文件不能发送给自己!"); + } + + onlineExcelService.batchSend(vo); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-common/src/main/java/lombok.config b/xingyun-common/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-common/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-core/pom.xml b/xingyun-core/pom.xml new file mode 100644 index 0000000..76d1f33 --- /dev/null +++ b/xingyun-core/pom.xml @@ -0,0 +1,25 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-core + 【${project.artifactId}】基础依赖 + + + + com.lframework + xingyun-template-core + + + com.lframework + websocket-starter + + + diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/annations/OrderTimeLineLog.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/annations/OrderTimeLineLog.java new file mode 100644 index 0000000..10418eb --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/annations/OrderTimeLineLog.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.core.annations; + +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 单据时间轴记录 + * 如果出现嵌套那么以最外层的为准,不会进行嵌套隔离 + * @author zmj + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OrderTimeLineLog { + + /** + * 业务类型 + * + * @return + */ + OrderTimeLineBizType type() default OrderTimeLineBizType.NORMAL; + + /** + * 单据ID + * @return + */ + String[] orderId(); + + /** + * 内容 需要填充参数部分用{}占位,会根据params的值进行填充 + * + * @return + */ + String name() default ""; + + /** + * 需要保存的参数 Spel表达式 + * + * @return + */ + String[] params() default {}; + + /** + * 是否循环填充内容 会将params中的collection循环format + * + * @return + */ + boolean loopFormat() default false; + + /** + * 是否为删除操作 + * 如果为删除操作,那么忽略type、name、loopFormat,直接根据orderId进行删除操作 + * @return + */ + boolean delete() default false; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/aop/OrderTimeLineLogAspect.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/aop/OrderTimeLineLogAspect.java new file mode 100644 index 0000000..8ef4f55 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/aop/OrderTimeLineLogAspect.java @@ -0,0 +1,224 @@ +package com.lframework.xingyun.core.aop; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.config.properties.DefaultSettingProperties; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.SpelUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.expression.EvaluationContext; +import org.springframework.stereotype.Component; + +/** + * 单据时间轴切面 + * + * @author zmj + */ +@Slf4j +@Aspect +@Component +public class OrderTimeLineLogAspect { + + @Autowired + private DefaultSettingProperties defaultSettingProperties; + + private final ThreadLocal POOL = new ThreadLocal<>(); + + @Pointcut("@annotation(com.lframework.xingyun.core.annations.OrderTimeLineLog)") + public void orderTimeLineLogCutPoint() { + + } + + @Around(value = "orderTimeLineLogCutPoint()") + public Object orderTimeLineLog(ProceedingJoinPoint joinPoint) throws Throwable { + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + String curUserId = + currentUser == null ? defaultSettingProperties.getDefaultUserId() : currentUser.getId(); + String curUserName = + currentUser == null ? defaultSettingProperties.getDefaultUserName() : currentUser.getName(); + + Object value = null; + + try { + if (POOL.get() != null) { + POOL.set(POOL.get() + 1); + // 如果出现嵌套,那么以最外层的为准,不进行嵌套隔离 + return joinPoint.proceed(); + } + + POOL.set(1); + + value = joinPoint.proceed(); + + try { + //获取方法的参数名和参数值 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + List paramNameList = Arrays.asList(methodSignature.getParameterNames()); + List paramList = Arrays.asList(joinPoint.getArgs()); + + //将方法的参数名和参数值一一对应的放入上下文中 + EvaluationContext ctx = SpelUtil.buildContext(); + for (int i = 0; i < paramNameList.size(); i++) { + ctx.setVariable(paramNameList.get(i), paramList.get(i)); + } + + //将返回值放入上下文中 + ctx.setVariable("_result", value); + + // 解析SpEL表达式获取结果 + Object[] params; + OrderTimeLineLog orderTimeLineLog = methodSignature.getMethod() + .getAnnotation(OrderTimeLineLog.class); + if (!ArrayUtil.isEmpty(orderTimeLineLog.params())) { + params = new Object[orderTimeLineLog.params().length]; + for (int i = 0; i < orderTimeLineLog.params().length; i++) { + String param = orderTimeLineLog.params()[i]; + Object p = SpelUtil.parse(param, ctx); + params[i] = p; + } + } else { + params = new String[0]; + } + + List paramsList = new ArrayList<>(); + //循环format + if (orderTimeLineLog.loopFormat() && Arrays.stream(params) + .anyMatch(t -> t instanceof Collection)) { + String[] strParams = new String[params.length]; + //collectionIndex的索引 + List collectionIndexes = new ArrayList<>(); + for (int i = 0; i < params.length; i++) { + //先处理不是Collection的元素 + if (params[i] instanceof Collection) { + collectionIndexes.add(i); + continue; + } + strParams[i] = params[i] == null ? null : params[i].toString(); + } + + paramsList.add(strParams); + + if (!CollectionUtil.isEmpty(collectionIndexes)) { + //将所有的collection组合,例:collection1的size是2 collection2的size是3 则组合后的条数为2*3=6 + for (Integer collectionIndex : collectionIndexes) { + List tmpParamsList = new ArrayList<>(); + for (String[] paramsArr : paramsList) { + + Collection collection = (Collection) params[collectionIndex]; + for (Object o : collection) { + String[] tmp = new String[paramsArr.length]; + for (int j = 0; j < paramsArr.length; j++) { + if (j == collectionIndex) { + tmp[j] = o == null ? null : o.toString(); + } else { + tmp[j] = paramsArr[j]; + } + } + + tmpParamsList.add(tmp); + } + } + + paramsList.clear(); + paramsList.addAll(tmpParamsList); + } + } else { + paramsList.add(strParams); + } + } else { + String[] strParams = new String[params.length]; + for (int i = 0; i < params.length; i++) { + strParams[i] = params[i] == null ? null : params[i].toString(); + } + paramsList.add(strParams); + } + + Object[] orderIds; + if (!ArrayUtil.isEmpty(orderTimeLineLog.orderId())) { + orderIds = new Object[orderTimeLineLog.orderId().length]; + for (int i = 0; i < orderTimeLineLog.orderId().length; i++) { + String orderId = orderTimeLineLog.orderId()[i]; + Object p = SpelUtil.parse(orderId, ctx); + orderIds[i] = p; + } + } else { + orderIds = new String[0]; + } + + List orderIdList = new ArrayList<>(); + for (Object orderId : orderIds) { + if (orderId == null) { + continue; + } + + if (orderId instanceof Collection) { + Collection c = (Collection) orderId; + CollectionUtil.forEach(c, (item, index) -> orderIdList.add(item.toString())); + } + + orderIdList.add(orderId.toString()); + } + + if (orderTimeLineLog.delete()) { + for (String orderId : orderIdList) { + // 这里不异步,在同事务内执行 + OrderTimeLineService orderTimeLineService = ApplicationUtil.getBean( + OrderTimeLineService.class); + orderTimeLineService.deleteByOrder(orderId); + orderTimeLineService.cleanCacheByKey(orderId); + } + } else { + List records = new ArrayList<>(); + OrderTimeLineService orderTimeLineService = ApplicationUtil.getBean( + OrderTimeLineService.class); + for (String[] strArr : paramsList) { + for (String orderId : orderIdList) { + OrderTimeLine record = new OrderTimeLine(); + record.setId(IdUtil.getId()); + record.setOrderId(orderId); + record.setContent(StringUtil.format(orderTimeLineLog.name(), strArr)); + record.setCreateBy(curUserName); + record.setCreateById(curUserId); + record.setBizType(orderTimeLineLog.type()); + records.add(record); + } + } + if (CollectionUtil.isNotEmpty(records)) { + // 这里不异步,在同事务内执行 + orderTimeLineService.saveBatch(records); + orderTimeLineService.cleanCacheByKeys(orderIdList); + } + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } finally { + if (POOL.get() != null) { + POOL.set(POOL.get() - 1); + if (POOL.get() <= 0) { + POOL.remove(); + } + } + } + return value; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/bo/print/A4ExcelPortraitPrintBo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/bo/print/A4ExcelPortraitPrintBo.java new file mode 100644 index 0000000..374a1ed --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/bo/print/A4ExcelPortraitPrintBo.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.core.bo.print; + +import com.lframework.starter.web.bo.BasePrintBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + * Excel文件的A4纸纵向打印的默认设置 + */ +@Data +public class A4ExcelPortraitPrintBo> extends + BasePrintBo { + + public A4ExcelPortraitPrintBo(String templateName) { + + this(templateName, null); + } + + public A4ExcelPortraitPrintBo(String templateName, T data) { + + super(templateName, data); + + this.setOrient(2); + this.setPageHeight(2970); + this.setPageWidth(2100); + this.setPageName("A4"); + + this.setMarginTop(19.1D); + this.setMarginRight(17.8D); + this.setMarginBottom(19.1D); + this.setMarginLeft(17.8D); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/dto/dic/city/DicCityDto.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/dto/dic/city/DicCityDto.java new file mode 100644 index 0000000..8be955e --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/dto/dic/city/DicCityDto.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.core.dto.dic.city; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class DicCityDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "DicCityDto"; + + public static final String SELECTOR_CACHE_NAME = "DicCitySelectorDto"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + private String parentId; + + /** + * 层级 + */ + private Integer level; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/dto/stock/ProductStockChangeDto.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/dto/stock/ProductStockChangeDto.java new file mode 100644 index 0000000..71446b1 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/dto/stock/ProductStockChangeDto.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.core.dto.stock; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +@Data +public class ProductStockChangeDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + private String scId; + + /** + * 商品ID + */ + private String productId; + + /** + * 变动数量 + */ + private Integer num; + + /** + * 含税金额 + */ + private BigDecimal taxAmount; + + /** + * 当前含税均价 + */ + private BigDecimal curTaxPrice; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/DicCity.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/DicCity.java new file mode 100644 index 0000000..b8bdc1e --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/DicCity.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-07 + */ +@Data +@TableName("dic_city") +public class DicCity extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + private String parentId; + + /** + * 层级 + */ + private Integer level; + + /** + * 状态 + */ + private Boolean available; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/FileBox.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/FileBox.java new file mode 100644 index 0000000..95f7db1 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/FileBox.java @@ -0,0 +1,104 @@ +package com.lframework.xingyun.core.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.core.enums.FileBoxFileType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 文件收纳箱 + *

+ */ +@Data +@TableName("sw_file_box") +public class FileBox extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "FileBox"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * Url + */ + private String url; + + /** + * ContentType + */ + private String contentType; + + /** + * 文件类型 + */ + private FileBoxFileType fileType; + + /** + * 文件大小 + */ + private String fileSize; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 文件后缀 + */ + private String fileSuffix; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OnlineExcel.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OnlineExcel.java new file mode 100644 index 0000000..8d50fce --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OnlineExcel.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.core.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 在线Excel + *

+ */ +@Data +@TableName("sw_online_excel") +public class OnlineExcel extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "OnlineExcel"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 内容 + */ + private String content; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OrderTimeLine.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OrderTimeLine.java new file mode 100644 index 0000000..95af84a --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/entity/OrderTimeLine.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.core.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-07 + */ +@Data +@TableName("tbl_order_time_line") +public class OrderTimeLine extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "OrderTimeLine"; + + /** + * ID + */ + private String id; + + /** + * 订单ID + */ + private String orderId; + + /** + * 描述内容 + */ + private String content; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 业务类型 + */ + private OrderTimeLineBizType bizType; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxFileType.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxFileType.java new file mode 100644 index 0000000..c338ae8 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxFileType.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum FileBoxFileType implements BaseEnum { + DIR(0, "目录"), + FILE(1, "文件"), + ; + + @EnumValue + private final Integer code; + + private final String desc; + + FileBoxFileType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxNodeType.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxNodeType.java new file mode 100644 index 0000000..4e08ff0 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/FileBoxNodeType.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.core.enums; + +import com.lframework.xingyun.template.core.enums.NodeType; +import java.io.Serializable; +import org.springframework.stereotype.Component; + +@Component +public final class FileBoxNodeType implements NodeType, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public Integer getCode() { + + return 3; + } + + @Override + public String getDesc() { + + return "文件收纳箱"; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/OrderTimeLineBizType.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/OrderTimeLineBizType.java new file mode 100644 index 0000000..240006f --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/OrderTimeLineBizType.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +/** + * @author zmj + * @since 2022/8/10 + */ +public enum OrderTimeLineBizType implements BaseEnum { + NORMAL(0, "普通操作"), + CREATE(1, "保存"), + UPDATE(2, "修改"), + SEND(3, "发送"), + APPROVE_PASS(4, "审核通过"), + APPROVE_RETURN(5, "审核拒绝"), + CANCEL_APPROVE(6, "取消审核"), + APPROVE_SEND(8, "发送审批"), + RECEIVE(7, "收货") + + ; + + @EnumValue + private final Integer code; + + private final String desc; + + OrderTimeLineBizType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/SwOpLogType.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/SwOpLogType.java new file mode 100644 index 0000000..e7ff780 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/enums/SwOpLogType.java @@ -0,0 +1,7 @@ +package com.lframework.xingyun.core.enums; + +public interface SwOpLogType { + + // 便捷办公 + int SW = 4000; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/ApprovePassOrderEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/ApprovePassOrderEvent.java new file mode 100644 index 0000000..962b4f6 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/ApprovePassOrderEvent.java @@ -0,0 +1,56 @@ +package com.lframework.xingyun.core.events.order; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; +import org.springframework.context.ApplicationEvent; + +/** + * 业务单据审核通过Event + */ +public abstract class ApprovePassOrderEvent extends ApplicationEvent { + + /** + * 业务单据ID + */ + @Getter + @Setter + private String id; + + /** + * 单据总金额 + */ + @Getter + @Setter + private BigDecimal totalAmount; + + /** + * 审核时间 + */ + @Getter + @Setter + private LocalDateTime approveTime = LocalDateTime.now(); + + /** + * 单据类型 + */ + @Getter + private OrderType orderType; + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassOrderEvent(Object source, OrderType orderType) { + + super(source); + this.orderType = orderType; + } + + public enum OrderType { + PURCHASE_ORDER, PURCHASE_RETURN, SALE_ORDER, SALE_RETURN, RETAIL_OUT_SHEET, RETAIL_RETURN + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseOrderEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseOrderEvent.java new file mode 100644 index 0000000..7be0446 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseOrderEvent.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.core.events.order.impl; + +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; + +public class ApprovePassPurchaseOrderEvent extends ApprovePassOrderEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassPurchaseOrderEvent(Object source) { + + super(source, OrderType.PURCHASE_ORDER); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseReturnEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseReturnEvent.java new file mode 100644 index 0000000..f97f50a --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassPurchaseReturnEvent.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.core.events.order.impl; + +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; + +public class ApprovePassPurchaseReturnEvent extends ApprovePassOrderEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassPurchaseReturnEvent(Object source) { + + super(source, OrderType.PURCHASE_RETURN); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailOutSheetEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailOutSheetEvent.java new file mode 100644 index 0000000..c653ddb --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailOutSheetEvent.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.core.events.order.impl; + +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; + +public class ApprovePassRetailOutSheetEvent extends ApprovePassOrderEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassRetailOutSheetEvent(Object source) { + + super(source, OrderType.RETAIL_OUT_SHEET); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailReturnEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailReturnEvent.java new file mode 100644 index 0000000..db68045 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassRetailReturnEvent.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.core.events.order.impl; + +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; + +public class ApprovePassRetailReturnEvent extends ApprovePassOrderEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassRetailReturnEvent(Object source) { + + super(source, OrderType.RETAIL_RETURN); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleOrderEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleOrderEvent.java new file mode 100644 index 0000000..5560053 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleOrderEvent.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.core.events.order.impl; + +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; + +public class ApprovePassSaleOrderEvent extends ApprovePassOrderEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassSaleOrderEvent(Object source) { + + super(source, OrderType.SALE_ORDER); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleReturnEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleReturnEvent.java new file mode 100644 index 0000000..94eaff6 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/order/impl/ApprovePassSaleReturnEvent.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.core.events.order.impl; + +import com.lframework.xingyun.core.events.order.ApprovePassOrderEvent; + +public class ApprovePassSaleReturnEvent extends ApprovePassOrderEvent { + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public ApprovePassSaleReturnEvent(Object source) { + + super(source, OrderType.SALE_RETURN); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/AddStockEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/AddStockEvent.java new file mode 100644 index 0000000..b9ab4cf --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/AddStockEvent.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.core.events.stock; + +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import org.springframework.context.ApplicationEvent; + +/** + * 入库事件 + */ +public class AddStockEvent extends ApplicationEvent { + + /** + * 变动记录 + */ + private ProductStockChangeDto change; + + public AddStockEvent(Object source, ProductStockChangeDto change) { + + super(source); + this.change = change; + } + + public ProductStockChangeDto getChange() { + + return change; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/SubStockEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/SubStockEvent.java new file mode 100644 index 0000000..eedca74 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/SubStockEvent.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.core.events.stock; + +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import org.springframework.context.ApplicationEvent; + +/** + * 出库事件 + */ +public class SubStockEvent extends ApplicationEvent { + + /** + * 变动记录 + */ + private ProductStockChangeDto change; + + public SubStockEvent(Object source, ProductStockChangeDto change) { + + super(source); + this.change = change; + } + + public ProductStockChangeDto getChange() { + + return change; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/take/DeleteTakeStockPlanEvent.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/take/DeleteTakeStockPlanEvent.java new file mode 100644 index 0000000..4f98c93 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/events/stock/take/DeleteTakeStockPlanEvent.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.core.events.stock.take; + +import org.springframework.context.ApplicationEvent; + +/** + * 删除盘点任务事件 + */ +public class DeleteTakeStockPlanEvent extends ApplicationEvent { + + /** + * 盘点任务ID + */ + private String id; + + public DeleteTakeStockPlanEvent(Object source, String id) { + + super(source); + + this.id = id; + } + + public String getId() { + + return id; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/DicCityServiceImpl.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/DicCityServiceImpl.java new file mode 100644 index 0000000..ddc45e4 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/DicCityServiceImpl.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.core.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.entity.DicCity; +import com.lframework.xingyun.core.mappers.DicCityMapper; +import com.lframework.xingyun.core.service.DicCityService; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class DicCityServiceImpl extends BaseMpServiceImpl implements + DicCityService { + + @Cacheable(value = DicCityDto.SELECTOR_CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List getAll() { + + return getBaseMapper().getAll(); + } + + @Cacheable(value = DicCityDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public DicCityDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Override + public List getChainById(String id) { + + DicCityService thisService = getThis(this.getClass()); + List all = thisService.getAll(); + List results = new ArrayList<>(); + DicCityDto current = all.stream().filter(t -> t.getId().equals(id)).findFirst().orElse(null); + if (current == null) { + return results; + } + + while (current != null) { + results.add(current); + + String pId = current.getParentId(); + current = all.stream().filter(t -> t.getId().equals(pId)).findFirst().orElse(null); + } + + Collections.reverse(results); + + return results; + } + + @CacheEvict(value = DicCityDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/FileBoxServiceImpl.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/FileBoxServiceImpl.java new file mode 100644 index 0000000..a4eab08 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/FileBoxServiceImpl.java @@ -0,0 +1,222 @@ +package com.lframework.xingyun.core.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.FileUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.UploadUtil; +import com.lframework.xingyun.core.entity.FileBox; +import com.lframework.xingyun.core.enums.FileBoxFileType; +import com.lframework.xingyun.core.enums.FileBoxNodeType; +import com.lframework.xingyun.core.enums.SwOpLogType; +import com.lframework.xingyun.core.mappers.FileBoxMapper; +import com.lframework.xingyun.core.service.FileBoxService; +import com.lframework.xingyun.core.vo.sw.filebox.CreateFileBoxDirVo; +import com.lframework.xingyun.core.vo.sw.filebox.QueryFileBoxVo; +import com.lframework.xingyun.core.vo.sw.filebox.UpdateFileBoxVo; +import com.lframework.xingyun.core.vo.sw.filebox.UploadFileBoxVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class FileBoxServiceImpl extends + BaseMpServiceImpl implements FileBoxService { + + @Autowired + private RecursionMappingService recursionMappingService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryFileBoxVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryFileBoxVo vo) { + + return getBaseMapper().query(vo, SecurityUtil.getCurrentUser().getId()); + } + + @Override + public FileBox findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = SwOpLogType.SW, name = "修改文件,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateFileBoxVo vo) { + + FileBox data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("文件或文件夹不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(FileBox.class) + .set(data.getFileType() != FileBoxFileType.DIR, FileBox::getName, vo.getName()) + .set(FileBox::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR + : vo.getDescription()) + .eq(FileBox::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SwOpLogType.SW, name = "删除文件,ID:{}", params = { + "#ids"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + List delIds = new ArrayList<>(); + + for (String id : ids) { + + List childIds = recursionMappingService.getNodeChildIds(id, + ApplicationUtil.getBean(FileBoxNodeType.class)); + delIds.addAll(childIds); + } + + for (String id : ids) { + recursionMappingService.deleteNodeAndChildren(id, ApplicationUtil.getBean(FileBoxNodeType.class)); + } + + delIds.addAll(ids); + + Wrapper deleteWrapper = Wrappers.lambdaQuery(FileBox.class) + .in(FileBox::getId, delIds) + .eq(FileBox::getCreateById, SecurityUtil.getCurrentUser().getId()); + this.remove(deleteWrapper); + } + + @OpLog(type = SwOpLogType.SW, name = "创建文件夹,父级目录:{},文件夹名称:{}", params = { + "#vo.parentPath", "#vo.name"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void createDir(CreateFileBoxDirVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(FileBox.class) + .eq(FileBox::getName, vo.getName()).eq(FileBox::getFilePath, vo.getParentPath()) + .eq(FileBox::getCreateById, SecurityUtil.getCurrentUser().getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("文件夹名称重复,请重新输入!"); + } + FileBox dir = new FileBox(); + dir.setId(IdUtil.getId()); + dir.setName(vo.getName()); + dir.setFileType(FileBoxFileType.DIR); + dir.setFilePath(vo.getParentPath()); + dir.setDescription(StringPool.EMPTY_STR); + + this.save(dir); + + if ("/".equals(vo.getParentPath())) { + recursionMappingService.saveNode(dir.getId(), + ApplicationUtil.getBean(FileBoxNodeType.class)); + } else { + String path = vo.getParentPath().substring(0, vo.getParentPath().lastIndexOf("/") == 0 ? 1 : vo.getParentPath().lastIndexOf("/")); + String name = vo.getParentPath().substring(vo.getParentPath().lastIndexOf("/") + 1); + + Wrapper queryWrapper = Wrappers.lambdaQuery(FileBox.class) + .eq(FileBox::getName, name).eq(FileBox::getFilePath, path) + .eq(FileBox::getCreateById, SecurityUtil.getCurrentUser().getId()); + FileBox fileBox = this.getOne(queryWrapper); + if (fileBox == null) { + throw new DefaultClientException("父级目录不存在!"); + } + + List parentIds = recursionMappingService.getNodeParentIds(fileBox.getId(), + ApplicationUtil.getBean(FileBoxNodeType.class)); + parentIds.add(fileBox.getId()); + + recursionMappingService.saveNode(dir.getId(), + ApplicationUtil.getBean(FileBoxNodeType.class), parentIds); + } + } + + @OpLog(type = SwOpLogType.SW, name = "上传文件,父级目录:{},文件名称:{}", params = { + "#vo.path", "#vo.name"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void upload(UploadFileBoxVo vo) { + MultipartFile file = vo.getFile(); + String url = UploadUtil.upload(file); + + FileBox record = new FileBox(); + record.setId(IdUtil.getId()); + record.setName(file.getOriginalFilename()); + record.setUrl(url); + record.setContentType(file.getContentType()); + record.setFileType(FileBoxFileType.FILE); + record.setFileSize(FileUtil.readableFileSize(file.getSize())); + record.setFilePath(vo.getPath()); + record.setFileSuffix(FileUtil.getSuffix(file.getOriginalFilename())); + record.setDescription(StringPool.EMPTY_STR); + + this.save(record); + + if ("/".equals(vo.getPath())) { + recursionMappingService.saveNode(record.getId(), + ApplicationUtil.getBean(FileBoxNodeType.class)); + } else { + String path = vo.getPath().substring(0, vo.getPath().lastIndexOf("/") == 0 ? 1 : vo.getPath().lastIndexOf("/")); + String name = vo.getPath().substring(vo.getPath().lastIndexOf("/") + 1); + + Wrapper queryWrapper = Wrappers.lambdaQuery(FileBox.class) + .eq(FileBox::getName, name).eq(FileBox::getFilePath, path) + .eq(FileBox::getCreateById, SecurityUtil.getCurrentUser().getId()); + FileBox fileBox = this.getOne(queryWrapper); + if (fileBox == null) { + throw new DefaultClientException("父级目录不存在!"); + } + + List parentIds = recursionMappingService.getNodeParentIds(fileBox.getId(), + ApplicationUtil.getBean(FileBoxNodeType.class)); + parentIds.add(fileBox.getId()); + + recursionMappingService.saveNode(record.getId(), + ApplicationUtil.getBean(FileBoxNodeType.class), parentIds); + } + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OnlineExcelServiceImpl.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OnlineExcelServiceImpl.java new file mode 100644 index 0000000..22a4c25 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OnlineExcelServiceImpl.java @@ -0,0 +1,208 @@ +package com.lframework.xingyun.core.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.JsonUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.entity.OnlineExcel; +import com.lframework.xingyun.core.enums.SwOpLogType; +import com.lframework.xingyun.core.mappers.OnlineExcelMapper; +import com.lframework.xingyun.core.service.OnlineExcelService; +import com.lframework.xingyun.core.vo.sw.excel.BatchSendOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.CreateOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.QueryOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.SendOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.UpdateOnlineExcelContentVo; +import com.lframework.xingyun.core.vo.sw.excel.UpdateOnlineExcelVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class OnlineExcelServiceImpl extends + BaseMpServiceImpl implements OnlineExcelService { + + @Autowired + private UserService userService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryOnlineExcelVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryOnlineExcelVo vo) { + + return getBaseMapper().query(vo, SecurityUtil.getCurrentUser().getId()); + } + + @Override + public OnlineExcel findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = SwOpLogType.SW, name = "新增在线Excel,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateOnlineExcelVo vo) { + + OnlineExcel data = new OnlineExcel(); + data.setId(IdUtil.getId()); + data.setName(vo.getName()); + data.setContent(vo.getContent()); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SwOpLogType.SW, name = "修改在线Excel,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateOnlineExcelVo vo) { + + OnlineExcel data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("在线Excel不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(OnlineExcel.class) + .set(OnlineExcel::getName, vo.getName()).set(OnlineExcel::getAvailable, vo.getAvailable()) + .set(OnlineExcel::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(OnlineExcel::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SwOpLogType.SW, name = "修改在线Excel内容,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void updateContent(UpdateOnlineExcelContentVo vo) { + OnlineExcel data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("在线Excel不存在!"); + } + + Map content = JsonUtil.parseObject(data.getContent(), Map.class); + List sheets = JsonUtil.parseList(vo.getContent(), Map.class); + content.put("sheets", sheets); + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(OnlineExcel.class) + .set(OnlineExcel::getContent, JsonUtil.toJsonString(content)) + .eq(OnlineExcel::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SwOpLogType.SW, name = "发送Excel文件,发送方{}, 接收方{}", params = {"#sender", "#receiver"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void send(SendOnlineExcelVo vo) { + + OnlineExcel record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("Excel文件不存在!"); + } + + UserDto receiver = userService.findById(vo.getUserId()); + if (receiver == null) { + throw new DefaultClientException("接收方不存在!"); + } + + if (vo.getSelfSave()) { + record.setId(IdUtil.getId()); + record.setAvailable(Boolean.TRUE); + record.setCreateById(receiver.getId()); + record.setCreateBy(receiver.getName()); + this.save(record); + } else { + record.setCreateById(receiver.getId()); + record.setCreateBy(receiver.getName()); + record.setAvailable(Boolean.TRUE); + this.updateById(record); + } + + OpLogUtil.setVariable("sender", SecurityUtil.getCurrentUser().getId()); + OpLogUtil.setVariable("receiver", vo.getUserId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SwOpLogType.SW, name = "批量发送Excel文件,发送方{}, 接收方{}", params = {"#sender", + "#receiver"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchSend(BatchSendOnlineExcelVo vo) { + + UserDto receiver = userService.findById(vo.getUserId()); + if (receiver == null) { + throw new DefaultClientException("接收方不存在!"); + } + + for (String id : vo.getIds()) { + OnlineExcel record = this.getById(id); + if (record == null) { + throw new DefaultClientException("Excel文件不存在!"); + } + + if (vo.getSelfSave()) { + record.setId(IdUtil.getId()); + record.setCreateById(receiver.getId()); + record.setCreateBy(receiver.getName()); + record.setAvailable(Boolean.TRUE); + this.save(record); + } else { + record.setCreateById(receiver.getId()); + record.setCreateBy(receiver.getName()); + record.setAvailable(Boolean.TRUE); + this.updateById(record); + } + } + + OpLogUtil.setVariable("sender", SecurityUtil.getCurrentUser().getId()); + OpLogUtil.setVariable("receiver", vo.getUserId()); + OpLogUtil.setExtra(vo); + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OrderTimeLineServiceImpl.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OrderTimeLineServiceImpl.java new file mode 100644 index 0000000..38515eb --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/impl/OrderTimeLineServiceImpl.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.core.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.mappers.OrderTimeLineMapper; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author zmj + * @since 2022/8/10 + */ +@Service +public class OrderTimeLineServiceImpl extends BaseMpServiceImpl implements + OrderTimeLineService { + + @Cacheable(value = OrderTimeLine.CACHE_NAME, key = "@cacheVariables.tenantId() + #orderId", unless = "#result == null") + @Override + public List getByOrder(String orderId) { + super.cleanCaches(); + Wrapper queryWrapper = Wrappers.lambdaQuery(OrderTimeLine.class).eq(OrderTimeLine::getOrderId, orderId).orderByAsc(OrderTimeLine::getCreateTime); + + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByOrder(String orderId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(OrderTimeLine.class).eq(OrderTimeLine::getOrderId, orderId); + this.remove(deleteWrapper); + } + + @CacheEvict(value = OrderTimeLine.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + super.cleanCacheByKey(key); + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/DicCityMapper.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/DicCityMapper.java new file mode 100644 index 0000000..38b7909 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/DicCityMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.entity.DicCity; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-07 + */ +public interface DicCityMapper extends BaseMapper { + + /** + * 查询所有数据 + * + * @return + */ + List getAll(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + DicCityDto findById(String id); +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/FileBoxMapper.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/FileBoxMapper.java new file mode 100644 index 0000000..95ffe05 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/FileBoxMapper.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.core.entity.FileBox; +import com.lframework.xingyun.core.vo.sw.filebox.QueryFileBoxVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 收件收纳箱 Mapper 接口 + *

+ */ +public interface FileBoxMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryFileBoxVo vo, @Param("createById") String createById); +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OnlineExcelMapper.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OnlineExcelMapper.java new file mode 100644 index 0000000..4f97f1d --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OnlineExcelMapper.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.core.entity.OnlineExcel; +import com.lframework.xingyun.core.vo.sw.excel.QueryOnlineExcelVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 在线Excel Mapper 接口 + *

+ */ +public interface OnlineExcelMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryOnlineExcelVo vo, @Param("createById") String createById); +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OrderTimeLineMapper.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OrderTimeLineMapper.java new file mode 100644 index 0000000..1097fd5 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/mappers/OrderTimeLineMapper.java @@ -0,0 +1,12 @@ +package com.lframework.xingyun.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.core.entity.OrderTimeLine; + +/** + * @author zmj + * @since 2022/8/10 + */ +public interface OrderTimeLineMapper extends BaseMapper { + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/service/DicCityService.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/DicCityService.java new file mode 100644 index 0000000..3f25d1f --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/DicCityService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.core.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.entity.DicCity; +import java.util.List; + +public interface DicCityService extends BaseMpService { + + /** + * 查询所有数据 + * + * @return + */ + List getAll(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + DicCityDto findById(String id); + + /** + * 根据ID查询链路数据 + * + * @param id 末级ID + * @return 返回值顺序:省、市、区 + */ + List getChainById(String id); +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/service/FileBoxService.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/FileBoxService.java new file mode 100644 index 0000000..3eb3a87 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/FileBoxService.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.core.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.core.entity.FileBox; +import com.lframework.xingyun.core.vo.sw.filebox.CreateFileBoxDirVo; +import com.lframework.xingyun.core.vo.sw.filebox.QueryFileBoxVo; +import com.lframework.xingyun.core.vo.sw.filebox.UpdateFileBoxVo; +import com.lframework.xingyun.core.vo.sw.filebox.UploadFileBoxVo; +import java.util.List; + +/** + * 文件收纳箱 Service + */ +public interface FileBoxService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryFileBoxVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryFileBoxVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + FileBox findById(String id); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateFileBoxVo vo); + + + /** + * 批量删除 + * @param ids + */ + void batchDelete(List ids); + + /** + * 创建文件夹 + * @param vo + */ + void createDir(CreateFileBoxDirVo vo); + + /** + * 上传文件 + * @param vo + */ + void upload(UploadFileBoxVo vo); + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/service/OnlineExcelService.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/OnlineExcelService.java new file mode 100644 index 0000000..cfc6e45 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/OnlineExcelService.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.core.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.core.entity.OnlineExcel; +import com.lframework.xingyun.core.vo.sw.excel.BatchSendOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.CreateOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.QueryOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.SendOnlineExcelVo; +import com.lframework.xingyun.core.vo.sw.excel.UpdateOnlineExcelContentVo; +import com.lframework.xingyun.core.vo.sw.excel.UpdateOnlineExcelVo; +import java.util.List; + +/** + * 在线Excel Service + */ +public interface OnlineExcelService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryOnlineExcelVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryOnlineExcelVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + OnlineExcel findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateOnlineExcelVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateOnlineExcelVo vo); + + /** + * 修改内容 + * + * @param vo + */ + void updateContent(UpdateOnlineExcelContentVo vo); + + /** + * 发送 + * + * @param vo + */ + void send(SendOnlineExcelVo vo); + + /** + * 批量发送 + * + * @param vo + */ + void batchSend(BatchSendOnlineExcelVo vo); + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/service/OrderTimeLineService.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/OrderTimeLineService.java new file mode 100644 index 0000000..d107805 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/service/OrderTimeLineService.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.core.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import java.util.List; + +/** + * @author zmj + * @since 2022/8/10 + */ +public interface OrderTimeLineService extends BaseMpService { + + /** + * 根据订单查询 + * @param orderId + * @return + */ + List getByOrder(String orderId); + + /** + * 根据订单删除 + * @param orderId + */ + void deleteByOrder(String orderId); +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/utils/SplitNumberUtil.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/utils/SplitNumberUtil.java new file mode 100644 index 0000000..6119fa9 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/utils/SplitNumberUtil.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.core.utils; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +public class SplitNumberUtil { + + /** + * 将 totalNum 按照权重指标分摊 + * + * @param totalNum + * @param datas key:唯一标识 value:权重指标 + * @param precision 精度 + * @return + */ + public static Map split(Number totalNum, Map datas, + int precision) { + if (CollectionUtil.isEmpty(datas)) { + return null; + } + + if (precision < 0) { + throw new DefaultSysException("precision不允许小于0!"); + } + if (!NumberUtil.isNumberPrecision(totalNum, precision)) { + throw new DefaultSysException("totalNum的小数位数不允许大于 " + precision + "!"); + } + + Number totalWeight = datas.values().stream().reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + Map results = new HashMap<>(datas.size()); + Number remainNum = totalNum; + + int index = 0; + int dataSize = datas.size(); + for (Entry entry : datas.entrySet()) { + Object key = entry.getKey(); + Number val = entry.getValue(); + if (index == dataSize - 1) { + // 最后一行 + results.put(key, remainNum); + } else { + Number curNum = NumberUtil.getNumber(NumberUtil.mul(totalNum, + NumberUtil.equal(totalWeight, BigDecimal.ZERO) ? dataSize + : NumberUtil.div(val, totalWeight)), precision); + remainNum = NumberUtil.sub(remainNum, curNum); + if (NumberUtil.lt(remainNum, BigDecimal.ZERO)) { + curNum = NumberUtil.add(remainNum, curNum); + remainNum = BigDecimal.ZERO; + } + results.put(key, curNum); + } + } + + return results; + } +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/BatchSendOnlineExcelVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/BatchSendOnlineExcelVo.java new file mode 100644 index 0000000..dbd36bc --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/BatchSendOnlineExcelVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.core.vo.sw.excel; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchSendOnlineExcelVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotEmpty(message = "ID不能为空!") + private List ids; + + /** + * 用户ID + */ + @ApiModelProperty(value = "用户ID", required = true) + @NotBlank(message = "用户ID不能为空!") + private String userId; + + /** + * 是否留存副本 + */ + @ApiModelProperty(value = "是否留存副本", required = true) + @NotNull(message = "是否留存副本不能为空!") + @TypeMismatch(message = "是否留存副本格式错误!") + private Boolean selfSave; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/CreateOnlineExcelVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/CreateOnlineExcelVo.java new file mode 100644 index 0000000..0be8a4c --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/CreateOnlineExcelVo.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.core.vo.sw.excel; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateOnlineExcelVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 内容 + */ + @ApiModelProperty(value = "内容", required = true) + @NotBlank(message = "请输入内容!") + private String content; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/QueryOnlineExcelVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/QueryOnlineExcelVo.java new file mode 100644 index 0000000..2791baa --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/QueryOnlineExcelVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.core.vo.sw.excel; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryOnlineExcelVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + private Boolean available; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/SendOnlineExcelVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/SendOnlineExcelVo.java new file mode 100644 index 0000000..63e0d9d --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/SendOnlineExcelVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.core.vo.sw.excel; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class SendOnlineExcelVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 用户ID + */ + @ApiModelProperty(value = "用户ID", required = true) + @NotBlank(message = "用户ID不能为空!") + private String userId; + + /** + * 是否留存副本 + */ + @ApiModelProperty(value = "是否留存副本", required = true) + @NotNull(message = "是否留存副本不能为空!") + @TypeMismatch(message = "是否留存副本格式错误!") + private Boolean selfSave; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelContentVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelContentVo.java new file mode 100644 index 0000000..bd2ddfd --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelContentVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.core.vo.sw.excel; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateOnlineExcelContentVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 内容 + */ + @ApiModelProperty(value = "内容", required = true) + @NotBlank(message = "内容不能为空!") + private String content; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelVo.java new file mode 100644 index 0000000..0ed6037 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/excel/UpdateOnlineExcelVo.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.core.vo.sw.excel; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateOnlineExcelVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @TypeMismatch(message = "状态格式有误!") + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/CreateFileBoxDirVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/CreateFileBoxDirVo.java new file mode 100644 index 0000000..06adcb8 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/CreateFileBoxDirVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.core.vo.sw.filebox; + +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateFileBoxDirVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "父级目录", required = true) + @NotBlank(message = "父级目录不能为空!") + private String parentPath; + + @ApiModelProperty(value = "文件夹名称", required = true) + @Pattern(regexp = "^(?!^\\.)[^\\/:*?\"<>|\\s].*$", message = "文件夹名称不合法!") + @NotBlank(message = "文件夹名称不能为空!") + private String name; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/QueryFileBoxVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/QueryFileBoxVo.java new file mode 100644 index 0000000..d2a8086 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/QueryFileBoxVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.core.vo.sw.filebox; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryFileBoxVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + @ApiModelProperty("路径") + private String path; +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UpdateFileBoxVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UpdateFileBoxVo.java new file mode 100644 index 0000000..21e2e17 --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UpdateFileBoxVo.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.core.vo.sw.filebox; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateFileBoxVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UploadFileBoxVo.java b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UploadFileBoxVo.java new file mode 100644 index 0000000..a71f40e --- /dev/null +++ b/xingyun-core/src/main/java/com/lframework/xingyun/core/vo/sw/filebox/UploadFileBoxVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.core.vo.sw.filebox; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Data +public class UploadFileBoxVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 文件 + */ + @ApiModelProperty(value = "文件", required = true) + @NotNull(message = "文件不能为空!") + private MultipartFile file; + + @ApiModelProperty(value = "路径", required = true) + @NotBlank(message = "路径不能为空!") + private String path; +} diff --git a/xingyun-core/src/main/java/lombok.config b/xingyun-core/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-core/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-core/src/main/resources/mappers/DicCityMapper.xml b/xingyun-core/src/main/resources/mappers/DicCityMapper.xml new file mode 100644 index 0000000..5cadf0b --- /dev/null +++ b/xingyun-core/src/main/resources/mappers/DicCityMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + SELECT id, + code, + name, + parent_id, + level + FROM dic_city + + + + + + diff --git a/xingyun-core/src/main/resources/mappers/FileBoxMapper.xml b/xingyun-core/src/main/resources/mappers/FileBoxMapper.xml new file mode 100644 index 0000000..d571f69 --- /dev/null +++ b/xingyun-core/src/main/resources/mappers/FileBoxMapper.xml @@ -0,0 +1,24 @@ + + + + + + + + SELECT tb.* + FROM sw_file_box AS tb + + diff --git a/xingyun-core/src/main/resources/mappers/OnlineExcelMapper.xml b/xingyun-core/src/main/resources/mappers/OnlineExcelMapper.xml new file mode 100644 index 0000000..2466d18 --- /dev/null +++ b/xingyun-core/src/main/resources/mappers/OnlineExcelMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + SELECT tb.id, + tb.name, + tb.content, + tb.available, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sw_online_excel AS tb + + diff --git a/xingyun-sc/pom.xml b/xingyun-sc/pom.xml new file mode 100644 index 0000000..12fa213 --- /dev/null +++ b/xingyun-sc/pom.xml @@ -0,0 +1,26 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-sc + 【${project.artifactId}】仓库业务服务层 + + + + com.lframework + xingyun-core + + + + com.lframework + xingyun-basedata + + + diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetBo.java new file mode 100644 index 0000000..96daea1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetBo.java @@ -0,0 +1,376 @@ +package com.lframework.xingyun.sc.bo.logistics; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetFullDto; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetFullDto.DetailDto; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetLogisticsSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 物流单号 + */ + @ApiModelProperty("物流单号") + private String logisticsNo; + + /** + * 物流公司ID + */ + @ApiModelProperty("物流公司ID") + private String logisticsCompanyId; + + /** + * 寄件人姓名 + */ + @ApiModelProperty("寄件人姓名") + private String senderName; + + /** + * 寄件人联系电话 + */ + @ApiModelProperty("寄件人联系电话") + private String senderTelephone; + + /** + * 寄件人省 + */ + @ApiModelProperty("寄件人省") + private String senderProvinceId; + + /** + * 寄件人市 + */ + @ApiModelProperty("寄件人市") + private String senderCityId; + + /** + * 寄件人区 + */ + @ApiModelProperty("寄件人区") + private String senderDistrictId; + + /** + * 寄件人地区 + */ + @ApiModelProperty("寄件人地区") + private String senderCity; + + /** + * 寄件人地址 + */ + @ApiModelProperty("寄件人地址") + private String senderAddress; + + /** + * 收件人姓名 + */ + @ApiModelProperty("收件人姓名") + private String receiverName; + + /** + * 收件人联系电话 + */ + @ApiModelProperty("收件人联系电话") + private String receiverTelephone; + + /** + * 收件人省 + */ + @ApiModelProperty("收件人省") + private String receiverProvinceId; + + /** + * 收件人市 + */ + @ApiModelProperty("收件人市") + private String receiverCityId; + + /** + * 收件人区 + */ + @ApiModelProperty("收件人区") + private String receiverDistrictId; + + /** + * 收件人地区 + */ + @ApiModelProperty("收件人地区") + private String receiverCity; + + /** + * 收件人地址 + */ + @ApiModelProperty("收件人地址") + private String receiverAddress; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @EnumConvert + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 总重量 + */ + @ApiModelProperty("总重量") + private BigDecimal totalWeight; + + /** + * 总体积 + */ + @ApiModelProperty("总体积") + private BigDecimal totalVolume; + + /** + * 物流费 + */ + @ApiModelProperty("物流费") + private BigDecimal totalAmount; + + /** + * 发货人 + */ + @ApiModelProperty("发货人") + private String deliveryBy; + + /** + * 发货时间 + */ + @ApiModelProperty("发货时间") + private LocalDateTime deliveryTime; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + private LocalDateTime updateTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetLogisticsSheetBo() { + + } + + public GetLogisticsSheetBo(LogisticsSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(LogisticsSheetFullDto dto) { + + return super.convert(dto, GetLogisticsSheetBo::getDetails); + } + + @Override + protected void afterInit(LogisticsSheetFullDto dto) { + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(OrderDetailBo::new) + .collect(Collectors.toList()); + } + + if (StringUtil.isNotBlank(dto.getDeliveryBy())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto deliveryBy = userService.findById(dto.getDeliveryBy()); + this.deliveryBy = deliveryBy.getName(); + } + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List senderCitys = dicCityService.getChainById(senderDistrictId); + this.senderCity = senderCitys.stream().map(DicCityDto::getName).collect(Collectors.joining(StringPool.CITY_SPLIT)); + + List receiverCitys = dicCityService.getChainById(receiverDistrictId); + this.receiverCity = receiverCitys.stream().map(DicCityDto::getName).collect(Collectors.joining(StringPool.CITY_SPLIT)); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 物流单ID + */ + @ApiModelProperty("物流单ID") + private String sheetId; + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @EnumConvert + private Integer bizType; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 收货人ID + */ + @ApiModelProperty("收货人ID") + private String receiverId; + + /** + * 收货人姓名 + */ + @ApiModelProperty("收货人姓名") + private String receiverName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + public OrderDetailBo(LogisticsSheetFullDto.DetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(LogisticsSheetFullDto.DetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(DetailDto dto) { + if (dto.getBizType() == LogisticsSheetDetailBizType.SALE_OUT_SHEET) { + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean( + SaleOutSheetService.class); + SaleOutSheet saleOutSheet = saleOutSheetService.getById(dto.getBizId()); + this.bizCode = saleOutSheet.getCode(); + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(saleOutSheet.getScId()); + this.scId = sc.getId(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(saleOutSheet.getCustomerId()); + this.receiverId = customer.getId(); + this.receiverName = customer.getName(); + + this.createBy = saleOutSheet.getCreateBy(); + this.createTime = saleOutSheet.getCreateTime(); + } else if (dto.getBizType() == LogisticsSheetDetailBizType.RETAIL_OUT_SHEET) { + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailOutSheet retailOutSheet = retailOutSheetService.getById(dto.getBizId()); + this.bizCode = retailOutSheet.getCode(); + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(retailOutSheet.getScId()); + this.scId = sc.getId(); + this.scName = sc.getName(); + + if (StringUtil.isNotBlank(retailOutSheet.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(retailOutSheet.getMemberId()); + this.receiverId = member.getId(); + this.receiverName = member.getName(); + } + + this.createBy = retailOutSheet.getCreateBy(); + this.createTime = retailOutSheet.getCreateTime(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetDeliveryBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetDeliveryBo.java new file mode 100644 index 0000000..2ff90e3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/GetLogisticsSheetDeliveryBo.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.sc.bo.logistics; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class GetLogisticsSheetDeliveryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 物流单号 + */ + @ApiModelProperty("物流单号") + private String logisticsNo; + + /** + * 物流费 + */ + @ApiModelProperty("物流费") + private BigDecimal totalAmount; + + public GetLogisticsSheetDeliveryBo() { + + } + + public GetLogisticsSheetDeliveryBo(LogisticsSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(LogisticsSheet dto) { + + return super.convert(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBizOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBizOrderBo.java new file mode 100644 index 0000000..8615c16 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBizOrderBo.java @@ -0,0 +1,102 @@ +package com.lframework.xingyun.sc.bo.logistics; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetBizOrderDto; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryLogisticsSheetBizOrderBo extends BaseBo { + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @EnumConvert + private Integer bizType; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 收货人ID + */ + @ApiModelProperty("收货人ID") + private String receiverId; + + /** + * 收货人姓名 + */ + @ApiModelProperty("收货人姓名") + private String receiverName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + public QueryLogisticsSheetBizOrderBo() { + } + + public QueryLogisticsSheetBizOrderBo(LogisticsSheetBizOrderDto dto) { + super(dto); + } + + @Override + protected void afterInit(LogisticsSheetBizOrderDto dto) { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + if (dto.getBizType() == LogisticsSheetDetailBizType.SALE_OUT_SHEET) { + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getReceiverId()); + this.receiverName = customer.getName(); + } else if (dto.getBizType() == LogisticsSheetDetailBizType.RETAIL_OUT_SHEET) { + if (StringUtil.isNotBlank(dto.getReceiverId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getReceiverId()); + this.receiverName = member.getName(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBo.java new file mode 100644 index 0000000..4836976 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/logistics/QueryLogisticsSheetBo.java @@ -0,0 +1,124 @@ +package com.lframework.xingyun.sc.bo.logistics; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.service.logistics.LogisticsCompanyService; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryLogisticsSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 物流单号 + */ + @ApiModelProperty("物流单号") + private String logisticsNo; + + /** + * 物流公司名称 + */ + @ApiModelProperty("物流公司名称") + private String logisticsCompanyName; + + /** + * 总重量 + */ + @ApiModelProperty("总重量") + private BigDecimal totalWeight; + + /** + * 总体积 + */ + @ApiModelProperty("总体积") + private BigDecimal totalVolume; + + /** + * 物流费 + */ + @ApiModelProperty("物流费") + private BigDecimal totalAmount; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @EnumConvert + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + /** + * 发货人 + */ + @ApiModelProperty("发货人") + private String deliveryBy; + + /** + * 发货时间 + */ + @ApiModelProperty("发货时间") + private LocalDateTime deliveryTime; + + public QueryLogisticsSheetBo(LogisticsSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(LogisticsSheet dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(LogisticsSheet dto) { + LogisticsCompanyService logisticsCompanyService = ApplicationUtil.getBean( + LogisticsCompanyService.class); + LogisticsCompany logisticsCompany = logisticsCompanyService.findById( + dto.getLogisticsCompanyId()); + this.logisticsCompanyName = logisticsCompany.getName(); + + if (StringUtil.isNotBlank(dto.getDeliveryBy())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto deliveryBy = userService.findById(dto.getDeliveryBy()); + this.deliveryBy = deliveryBy.getName(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/paytype/OrderPayTypeBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/paytype/OrderPayTypeBo.java new file mode 100644 index 0000000..fb15317 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/paytype/OrderPayTypeBo.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.sc.bo.paytype; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class OrderPayTypeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String orderId; + + /** + * 支付方式ID + */ + @ApiModelProperty("支付方式ID") + private String payTypeId; + + /** + * 支付金额 + */ + @ApiModelProperty("支付金额") + private BigDecimal payAmount; + + /** + * 支付内容 + */ + @ApiModelProperty("支付内容") + private String text; + + @ApiModelProperty("是否记录内容") + private Boolean recText; + + public OrderPayTypeBo() { + } + + public OrderPayTypeBo(OrderPayType dto) { + super(dto); + } + + @Override + protected void afterInit(OrderPayType dto) { + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + PayType payType = payTypeService.findById(dto.getPayTypeId()); + this.recText = payType.getRecText(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/GetPurchaseOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/GetPurchaseOrderBo.java new file mode 100644 index 0000000..b4a564f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/GetPurchaseOrderBo.java @@ -0,0 +1,375 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetPurchaseOrderBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 采购人员编号 + */ + @ApiModelProperty("采购人员") + private String purchaserCode; + + /** + * 预计到货日期 + */ + @ApiModelProperty("预计到货日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate expectArriveDate; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetPurchaseOrderBo() { + + } + + public GetPurchaseOrderBo(PurchaseOrderFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseOrderFullDto dto) { + + return super.convert(dto, GetPurchaseOrderBo::getStatus, GetPurchaseOrderBo::getDetails); + } + + @Override + protected void afterInit(PurchaseOrderFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + this.supplierName = supplierService.findById(dto.getSupplierId()).getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + if (!StringUtil.isBlank(dto.getCreateById())) { + this.purchaserCode = userService.findById(dto.getCreateById()).getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new OrderDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer purchaseNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 含税成本价 + */ + @ApiModelProperty("含税成本价") + private BigDecimal taxCostPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public OrderDetailBo(String scId, PurchaseOrderFullDto.OrderDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + PurchaseOrderFullDto.OrderDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(PurchaseOrderFullDto.OrderDetailDto dto) { + + this.purchaseNum = dto.getOrderNum(); + this.purchasePrice = dto.getTaxPrice(); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId( + this.getProductId(), this.getScId()); + this.taxCostPrice = + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PrintPurchaseOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PrintPurchaseOrderBo.java new file mode 100644 index 0000000..b94fcbb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PrintPurchaseOrderBo.java @@ -0,0 +1,258 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintPurchaseOrderBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 预计到货日期 + */ + @ApiModelProperty("预计到货日期") + private String expectArriveDate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + /** + * 大写总采购金额 + */ + @ApiModelProperty("大写总采购金额") + private String bigTotalAmount; + + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + public PrintPurchaseOrderBo() { + + } + + public PrintPurchaseOrderBo(PurchaseOrderFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseOrderFullDto dto) { + + return super.convert(dto, PrintPurchaseOrderBo::getDetails); + } + + @Override + protected void afterInit(PurchaseOrderFullDto dto) { + + this.purchaserName = StringPool.EMPTY_STR; + this.expectArriveDate = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + if (dto.getExpectArriveDate() != null) { + this.expectArriveDate = DateUtil.formatDate(dto.getExpectArriveDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(OrderDetailBo::new).collect(Collectors.toList()); + } + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer purchaseNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal purchaseAmount; + + public OrderDetailBo(PurchaseOrderFullDto.OrderDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + PurchaseOrderFullDto.OrderDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(PurchaseOrderFullDto.OrderDetailDto dto) { + + this.purchaseNum = dto.getOrderNum(); + this.purchasePrice = dto.getTaxPrice(); + this.purchaseAmount = NumberUtil.mul(dto.getOrderNum(), dto.getTaxPrice()); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderSelectorBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderSelectorBo.java new file mode 100644 index 0000000..550f9b9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderSelectorBo.java @@ -0,0 +1,104 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class PurchaseOrderSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + public PurchaseOrderSelectorBo() { + + } + + public PurchaseOrderSelectorBo(PurchaseOrder dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseOrder dto) { + + return super.convert(dto, PurchaseOrderSelectorBo::getStatus); + } + + @Override + protected void afterInit(PurchaseOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderWithReceiveBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderWithReceiveBo.java new file mode 100644 index 0000000..8b48e19 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseOrderWithReceiveBo.java @@ -0,0 +1,296 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderWithReceiveDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PurchaseOrderWithReceiveBo extends BaseBo { + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public PurchaseOrderWithReceiveBo() { + + } + + public PurchaseOrderWithReceiveBo(PurchaseOrderWithReceiveDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseOrderWithReceiveDto dto) { + + return super.convert(dto, PurchaseOrderWithReceiveBo::getPurchaserId, + PurchaseOrderWithReceiveBo::getDetails); + } + + @Override + protected void afterInit(PurchaseOrderWithReceiveDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierName = supplier.getName(); + + if (!StringUtil.isBlank(dto.getPurchaserId())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto purchaser = userService.findById(dto.getPurchaserId()); + + this.purchaserId = purchaser.getId(); + this.purchaserName = purchaser.getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new DetailBo(this.scId, t)).collect(Collectors.toList()); + } + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer orderNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 剩余收货数量 + */ + @ApiModelProperty("剩余收货数量") + private Integer remainNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 含税成本价 + */ + @ApiModelProperty("含税成本价") + private BigDecimal taxCostPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public DetailBo() { + + } + + public DetailBo(String scId, PurchaseOrderWithReceiveDto.DetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + PurchaseOrderWithReceiveDto.DetailDto dto) { + + return this; + } + + @Override + public BaseBo convert( + PurchaseOrderWithReceiveDto.DetailDto dto, + SFunction... columns) { + + return this; + } + + @Override + protected void afterInit(PurchaseOrderWithReceiveDto.DetailDto dto) { + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.id = dto.getId(); + this.productId = product.getId(); + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + this.orderNum = dto.getOrderNum(); + this.purchasePrice = dto.getTaxPrice(); + this.remainNum = NumberUtil.sub(dto.getOrderNum(), dto.getReceiveNum()).intValue(); + this.isGift = dto.getIsGift(); + this.taxRate = dto.getTaxRate(); + this.description = dto.getDescription(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId( + this.getProductId(), this.getScId()); + this.taxCostPrice = + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseProductBo.java new file mode 100644 index 0000000..600154c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/PurchaseProductBo.java @@ -0,0 +1,131 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class PurchaseProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 是否多销售属性 + */ + @ApiModelProperty("是否多销售属性") + private Boolean multiSaleProp; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 含税成本价 + */ + @ApiModelProperty("含税成本价") + private BigDecimal taxCostPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public PurchaseProductBo(String scId, PurchaseProductDto dto) { + + this.scId = scId; + + this.init(dto); + } + + @Override + protected void afterInit(PurchaseProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.taxCostPrice = + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderBo.java new file mode 100644 index 0000000..72c6784 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderBo.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPurchaseOrderBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 预计到货日期 + */ + @ApiModelProperty("预计到货日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate expectArriveDate; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + public QueryPurchaseOrderBo(PurchaseOrder dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseOrder dto) { + + return super.convert(dto, QueryPurchaseOrderBo::getStatus); + } + + @Override + protected void afterInit(PurchaseOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderWithReceiveBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderWithReceiveBo.java new file mode 100644 index 0000000..0df43ba --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/QueryPurchaseOrderWithReceiveBo.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.sc.bo.purchase; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPurchaseOrderWithReceiveBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryPurchaseOrderWithReceiveBo(PurchaseOrder dto) { + + super(dto); + } + + @Override + protected void afterInit(PurchaseOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/config/GetPurchaseConfigBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/config/GetPurchaseConfigBo.java new file mode 100644 index 0000000..be676a0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/config/GetPurchaseConfigBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.bo.purchase.config; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetPurchaseConfigBo extends BaseBo { + + /** + * 采购收货单是否关联采购订单 + */ + @ApiModelProperty("采购收货单是否关联采购订单") + private Boolean receiveRequirePurchase; + + /** + * 采购收货单是否多次关联采购订单 + */ + @ApiModelProperty("采购收货单是否多次关联采购订单") + private Boolean receiveMultipleRelatePurchase; + + /** + * 采购退货单是否关联采购收货单 + */ + @ApiModelProperty("采购退货单是否关联采购收货单") + private Boolean purchaseReturnRequireReceive; + + /** + * 采购退货单是否多次关联采购收货单 + */ + @ApiModelProperty("采购退货单是否多次关联采购收货单") + private Boolean purchaseReturnMultipleRelateReceive; + + public GetPurchaseConfigBo() { + + } + + public GetPurchaseConfigBo(PurchaseConfig dto) { + + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetPaymentDateBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetPaymentDateBo.java new file mode 100644 index 0000000..cf8d4ab --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetPaymentDateBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDate; +import lombok.Data; + +@Data +public class GetPaymentDateBo extends BaseBo { + + /** + * 是否允许修改付款日期 + */ + @ApiModelProperty("是否允许修改付款日期") + private Boolean allowModify; + + /** + * 默认付款日期 + */ + @ApiModelProperty("默认付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + public GetPaymentDateBo() { + + } + + public GetPaymentDateBo(GetPaymentDateDto dto) { + + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetReceiveSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetReceiveSheetBo.java new file mode 100644 index 0000000..1d76c08 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/GetReceiveSheetBo.java @@ -0,0 +1,429 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderDetailService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetReceiveSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + /** + * 到货日期 + */ + @ApiModelProperty("到货日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate receiveDate; + + /** + * 采购订单ID + */ + @ApiModelProperty("采购订单ID") + private String purchaseOrderId; + + /** + * 采购订单号 + */ + @ApiModelProperty("采购订单号") + private String purchaseOrderCode; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetReceiveSheetBo() { + + } + + public GetReceiveSheetBo(ReceiveSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheetFullDto dto) { + + return super.convert(dto, GetReceiveSheetBo::getStatus, GetReceiveSheetBo::getSettleStatus, + GetReceiveSheetBo::getDetails); + } + + @Override + protected void afterInit(ReceiveSheetFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + this.supplierName = supplierService.findById(dto.getSupplierId()).getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean(PurchaseOrderService.class); + if (!StringUtil.isBlank(dto.getPurchaseOrderId())) { + PurchaseOrder purchaseOrder = purchaseOrderService.getById(dto.getPurchaseOrderId()); + this.purchaseOrderCode = purchaseOrder.getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new OrderDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer orderNum; + + /** + * 剩余收货数量 + */ + @ApiModelProperty("剩余收货数量") + private Integer remainNum; + + /** + * 收货数量 + */ + @ApiModelProperty("收货数量") + private Integer receiveNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 含税成本价 + */ + @ApiModelProperty("含税成本价") + private BigDecimal taxCostPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 采购订单明细ID + */ + @ApiModelProperty("采购订单明细ID") + private String purchaseOrderDetailId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public OrderDetailBo(String scId, ReceiveSheetFullDto.OrderDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + ReceiveSheetFullDto.OrderDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(ReceiveSheetFullDto.OrderDetailDto dto) { + + this.receiveNum = dto.getOrderNum(); + this.purchasePrice = dto.getTaxPrice(); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + if (!StringUtil.isBlank(dto.getPurchaseOrderDetailId())) { + PurchaseOrderDetailService purchaseOrderDetailService = ApplicationUtil.getBean( + PurchaseOrderDetailService.class); + PurchaseOrderDetail purchaseOrderDetail = purchaseOrderDetailService.getById( + dto.getPurchaseOrderDetailId()); + this.orderNum = purchaseOrderDetail.getOrderNum(); + this.remainNum = NumberUtil.sub(purchaseOrderDetail.getOrderNum(), + purchaseOrderDetail.getReceiveNum()) + .intValue(); + } + + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.taxCostPrice = + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/PrintReceiveSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/PrintReceiveSheetBo.java new file mode 100644 index 0000000..a41ae23 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/PrintReceiveSheetBo.java @@ -0,0 +1,283 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetFullDto; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintReceiveSheetBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private String paymentDate; + + /** + * 到货日期 + */ + @ApiModelProperty("到货日期") + private String receiveDate; + + /** + * 采购订单号 + */ + @ApiModelProperty("采购订单号") + private String purchaseOrderCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 大写总金额 + */ + @ApiModelProperty("大写总金额") + private String bigTotalAmount; + + + + public PrintReceiveSheetBo() { + + } + + public PrintReceiveSheetBo(ReceiveSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheetFullDto dto) { + + return super.convert(dto, PrintReceiveSheetBo::getDetails); + } + + @Override + protected void afterInit(ReceiveSheetFullDto dto) { + + this.purchaserName = StringPool.EMPTY_STR; + this.paymentDate = StringPool.EMPTY_STR; + this.receiveDate = StringPool.EMPTY_STR; + this.purchaseOrderCode = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean(PurchaseOrderService.class); + if (!StringUtil.isBlank(dto.getPurchaseOrderId())) { + PurchaseOrder purchaseOrder = purchaseOrderService.getById(dto.getPurchaseOrderId()); + this.purchaseOrderCode = purchaseOrder.getCode(); + } + + if (dto.getPaymentDate() != null) { + this.paymentDate = DateUtil.formatDate(dto.getPaymentDate()); + } + + if (dto.getReceiveDate() != null) { + this.receiveDate = DateUtil.formatDate(dto.getReceiveDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == ReceiveSheetStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(OrderDetailBo::new).collect(Collectors.toList()); + } + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 收货数量 + */ + @ApiModelProperty("收货数量") + private Integer receiveNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 收货金额 + */ + @ApiModelProperty("收货金额") + private BigDecimal receiveAmount; + + public OrderDetailBo(ReceiveSheetFullDto.OrderDetailDto dto) { + + this.init(dto); + } + + @Override + public BaseBo convert( + ReceiveSheetFullDto.OrderDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(ReceiveSheetFullDto.OrderDetailDto dto) { + + this.receiveNum = dto.getOrderNum(); + this.purchasePrice = dto.getTaxPrice(); + this.receiveAmount = NumberUtil.mul(dto.getOrderNum(), dto.getTaxPrice()); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetBo.java new file mode 100644 index 0000000..2bd6382 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetBo.java @@ -0,0 +1,197 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryReceiveSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 到货日期 + */ + @ApiModelProperty("到货日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate receiveDate; + + /** + * 采购订单ID + */ + @ApiModelProperty("采购订单ID") + private String purchaseOrderId; + + /** + * 采购订单号 + */ + @ApiModelProperty("采购订单号") + private String purchaseOrderCode; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryReceiveSheetBo(ReceiveSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheet dto) { + + return super.convert(dto, QueryReceiveSheetBo::getStatus, QueryReceiveSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(ReceiveSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + if (!StringUtil.isBlank(dto.getPurchaseOrderId())) { + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseOrder purchaseOrder = purchaseOrderService.getById(dto.getPurchaseOrderId()); + this.purchaseOrderCode = purchaseOrder.getCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetWithReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetWithReturnBo.java new file mode 100644 index 0000000..b3223f3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/QueryReceiveSheetWithReturnBo.java @@ -0,0 +1,96 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryReceiveSheetWithReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryReceiveSheetWithReturnBo() { + + } + + public QueryReceiveSheetWithReturnBo(ReceiveSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheet dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(ReceiveSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetSelectorBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetSelectorBo.java new file mode 100644 index 0000000..9275a96 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetSelectorBo.java @@ -0,0 +1,104 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class ReceiveSheetSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + public ReceiveSheetSelectorBo() { + + } + + public ReceiveSheetSelectorBo(ReceiveSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheet dto) { + + return super.convert(dto, ReceiveSheetSelectorBo::getStatus); + } + + @Override + protected void afterInit(ReceiveSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetWithReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetWithReturnBo.java new file mode 100644 index 0000000..bfdd51f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/receive/ReceiveSheetWithReturnBo.java @@ -0,0 +1,294 @@ +package com.lframework.xingyun.sc.bo.purchase.receive; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class ReceiveSheetWithReturnBo extends BaseBo { + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public ReceiveSheetWithReturnBo() { + + } + + public ReceiveSheetWithReturnBo(ReceiveSheetWithReturnDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheetWithReturnDto dto) { + + return super.convert(dto, ReceiveSheetWithReturnBo::getPurchaserId, + ReceiveSheetWithReturnBo::getDetails); + } + + @Override + protected void afterInit(ReceiveSheetWithReturnDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierName = supplier.getName(); + + if (!StringUtil.isBlank(dto.getPurchaserId())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto purchaser = userService.findById(dto.getPurchaserId()); + + this.purchaserId = purchaser.getId(); + this.purchaserName = purchaser.getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new DetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 收货数量 + */ + @ApiModelProperty("收货数量") + private Integer receiveNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 含税成本价 + */ + @ApiModelProperty("含税成本价") + private BigDecimal taxCostPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 剩余退货数量 + */ + @ApiModelProperty("剩余退货数量") + private Integer remainNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public DetailBo(String scId, ReceiveSheetWithReturnDto.DetailDto dto) { + + this.scId = scId; + + this.init(dto); + } + + @Override + public BaseBo convert( + ReceiveSheetWithReturnDto.DetailDto dto) { + + return this; + } + + @Override + public BaseBo convert( + ReceiveSheetWithReturnDto.DetailDto dto, + SFunction... columns) { + + return this; + } + + @Override + protected void afterInit(ReceiveSheetWithReturnDto.DetailDto dto) { + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.id = dto.getId(); + this.productId = product.getId(); + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + this.receiveNum = dto.getOrderNum(); + this.purchasePrice = dto.getTaxPrice(); + this.remainNum = NumberUtil.sub(dto.getOrderNum(), dto.getReturnNum()).intValue(); + this.isGift = dto.getIsGift(); + this.taxRate = dto.getTaxRate(); + this.description = dto.getDescription(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.taxCostPrice = + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/GetPurchaseReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/GetPurchaseReturnBo.java new file mode 100644 index 0000000..e1ef7f6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/GetPurchaseReturnBo.java @@ -0,0 +1,418 @@ +package com.lframework.xingyun.sc.bo.purchase.returned; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.dto.purchase.returned.PurchaseReturnFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetDetailService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetPurchaseReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + /** + * 采购收货单ID + */ + @ApiModelProperty("采购收货单ID") + private String receiveSheetId; + + /** + * 采购收货单号 + */ + @ApiModelProperty("采购收货单号") + private String receiveSheetCode; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetPurchaseReturnBo(PurchaseReturnFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseReturnFullDto dto) { + + return super.convert(dto, GetPurchaseReturnBo::getStatus, GetPurchaseReturnBo::getSettleStatus, + GetPurchaseReturnBo::getDetails); + } + + @Override + protected void afterInit(PurchaseReturnFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + this.supplierName = supplierService.findById(dto.getSupplierId()).getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + if (!StringUtil.isBlank(dto.getReceiveSheetId())) { + ReceiveSheet receiveSheet = receiveSheetService.getById(dto.getReceiveSheetId()); + this.receiveSheetCode = receiveSheet.getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new ReturnDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class ReturnDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 收货数量 + */ + @ApiModelProperty("收货数量") + private Integer receiveNum; + + /** + * 剩余退货数量 + */ + @ApiModelProperty("剩余退货数量") + private Integer remainNum; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 含税成本价 + */ + @ApiModelProperty("含税成本价") + private BigDecimal taxCostPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 采购收货单明细ID + */ + @ApiModelProperty("采购收货单明细ID") + private String receiveSheetDetailId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public ReturnDetailBo(String scId, PurchaseReturnFullDto.ReturnDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + PurchaseReturnFullDto.ReturnDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(PurchaseReturnFullDto.ReturnDetailDto dto) { + + this.returnNum = dto.getReturnNum(); + this.purchasePrice = dto.getTaxPrice(); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + if (!StringUtil.isBlank(dto.getReceiveSheetDetailId())) { + ReceiveSheetDetailService receiveSheetDetailService = ApplicationUtil.getBean( + ReceiveSheetDetailService.class); + ReceiveSheetDetail receiveSheetDetailDto = receiveSheetDetailService.getById( + dto.getReceiveSheetDetailId()); + this.receiveNum = receiveSheetDetailDto.getOrderNum(); + this.remainNum = NumberUtil.sub(receiveSheetDetailDto.getOrderNum(), + receiveSheetDetailDto.getReturnNum()).intValue(); + } + + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.taxCostPrice = + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/PrintPurchaseReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/PrintPurchaseReturnBo.java new file mode 100644 index 0000000..053839f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/PrintPurchaseReturnBo.java @@ -0,0 +1,283 @@ +package com.lframework.xingyun.sc.bo.purchase.returned; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.dto.purchase.returned.PurchaseReturnFullDto; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.enums.PurchaseReturnStatus; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintPurchaseReturnBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private String paymentDate; + + /** + * 采购收货单号 + */ + @ApiModelProperty("采购收货单号") + private String receiveSheetCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + /** + * 商品数量 + */ + @ApiModelProperty("商品数量") + private Integer totalNum; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal totalAmount; + + /** + * 大写总退货金额 + */ + @ApiModelProperty("大写总退货金额") + private String bigTotalAmount; + + + + + public PrintPurchaseReturnBo(PurchaseReturnFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseReturnFullDto dto) { + + return super.convert(dto, PrintPurchaseReturnBo::getDetails); + } + + @Override + protected void afterInit(PurchaseReturnFullDto dto) { + + this.purchaserName = StringPool.EMPTY_STR; + this.paymentDate = StringPool.EMPTY_STR; + this.receiveSheetCode = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + if (!StringUtil.isBlank(dto.getReceiveSheetId())) { + ReceiveSheet receiveSheet = receiveSheetService.getById(dto.getReceiveSheetId()); + this.receiveSheetCode = receiveSheet.getCode(); + } + + if (dto.getPaymentDate() != null) { + this.paymentDate = DateUtil.formatDate(dto.getPaymentDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == PurchaseReturnStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(ReturnDetailBo::new) + .collect(Collectors.toList()); + } + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class ReturnDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal returnAmount; + + public ReturnDetailBo(PurchaseReturnFullDto.ReturnDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + PurchaseReturnFullDto.ReturnDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(PurchaseReturnFullDto.ReturnDetailDto dto) { + + this.returnNum = dto.getReturnNum(); + this.purchasePrice = dto.getTaxPrice(); + this.returnAmount = NumberUtil.mul(dto.getReturnNum(), dto.getTaxPrice()); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseProductDto product = purchaseOrderService.getPurchaseById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/QueryPurchaseReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/QueryPurchaseReturnBo.java new file mode 100644 index 0000000..68bca28 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/purchase/returned/QueryPurchaseReturnBo.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.sc.bo.purchase.returned; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPurchaseReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ApiModelProperty("采购员姓名") + private String purchaserName; + + /** + * 采购收货单ID + */ + @ApiModelProperty("采购收货单ID") + private String receiveSheetId; + + /** + * 采购收货单号 + */ + @ApiModelProperty("采购收货单号") + private String receiveSheetCode; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 采购金额 + */ + @ApiModelProperty("采购金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryPurchaseReturnBo(PurchaseReturn dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseReturn dto) { + + return super.convert(dto, QueryPurchaseReturnBo::getStatus, QueryPurchaseReturnBo::getSettleStatus); + } + + @Override + protected void afterInit(PurchaseReturn dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + this.purchaserName = userService.findById(dto.getPurchaserId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + if (!StringUtil.isBlank(dto.getReceiveSheetId())) { + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + ReceiveSheet receiveSheet = receiveSheetService.getById(dto.getReceiveSheetId()); + this.receiveSheetCode = receiveSheet.getCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/RetailProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/RetailProductBo.java new file mode 100644 index 0000000..52b29ca --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/RetailProductBo.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.sc.bo.retail; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class RetailProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 是否多销售属性 + */ + @ApiModelProperty("是否多销售属性") + private Boolean multiSaleProp; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 零售价 + */ + @ApiModelProperty("零售价") + private BigDecimal retailPrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public RetailProductBo(String scId, RetailProductDto dto) { + + this.scId = scId; + + this.init(dto); + } + + @Override + protected void afterInit(RetailProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/config/GetRetailConfigBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/config/GetRetailConfigBo.java new file mode 100644 index 0000000..f324094 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/config/GetRetailConfigBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.sc.bo.retail.config; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.RetailConfig; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetRetailConfigBo extends BaseBo { + + /** + * 零售出库单上的会员是否必填 + */ + @ApiModelProperty("零售出库单上的会员是否必填") + private Boolean retailOutSheetRequireMember; + + /** + * 零售退货单上的会员是否必填 + */ + @ApiModelProperty("零售退货单上的会员是否必填") + private Boolean retailReturnRequireMember; + + /** + * 零售退货单是否关联零售出库单 + */ + @ApiModelProperty("零售退货单是否关联零售出库单") + private Boolean retailReturnRequireOutStock; + + /** + * 零售退货单是否多次关联零售出库单 + */ + @ApiModelProperty("零售退货单是否多次关联零售出库单") + private Boolean retailReturnMultipleRelateOutStock; + + /** + * 零售出库单是否需要发货 + */ + @ApiModelProperty("零售出库单是否需要发货") + private Boolean retailOutSheetRequireLogistics; + + public GetRetailConfigBo() { + + } + + public GetRetailConfigBo(RetailConfig dto) { + + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/GetRetailOutSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/GetRetailOutSheetBo.java new file mode 100644 index 0000000..b4d5a4d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/GetRetailOutSheetBo.java @@ -0,0 +1,420 @@ +package com.lframework.xingyun.sc.bo.retail.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetRetailOutSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 会员名称 + */ + @ApiModelProperty("会员名称") + private String memberName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员编号 + */ + @ApiModelProperty("销售员编号") + private String salerCode; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetRetailOutSheetBo() { + + } + + public GetRetailOutSheetBo(RetailOutSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailOutSheetFullDto dto) { + + return super.convert(dto, GetRetailOutSheetBo::getStatus, GetRetailOutSheetBo::getSettleStatus, + GetRetailOutSheetBo::getDetails); + } + + @Override + protected void afterInit(RetailOutSheetFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + this.memberName = memberService.findById(dto.getMemberId()).getName(); + } + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + if (!StringUtil.isBlank(dto.getCreateById())) { + this.salerCode = userService.findById(dto.getCreateById()).getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new OrderDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 组合商品ID + */ + @ApiModelProperty("组合商品ID") + private String mainProductId; + + /** + * 组合商品名称 + */ + @ApiModelProperty("组合商品名称") + private String mainProductName; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer orderNum; + + /** + * 剩余出库数量 + */ + @ApiModelProperty("剩余出库数量") + private Integer remainNum; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal retailPrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public OrderDetailBo(String scId, RetailOutSheetFullDto.SheetDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + RetailOutSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(RetailOutSheetFullDto.SheetDetailDto dto) { + + this.outNum = dto.getOrderNum(); + this.taxPrice = dto.getTaxPrice(); + this.retailPrice = dto.getOriPrice(); + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailProductDto product = retailOutSheetService.getRetailById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId( + this.getProductId(), this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + + if (StringUtil.isNotBlank(dto.getMainProductId())) { + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product mainProduct = productService.findById(dto.getMainProductId()); + this.mainProductId = dto.getMainProductId(); + this.mainProductName = mainProduct.getName(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/PrintRetailOutSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/PrintRetailOutSheetBo.java new file mode 100644 index 0000000..33f2769 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/PrintRetailOutSheetBo.java @@ -0,0 +1,259 @@ +package com.lframework.xingyun.sc.bo.retail.out; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetFullDto; +import com.lframework.xingyun.sc.enums.RetailOutSheetStatus; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintRetailOutSheetBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 会员编号 + */ + @ApiModelProperty("会员编号") + private String memberCode; + + /** + * 会员名称 + */ + @ApiModelProperty("会员名称") + private String memberName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private String paymentDate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + + /** + * 商品数量 + */ + @ApiModelProperty("商品数量") + private Integer totalNum; + + /** + * 出库总金额 + */ + @ApiModelProperty("出库总金额") + private BigDecimal totalAmount; + + /** + * 大写合计总金额 + */ + @ApiModelProperty("大写合计总金额") + private String bigTotalAmount; + + public PrintRetailOutSheetBo() { + + } + + public PrintRetailOutSheetBo(RetailOutSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailOutSheetFullDto dto) { + + return super.convert(dto, PrintRetailOutSheetBo::getDetails); + } + + @Override + protected void afterInit(RetailOutSheetFullDto dto) { + + this.salerName = StringPool.EMPTY_STR; + this.paymentDate = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + this.memberCode = member.getCode(); + this.memberName = member.getName(); + } + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (dto.getPaymentDate() != null) { + this.paymentDate = DateUtil.formatDate(dto.getPaymentDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(OrderDetailBo::new).collect(Collectors.toList()); + } + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 出库金额 + */ + @ApiModelProperty("出库金额") + private BigDecimal outAmount; + + public OrderDetailBo(RetailOutSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + RetailOutSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(RetailOutSheetFullDto.SheetDetailDto dto) { + + this.outNum = dto.getOrderNum(); + this.taxPrice = dto.getTaxPrice(); + this.outAmount = NumberUtil.mul(dto.getTaxPrice(), dto.getOrderNum()); + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailProductDto product = retailOutSheetService.getRetailById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetBo.java new file mode 100644 index 0000000..17f855c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetBo.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.sc.bo.retail.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryRetailOutSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 会员编号 + */ + @ApiModelProperty("会员编号") + private String memberCode; + + /** + * 会员名称 + */ + @ApiModelProperty("会员名称") + private String memberName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryRetailOutSheetBo(RetailOutSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailOutSheet dto) { + + return super.convert(dto, QueryRetailOutSheetBo::getStatus, QueryRetailOutSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(RetailOutSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + this.memberCode = member.getCode(); + this.memberName = member.getName(); + } + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetWithReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetWithReturnBo.java new file mode 100644 index 0000000..84b0638 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/QueryRetailOutSheetWithReturnBo.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.sc.bo.retail.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryRetailOutSheetWithReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 会员编号 + */ + @ApiModelProperty("会员编号") + private String memberCode; + + /** + * 会员名称 + */ + @ApiModelProperty("会员名称") + private String memberName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryRetailOutSheetWithReturnBo() { + + } + + public QueryRetailOutSheetWithReturnBo(RetailOutSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailOutSheet dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(RetailOutSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + this.memberCode = member.getCode(); + this.memberName = member.getName(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/RetailOutSheetWithReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/RetailOutSheetWithReturnBo.java new file mode 100644 index 0000000..2fab05a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/out/RetailOutSheetWithReturnBo.java @@ -0,0 +1,299 @@ +package com.lframework.xingyun.sc.bo.retail.out; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class RetailOutSheetWithReturnBo extends BaseBo { + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 会员名称 + */ + @ApiModelProperty("会员名称") + private String memberName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public RetailOutSheetWithReturnBo() { + + } + + public RetailOutSheetWithReturnBo(RetailOutSheetWithReturnDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailOutSheetWithReturnDto dto) { + + return super.convert(dto, RetailOutSheetWithReturnBo::getSalerId, + RetailOutSheetWithReturnBo::getDetails); + } + + @Override + protected void afterInit(RetailOutSheetWithReturnDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + this.memberName = member.getName(); + } + + if (!StringUtil.isBlank(dto.getSalerId())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = userService.findById(dto.getSalerId()); + + this.salerId = saler.getId(); + this.salerName = saler.getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new DetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal retailPrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 剩余退货数量 + */ + @ApiModelProperty("剩余退货数量") + private Integer remainNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public DetailBo(String scId, RetailOutSheetWithReturnDto.SheetDetailDto dto) { + + this.scId = scId; + + this.init(dto); + } + + @Override + public BaseBo convert( + RetailOutSheetWithReturnDto.SheetDetailDto dto) { + + return this; + } + + @Override + public BaseBo convert( + RetailOutSheetWithReturnDto.SheetDetailDto dto, SFunction... columns) { + + return this; + } + + @Override + protected void afterInit(RetailOutSheetWithReturnDto.SheetDetailDto dto) { + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailProductDto product = retailOutSheetService.getRetailById(dto.getProductId()); + + this.id = dto.getId(); + this.productId = product.getId(); + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + this.outNum = dto.getOrderNum(); + this.retailPrice = dto.getOriPrice(); + this.taxPrice = dto.getTaxPrice(); + this.discountRate = dto.getDiscountRate(); + this.remainNum = NumberUtil.sub(dto.getOrderNum(), dto.getReturnNum()).intValue(); + this.isGift = dto.getIsGift(); + this.taxRate = dto.getTaxRate(); + this.description = dto.getDescription(); + + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/GetRetailReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/GetRetailReturnBo.java new file mode 100644 index 0000000..7f18a9a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/GetRetailReturnBo.java @@ -0,0 +1,412 @@ +package com.lframework.xingyun.sc.bo.retail.returned; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetDetailLotDto; +import com.lframework.xingyun.sc.dto.retail.returned.RetailReturnFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetRetailReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String memberId; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String memberName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + /** + * 销售出库单ID + */ + @ApiModelProperty("销售出库单ID") + private String outSheetId; + + /** + * 销售出库单号 + */ + @ApiModelProperty("销售出库单号") + private String outSheetCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetRetailReturnBo(RetailReturnFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailReturnFullDto dto) { + + return super.convert(dto, GetRetailReturnBo::getStatus, GetRetailReturnBo::getSettleStatus, + GetRetailReturnBo::getDetails); + } + + @Override + protected void afterInit(RetailReturnFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + this.memberName = memberService.findById(dto.getMemberId()).getName(); + } + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + if (!StringUtil.isBlank(dto.getOutSheetId())) { + RetailOutSheet outSheet = retailOutSheetService.getById(dto.getOutSheetId()); + this.outSheetCode = outSheet.getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new ReturnDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class ReturnDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 剩余退货数量 + */ + @ApiModelProperty("剩余退货数量") + private Integer remainNum; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal retailPrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 销售出库单明细ID + */ + @ApiModelProperty("销售出库单明细ID") + private String outSheetDetailId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public ReturnDetailBo(String scId, RetailReturnFullDto.ReturnDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + RetailReturnFullDto.ReturnDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(RetailReturnFullDto.ReturnDetailDto dto) { + + this.returnNum = dto.getReturnNum(); + this.retailPrice = dto.getTaxPrice(); + this.taxPrice = dto.getTaxPrice(); + this.discountRate = dto.getDiscountRate(); + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailProductDto product = retailOutSheetService.getRetailById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + if (!StringUtil.isBlank(dto.getOutSheetDetailId())) { + RetailOutSheetDetailLotService receiveSheetDetailService = ApplicationUtil.getBean( + RetailOutSheetDetailLotService.class); + RetailOutSheetDetailLotDto outSheetDetail = receiveSheetDetailService.findById( + dto.getOutSheetDetailId()); + this.outNum = outSheetDetail.getOrderNum(); + this.remainNum = NumberUtil.sub(outSheetDetail.getOrderNum(), + outSheetDetail.getReturnNum()).intValue(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/PrintRetailReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/PrintRetailReturnBo.java new file mode 100644 index 0000000..c408100 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/PrintRetailReturnBo.java @@ -0,0 +1,272 @@ +package com.lframework.xingyun.sc.bo.retail.returned; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.returned.RetailReturnFullDto; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.enums.RetailReturnStatus; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintRetailReturnBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String memberCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String memberName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private String paymentDate; + + /** + * 销售出库单号 + */ + @ApiModelProperty("销售出库单号") + private String outSheetCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + + /** + * 商品数量 + */ + @ApiModelProperty("商品数量") + private Integer totalNum; + + /** + * 退货总金额 + */ + @ApiModelProperty("退货总金额") + private BigDecimal totalAmount; + + + /** + * 大写合计总金额 + */ + @ApiModelProperty("大写合计总金额") + private String bigTotalAmount; + + public PrintRetailReturnBo(RetailReturnFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailReturnFullDto dto) { + + return super.convert(dto, PrintRetailReturnBo::getDetails); + } + + @Override + protected void afterInit(RetailReturnFullDto dto) { + + this.salerName = StringPool.EMPTY_STR; + this.paymentDate = StringPool.EMPTY_STR; + this.outSheetCode = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + this.memberCode = member.getCode(); + this.memberName = member.getName(); + } + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + if (!StringUtil.isBlank(dto.getOutSheetId())) { + RetailOutSheet outSheet = retailOutSheetService.getById(dto.getOutSheetId()); + this.outSheetCode = outSheet.getCode(); + } + + if (dto.getPaymentDate() != null) { + this.paymentDate = DateUtil.formatDate(dto.getPaymentDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == RetailReturnStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(ReturnDetailBo::new) + .collect(Collectors.toList()); + } + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class ReturnDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal returnAmount; + + public ReturnDetailBo(RetailReturnFullDto.ReturnDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + RetailReturnFullDto.ReturnDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(RetailReturnFullDto.ReturnDetailDto dto) { + + this.returnNum = dto.getReturnNum(); + this.taxPrice = dto.getTaxPrice(); + this.returnAmount = NumberUtil.mul(dto.getTaxPrice(), dto.getReturnNum()); + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailProductDto product = retailOutSheetService.getRetailById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/QueryRetailReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/QueryRetailReturnBo.java new file mode 100644 index 0000000..a0db161 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/retail/returned/QueryRetailReturnBo.java @@ -0,0 +1,191 @@ +package com.lframework.xingyun.sc.bo.retail.returned; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryRetailReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 会员编号 + */ + @ApiModelProperty("会员编号") + private String memberCode; + + /** + * 会员名称 + */ + @ApiModelProperty("会员名称") + private String memberName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 销售出库单ID + */ + @ApiModelProperty("销售出库单ID") + private String outSheetId; + + /** + * 销售出库单号 + */ + @ApiModelProperty("销售出库单号") + private String outSheetCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryRetailReturnBo(RetailReturn dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailReturn dto) { + + return super.convert(dto, QueryRetailReturnBo::getStatus, QueryRetailReturnBo::getSettleStatus); + } + + @Override + protected void afterInit(RetailReturn dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + if (!StringUtil.isBlank(dto.getMemberId())) { + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + this.memberCode = member.getCode(); + this.memberName = member.getName(); + } + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + if (!StringUtil.isBlank(dto.getOutSheetId())) { + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailOutSheet outSheet = retailOutSheetService.getById(dto.getOutSheetId()); + this.outSheetCode = outSheet.getCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/GetSaleOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/GetSaleOrderBo.java new file mode 100644 index 0000000..e3d0688 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/GetSaleOrderBo.java @@ -0,0 +1,390 @@ +package com.lframework.xingyun.sc.bo.sale; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSaleOrderBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 销售员编号 + */ + @ApiModelProperty("销售员编号") + private String salerCode; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetSaleOrderBo() { + + } + + public GetSaleOrderBo(SaleOrderFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOrderFullDto dto) { + + return super.convert(dto, GetSaleOrderBo::getStatus, GetSaleOrderBo::getDetails); + } + + @Override + protected void afterInit(SaleOrderFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + this.customerName = customerService.findById(dto.getCustomerId()).getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (!StringUtil.isBlank(dto.getCreateById())) { + this.salerCode = userService.findById(dto.getCreateById()).getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new OrderDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 组合商品ID + */ + @ApiModelProperty("组合商品ID") + private String mainProductId; + + /** + * 组合商品名称 + */ + @ApiModelProperty("组合商品名称") + private String mainProductName; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer orderNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal oriPrice; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + @ApiModelProperty("折扣(%)") + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + public OrderDetailBo(String scId, SaleOrderFullDto.OrderDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert(SaleOrderFullDto.OrderDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleOrderFullDto.OrderDetailDto dto) { + + this.orderNum = dto.getOrderNum(); + this.oriPrice = dto.getOriPrice(); + this.taxPrice = dto.getTaxPrice(); + this.discountRate = dto.getDiscountRate(); + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId( + this.getProductId(), this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + + if (StringUtil.isNotBlank(dto.getMainProductId())) { + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product mainProduct = productService.findById(dto.getMainProductId()); + this.mainProductId = dto.getMainProductId(); + this.mainProductName = mainProduct.getName(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/PrintSaleOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/PrintSaleOrderBo.java new file mode 100644 index 0000000..9616127 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/PrintSaleOrderBo.java @@ -0,0 +1,249 @@ +package com.lframework.xingyun.sc.bo.sale; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.enums.SaleOrderStatus; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +public class PrintSaleOrderBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + /** + * 大写中文总合计金额 + */ + @ApiModelProperty("大写中文总合计金额") + private String bigTotalAmount; + + /** + * 商品数量 + */ + @ApiModelProperty("商品数量") + private Integer totalNum; + + /** + * 销售总金额 + */ + @ApiModelProperty("销售总金额") + private BigDecimal totalAmount; + + + + public PrintSaleOrderBo() { + + } + + public PrintSaleOrderBo(SaleOrderFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOrderFullDto dto) { + + return super.convert(dto, PrintSaleOrderBo::getDetails); + } + + @Override + protected void afterInit(SaleOrderFullDto dto) { + + this.salerName = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == SaleOrderStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(OrderDetailBo::new).collect(Collectors.toList()); + } + + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + this.totalNum = dto.getTotalNum(); + this.totalAmount = dto.getTotalAmount(); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer orderNum; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal orderAmount; + + public OrderDetailBo(SaleOrderFullDto.OrderDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOrderFullDto.OrderDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleOrderFullDto.OrderDetailDto dto) { + + this.orderNum = dto.getOrderNum(); + this.taxPrice = dto.getTaxPrice(); + this.orderAmount = NumberUtil.mul(dto.getOrderNum(), dto.getTaxPrice()); + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderBo.java new file mode 100644 index 0000000..f73c042 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderBo.java @@ -0,0 +1,161 @@ +package com.lframework.xingyun.sc.bo.sale; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOrderBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + public QuerySaleOrderBo(SaleOrder dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOrder dto) { + + return super.convert(dto, QuerySaleOrderBo::getStatus); + } + + @Override + protected void afterInit(SaleOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderWithOutBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderWithOutBo.java new file mode 100644 index 0000000..d2453ff --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/QuerySaleOrderWithOutBo.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.sc.bo.sale; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOrder; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOrderWithOutBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QuerySaleOrderWithOutBo(SaleOrder dto) { + + super(dto); + } + + @Override + protected void afterInit(SaleOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleOrderWithOutBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleOrderWithOutBo.java new file mode 100644 index 0000000..fc04847 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleOrderWithOutBo.java @@ -0,0 +1,318 @@ +package com.lframework.xingyun.sc.bo.sale; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.sale.SaleOrderWithOutDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class SaleOrderWithOutBo extends BaseBo { + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public SaleOrderWithOutBo() { + + } + + public SaleOrderWithOutBo(SaleOrderWithOutDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOrderWithOutDto dto) { + + return super.convert(dto, SaleOrderWithOutBo::getDetails); + } + + @Override + protected void afterInit(SaleOrderWithOutDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerName = customer.getName(); + + if (!StringUtil.isBlank(dto.getSalerId())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = userService.findById(dto.getSalerId()); + + this.salerId = saler.getId(); + this.salerName = saler.getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new DetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 组合商品ID + */ + @ApiModelProperty("组合商品ID") + private String mainProductId; + + /** + * 组合商品名称 + */ + @ApiModelProperty("组合商品名称") + private String mainProductName; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer orderNum; + + /** + * 销售价 + */ + @ApiModelProperty("销售价") + private BigDecimal salePrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 剩余出库数量 + */ + @ApiModelProperty("剩余出库数量") + private Integer remainNum; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public DetailBo() { + + } + + public DetailBo(String scId, SaleOrderWithOutDto.DetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert(SaleOrderWithOutDto.DetailDto dto) { + + return this; + } + + @Override + public BaseBo convert(SaleOrderWithOutDto.DetailDto dto, + SFunction... columns) { + + return this; + } + + @Override + protected void afterInit(SaleOrderWithOutDto.DetailDto dto) { + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.id = dto.getId(); + this.productId = product.getId(); + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + this.orderNum = dto.getOrderNum(); + this.salePrice = dto.getOriPrice(); + this.taxPrice = dto.getTaxPrice(); + this.discountRate = dto.getDiscountRate(); + this.remainNum = NumberUtil.sub(dto.getOrderNum(), dto.getOutNum()).intValue(); + this.isGift = dto.getIsGift(); + this.taxRate = dto.getTaxRate(); + this.description = dto.getDescription(); + + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + + if (StringUtil.isNotBlank(dto.getMainProductId())) { + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product mainProduct = productService.findById(dto.getMainProductId()); + this.mainProductId = dto.getMainProductId(); + this.mainProductName = mainProduct.getName(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleProductBo.java new file mode 100644 index 0000000..27a703e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/SaleProductBo.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.sc.bo.sale; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SaleProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 是否多销售属性 + */ + @ApiModelProperty("是否多销售属性") + private Boolean multiSaleProp; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 销售价 + */ + @ApiModelProperty("销售价") + private BigDecimal salePrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public SaleProductBo(String scId, SaleProductDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + protected void afterInit(SaleProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/config/GetSaleConfigBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/config/GetSaleConfigBo.java new file mode 100644 index 0000000..91857b0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/config/GetSaleConfigBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.sc.bo.sale.config; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.SaleConfig; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSaleConfigBo extends BaseBo { + + /** + * 销售出库单是否关联销售订单 + */ + @ApiModelProperty("销售出库单是否关联销售订单") + private Boolean outStockRequireSale; + + /** + * 销售出库单是否多次关联销售订单 + */ + @ApiModelProperty("销售出库单是否多次关联销售订单") + private Boolean outStockMultipleRelateSale; + + /** + * 销售退货单是否关联销售出库单 + */ + @ApiModelProperty("销售退货单是否关联销售出库单") + private Boolean saleReturnRequireOutStock; + + /** + * 销售退货单是否多次关联销售出库单 + */ + @ApiModelProperty("销售退货单是否多次关联销售出库单") + private Boolean saleReturnMultipleRelateOutStock; + + /** + * 销售出库单是否关联物流单 + */ + @ApiModelProperty("销售出库单是否关联物流单") + private Boolean outStockRequireLogistics; + + public GetSaleConfigBo() { + + } + + public GetSaleConfigBo(SaleConfig dto) { + + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/GetSaleOutSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/GetSaleOutSheetBo.java new file mode 100644 index 0000000..96adc0a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/GetSaleOutSheetBo.java @@ -0,0 +1,446 @@ +package com.lframework.xingyun.sc.bo.sale.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSaleOutSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + /** + * 销售订单ID + */ + @ApiModelProperty("销售订单ID") + private String saleOrderId; + + /** + * 销售订单号 + */ + @ApiModelProperty("销售订单号") + private String saleOrderCode; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetSaleOutSheetBo() { + + } + + public GetSaleOutSheetBo(SaleOutSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOutSheetFullDto dto) { + + return super.convert(dto, GetSaleOutSheetBo::getStatus, GetSaleOutSheetBo::getSettleStatus, + GetSaleOutSheetBo::getDetails); + } + + @Override + protected void afterInit(SaleOutSheetFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + this.customerName = customerService.findById(dto.getCustomerId()).getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + if (!StringUtil.isBlank(dto.getSaleOrderId())) { + SaleOrder saleOrder = saleOrderService.getById(dto.getSaleOrderId()); + this.saleOrderCode = saleOrder.getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new OrderDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 组合商品ID + */ + @ApiModelProperty("组合商品ID") + private String mainProductId; + + /** + * 组合商品名称 + */ + @ApiModelProperty("组合商品名称") + private String mainProductName; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer orderNum; + + /** + * 剩余出库数量 + */ + @ApiModelProperty("剩余出库数量") + private Integer remainNum; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal salePrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 销售订单明细ID + */ + @ApiModelProperty("销售订单明细ID") + private String saleOrderDetailId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public OrderDetailBo(String scId, SaleOutSheetFullDto.SheetDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + SaleOutSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleOutSheetFullDto.SheetDetailDto dto) { + + this.outNum = dto.getOrderNum(); + this.taxPrice = dto.getTaxPrice(); + this.salePrice = dto.getOriPrice(); + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + if (!StringUtil.isBlank(dto.getSaleOrderDetailId())) { + SaleOrderDetailService saleOrderDetailService = ApplicationUtil.getBean( + SaleOrderDetailService.class); + SaleOrderDetail saleOrderDetail = saleOrderDetailService.getById( + dto.getSaleOrderDetailId()); + this.orderNum = saleOrderDetail.getOrderNum(); + this.remainNum = NumberUtil.sub(saleOrderDetail.getOrderNum(), saleOrderDetail.getOutNum()) + .intValue(); + } + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + + if (StringUtil.isNotBlank(dto.getMainProductId())) { + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product mainProduct = productService.findById(dto.getMainProductId()); + this.mainProductId = dto.getMainProductId(); + this.mainProductName = mainProduct.getName(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/PrintSaleOutSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/PrintSaleOutSheetBo.java new file mode 100644 index 0000000..8c5bb53 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/PrintSaleOutSheetBo.java @@ -0,0 +1,270 @@ +package com.lframework.xingyun.sc.bo.sale.out; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetFullDto; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.enums.SaleOutSheetStatus; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintSaleOutSheetBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private String paymentDate; + + /** + * 销售订单号 + */ + @ApiModelProperty("销售订单号") + private String saleOrderCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + /** + * 商品数量 + */ + @ApiModelProperty("商品数量") + private Integer totalNum; + + /** + * 出库总金额 + */ + @ApiModelProperty("出库总金额") + private BigDecimal totalAmount; + + /** + * 大写中文总合计金额 + */ + @ApiModelProperty("大写中文总合计金额") + private String bigTotalAmount; + + public PrintSaleOutSheetBo() { + + } + + public PrintSaleOutSheetBo(SaleOutSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOutSheetFullDto dto) { + + return super.convert(dto, PrintSaleOutSheetBo::getDetails); + } + + @Override + protected void afterInit(SaleOutSheetFullDto dto) { + + this.salerName = StringPool.EMPTY_STR; + this.paymentDate = StringPool.EMPTY_STR; + this.saleOrderCode = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + if (!StringUtil.isBlank(dto.getSaleOrderId())) { + SaleOrder saleOrder = saleOrderService.getById(dto.getSaleOrderId()); + this.saleOrderCode = saleOrder.getCode(); + } + + if (dto.getPaymentDate() != null) { + this.paymentDate = DateUtil.formatDate(dto.getPaymentDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == SaleOutSheetStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(OrderDetailBo::new).collect(Collectors.toList()); + } + + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class OrderDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal outAmount; + + public OrderDetailBo(SaleOutSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + SaleOutSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleOutSheetFullDto.SheetDetailDto dto) { + + this.outNum = dto.getOrderNum(); + this.taxPrice = dto.getTaxPrice(); + this.outAmount = NumberUtil.mul(dto.getTaxPrice(), dto.getOrderNum()); + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetBo.java new file mode 100644 index 0000000..5f6c067 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetBo.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.sc.bo.sale.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOutSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 销售订单ID + */ + @ApiModelProperty("销售订单ID") + private String saleOrderId; + + /** + * 销售订单号 + */ + @ApiModelProperty("销售订单号") + private String saleOrderCode; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 销售金额 + */ + @ApiModelProperty("销售金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QuerySaleOutSheetBo(SaleOutSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOutSheet dto) { + + return super.convert(dto, QuerySaleOutSheetBo::getStatus, QuerySaleOutSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(SaleOutSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + if (!StringUtil.isBlank(dto.getSaleOrderId())) { + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleOrder saleOrder = saleOrderService.getById(dto.getSaleOrderId()); + this.saleOrderCode = saleOrder.getCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetWithReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetWithReturnBo.java new file mode 100644 index 0000000..a6a4f5b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/QuerySaleOutSheetWithReturnBo.java @@ -0,0 +1,96 @@ +package com.lframework.xingyun.sc.bo.sale.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOutSheetWithReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QuerySaleOutSheetWithReturnBo() { + + } + + public QuerySaleOutSheetWithReturnBo(SaleOutSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOutSheet dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleOutSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/SaleOutSheetWithReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/SaleOutSheetWithReturnBo.java new file mode 100644 index 0000000..c77bbb1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/out/SaleOutSheetWithReturnBo.java @@ -0,0 +1,296 @@ +package com.lframework.xingyun.sc.bo.sale.out; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class SaleOutSheetWithReturnBo extends BaseBo { + + /** + * 订单ID + */ + @ApiModelProperty("订单ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public SaleOutSheetWithReturnBo() { + + } + + public SaleOutSheetWithReturnBo(SaleOutSheetWithReturnDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOutSheetWithReturnDto dto) { + + return super.convert(dto, SaleOutSheetWithReturnBo::getSalerId, + SaleOutSheetWithReturnBo::getDetails); + } + + @Override + protected void afterInit(SaleOutSheetWithReturnDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerName = customer.getName(); + + if (!StringUtil.isBlank(dto.getSalerId())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = userService.findById(dto.getSalerId()); + + this.salerId = saler.getId(); + this.salerName = saler.getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new DetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal salePrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 剩余退货数量 + */ + @ApiModelProperty("剩余退货数量") + private Integer remainNum; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率(%) + */ + @ApiModelProperty("税率(%)") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public DetailBo(String scId, SaleOutSheetWithReturnDto.SheetDetailDto dto) { + + this.scId = scId; + + this.init(dto); + } + + @Override + public BaseBo convert( + SaleOutSheetWithReturnDto.SheetDetailDto dto) { + + return this; + } + + @Override + public BaseBo convert( + SaleOutSheetWithReturnDto.SheetDetailDto dto, SFunction... columns) { + + return this; + } + + @Override + protected void afterInit(SaleOutSheetWithReturnDto.SheetDetailDto dto) { + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.id = dto.getId(); + this.productId = product.getId(); + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + this.outNum = dto.getOrderNum(); + this.salePrice = dto.getOriPrice(); + this.taxPrice = dto.getTaxPrice(); + this.discountRate = dto.getDiscountRate(); + this.remainNum = NumberUtil.sub(dto.getOrderNum(), dto.getReturnNum()).intValue(); + this.isGift = dto.getIsGift(); + this.taxRate = dto.getTaxRate(); + this.description = dto.getDescription(); + + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.getProductId(), + this.getScId()); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/GetSaleReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/GetSaleReturnBo.java new file mode 100644 index 0000000..baefdb1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/GetSaleReturnBo.java @@ -0,0 +1,409 @@ +package com.lframework.xingyun.sc.bo.sale.returned; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetDetailLotDto; +import com.lframework.xingyun.sc.dto.sale.returned.SaleReturnFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSaleReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + @JsonFormat(pattern = StringPool.DATE_PATTERN) + private LocalDate paymentDate; + + /** + * 销售出库单ID + */ + @ApiModelProperty("销售出库单ID") + private String outSheetId; + + /** + * 销售出库单号 + */ + @ApiModelProperty("销售出库单号") + private String outSheetCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer giftNum; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + public GetSaleReturnBo(SaleReturnFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleReturnFullDto dto) { + + return super.convert(dto, GetSaleReturnBo::getStatus, GetSaleReturnBo::getSettleStatus, + GetSaleReturnBo::getDetails); + } + + @Override + protected void afterInit(SaleReturnFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + this.scName = storeCenterService.findById(dto.getScId()).getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + this.customerName = customerService.findById(dto.getCustomerId()).getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + if (!StringUtil.isBlank(dto.getOutSheetId())) { + SaleOutSheet outSheet = saleOutSheetService.getById(dto.getOutSheetId()); + this.outSheetCode = outSheet.getCode(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalNum = dto.getTotalNum(); + this.giftNum = dto.getTotalGiftNum(); + this.totalAmount = dto.getTotalAmount(); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new ReturnDetailBo(this.getScId(), t)) + .collect(Collectors.toList()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + this.payTypes = orderPayTypes.stream().map(OrderPayTypeBo::new).collect(Collectors.toList()); + } + + @Data + public static class ReturnDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer outNum; + + /** + * 剩余退货数量 + */ + @ApiModelProperty("剩余退货数量") + private Integer remainNum; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal salePrice; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 折扣 + */ + @ApiModelProperty("折扣") + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + @ApiModelProperty("是否赠品") + private Boolean isGift; + + /** + * 税率 + */ + @ApiModelProperty("税率") + private BigDecimal taxRate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 销售出库单明细ID + */ + @ApiModelProperty("销售出库单明细ID") + private String outSheetDetailId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public ReturnDetailBo(String scId, SaleReturnFullDto.ReturnDetailDto dto) { + + this.scId = scId; + this.init(dto); + } + + @Override + public BaseBo convert( + SaleReturnFullDto.ReturnDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleReturnFullDto.ReturnDetailDto dto) { + + this.returnNum = dto.getReturnNum(); + this.salePrice = dto.getOriPrice(); + this.taxPrice = dto.getTaxPrice(); + this.discountRate = dto.getDiscountRate(); + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.unit = product.getUnit(); + this.spec = product.getSpec(); + this.categoryName = product.getCategoryName(); + this.brandName = product.getBrandName(); + + if (!StringUtil.isBlank(dto.getOutSheetDetailId())) { + SaleOutSheetDetailLotService receiveSheetDetailService = ApplicationUtil.getBean( + SaleOutSheetDetailLotService.class); + SaleOutSheetDetailLotDto outSheetDetail = receiveSheetDetailService.findById( + dto.getOutSheetDetailId()); + this.outNum = outSheetDetail.getOrderNum(); + this.remainNum = NumberUtil.sub(outSheetDetail.getOrderNum(), + outSheetDetail.getReturnNum()).intValue(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/PrintSaleReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/PrintSaleReturnBo.java new file mode 100644 index 0000000..16498ee --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/PrintSaleReturnBo.java @@ -0,0 +1,267 @@ +package com.lframework.xingyun.sc.bo.sale.returned; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.BasePrintDataBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.dto.sale.returned.SaleReturnFullDto; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.enums.SaleReturnStatus; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PrintSaleReturnBo extends BasePrintDataBo { + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private String paymentDate; + + /** + * 销售出库单号 + */ + @ApiModelProperty("销售出库单号") + private String outSheetCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private String createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + private String approveTime; + + /** + * 订单明细 + */ + @ApiModelProperty("订单明细") + private List details; + + /** + * 商品数量 + */ + @ApiModelProperty("商品数量") + private Integer totalNum; + + /** + * 退货总金额 + */ + @ApiModelProperty("退货总金额") + private BigDecimal totalAmount; + + /** + * 大写合计总金额 + */ + @ApiModelProperty("大写合计总金额") + private String bigTotalAmount; + + public PrintSaleReturnBo(SaleReturnFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleReturnFullDto dto) { + + return super.convert(dto, PrintSaleReturnBo::getDetails); + } + + @Override + protected void afterInit(SaleReturnFullDto dto) { + + this.salerName = StringPool.EMPTY_STR; + this.paymentDate = StringPool.EMPTY_STR; + this.outSheetCode = StringPool.EMPTY_STR; + this.approveBy = StringPool.EMPTY_STR; + this.approveTime = StringPool.EMPTY_STR; + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + if (!StringUtil.isBlank(dto.getOutSheetId())) { + SaleOutSheet outSheet = saleOutSheetService.getById(dto.getOutSheetId()); + this.outSheetCode = outSheet.getCode(); + } + + if (dto.getPaymentDate() != null) { + this.paymentDate = DateUtil.formatDate(dto.getPaymentDate()); + } + + this.createTime = DateUtil.formatDateTime(dto.getCreateTime()); + + if (!StringUtil.isBlank(dto.getApproveBy()) + && dto.getStatus() == SaleReturnStatus.APPROVE_PASS) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + this.approveTime = DateUtil.formatDateTime(dto.getApproveTime()); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(ReturnDetailBo::new) + .collect(Collectors.toList()); + } + this.bigTotalAmount = Convert.digitToChinese(dto.getTotalAmount()); + } + + @Data + public static class ReturnDetailBo extends BaseBo { + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * SKU编号 + */ + @ApiModelProperty("SKU编号") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private BigDecimal taxPrice; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal returnAmount; + + public ReturnDetailBo(SaleReturnFullDto.ReturnDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + SaleReturnFullDto.ReturnDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SaleReturnFullDto.ReturnDetailDto dto) { + + this.returnNum = dto.getReturnNum(); + this.taxPrice = dto.getTaxPrice(); + this.returnAmount = NumberUtil.mul(dto.getTaxPrice(), dto.getReturnNum()); + + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleProductDto product = saleOrderService.getSaleById(dto.getProductId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/QuerySaleReturnBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/QuerySaleReturnBo.java new file mode 100644 index 0000000..903968b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/sale/returned/QuerySaleReturnBo.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.sc.bo.sale.returned; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleReturnBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ApiModelProperty("销售员姓名") + private String salerName; + + /** + * 销售出库单ID + */ + @ApiModelProperty("销售出库单ID") + private String outSheetId; + + /** + * 销售出库单号 + */ + @ApiModelProperty("销售出库单号") + private String outSheetCode; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ApiModelProperty("赠品数量") + private Integer totalGiftNum; + + /** + * 退货金额 + */ + @ApiModelProperty("退货金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QuerySaleReturnBo(SaleReturn dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleReturn dto) { + + return super.convert(dto, QuerySaleReturnBo::getStatus, QuerySaleReturnBo::getSettleStatus); + } + + @Override + protected void afterInit(SaleReturn dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getSalerId())) { + this.salerName = userService.findById(dto.getSalerId()).getName(); + } + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + if (!StringUtil.isBlank(dto.getOutSheetId())) { + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + SaleOutSheet outSheet = saleOutSheetService.getById(dto.getOutSheetId()); + this.outSheetCode = outSheet.getCode(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/QueryStockCostAdjustSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/QueryStockCostAdjustSheetBo.java new file mode 100644 index 0000000..601a44e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/QueryStockCostAdjustSheetBo.java @@ -0,0 +1,131 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.cost; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheet; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 库存成本调整单 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryStockCostAdjustSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 调价品种数 + */ + @ApiModelProperty("调价品种数") + private Integer productNum; + + /** + * 库存调价差额 + */ + @ApiModelProperty("库存调价差额") + private BigDecimal diffAmount; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public QueryStockCostAdjustSheetBo() { + + } + + public QueryStockCostAdjustSheetBo(StockCostAdjustSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(StockCostAdjustSheet dto) { + + return super.convert(dto, QueryStockCostAdjustSheetBo::getStatus); + } + + @Override + protected void afterInit(StockCostAdjustSheet dto) { + + this.status = dto.getStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustProductBo.java new file mode 100644 index 0000000..a4a6295 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustProductBo.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.cost; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustProductDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class StockCostAdjustProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 档案采购价 + */ + @ApiModelProperty("档案采购价") + private BigDecimal purchasePrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 调价前成本价 + */ + @ApiModelProperty("调价前成本价") + private BigDecimal oriPrice; + + public StockCostAdjustProductBo() { + + } + + public StockCostAdjustProductBo(StockCostAdjustProductDto dto) { + + super(dto); + } + + @Override + protected void afterInit(StockCostAdjustProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustSheetFullBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustSheetFullBo.java new file mode 100644 index 0000000..f692ab6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/cost/StockCostAdjustSheetFullBo.java @@ -0,0 +1,321 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.cost; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.enums.StockCostAdjustSheetStatus; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +/** + *

+ * 库存成本调整单 GetBo + *

+ * + * @author zmj + */ +@Data +public class StockCostAdjustSheetFullBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 调价品种数 + */ + @ApiModelProperty("调价品种数") + private Integer productNum; + + /** + * 库存调价差额 + */ + @ApiModelProperty("库存调价差额") + private BigDecimal diffAmount; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 明细 + */ + @ApiModelProperty("明细") + private List details; + + public StockCostAdjustSheetFullBo(StockCostAdjustSheetFullDto dto) { + + super(dto); + } + + @Override + public
BaseBo convert(StockCostAdjustSheetFullDto dto) { + + return super.convert(dto, StockCostAdjustSheetFullBo::getStatus); + } + + @Override + protected void afterInit(StockCostAdjustSheetFullDto dto) { + + this.status = dto.getStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.details = dto.getDetails().stream().map(t -> new DetailBo(t, this.scId, this.status)) + .collect(Collectors.toList()); + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 档案采购价 + */ + @ApiModelProperty("档案采购价") + private BigDecimal purchasePrice; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 调整前成本价 + */ + @ApiModelProperty("调整前成本价") + private BigDecimal oriPrice; + + /** + * 调整后成本价 + */ + @ApiModelProperty("调整后成本价") + private BigDecimal price; + + /** + * 库存调价差额 + */ + @ApiModelProperty("库存调价差额") + private BigDecimal diffAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private String scId; + + /** + * 状态 + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private Integer status; + + public DetailBo(StockCostAdjustSheetFullDto.DetailDto dto, String scId, Integer status) { + + this.scId = scId; + this.status = status; + + this.init(dto); + } + + @Override + public BaseBo convert( + StockCostAdjustSheetFullDto.DetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(StockCostAdjustSheetFullDto.DetailDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.brandName = productBrand.getName(); + this.categoryName = productCategory.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + if (EnumUtil.getByCode(StockCostAdjustSheetStatus.class, this.status) + != StockCostAdjustSheetStatus.APPROVE_PASS) { + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(dto.getProductId(), + this.scId); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + this.oriPrice = productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2); + this.diffAmount = NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.sub(this.price, this.oriPrice), this.stockNum), 2); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/QueryStockAdjustSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/QueryStockAdjustSheetBo.java new file mode 100644 index 0000000..08c3b18 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/QueryStockAdjustSheetBo.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.stock; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.entity.StockAdjustSheet; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustReasonService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 库存成本调整单 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryStockAdjustSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @EnumConvert + private Integer bizType; + + /** + * 调整原因 + */ + @ApiModelProperty("调整原因") + private String reasonName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public QueryStockAdjustSheetBo() { + + } + + public QueryStockAdjustSheetBo(StockAdjustSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(StockAdjustSheet dto) { + + return super.convert(dto, QueryStockAdjustSheetBo::getStatus); + } + + @Override + protected void afterInit(StockAdjustSheet dto) { + + this.status = dto.getStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + StockAdjustReasonService stockAdjustReasonService = ApplicationUtil.getBean( + StockAdjustReasonService.class); + StockAdjustReason reason = stockAdjustReasonService.findById(dto.getReasonId()); + this.reasonName = reason.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustProductBo.java new file mode 100644 index 0000000..f86f9e7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustProductBo.java @@ -0,0 +1,105 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.stock; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class StockAdjustProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 当前库存数量 + */ + @ApiModelProperty("当前库存数量") + private Integer curStockNum; + + /** + * 仓库ID + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private String scId; + + public StockAdjustProductBo() { + + } + + public StockAdjustProductBo(String scId, StockAdjustProductDto dto) { + this.scId = scId; + + this.init(dto); + } + + @Override + protected void afterInit(StockAdjustProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(dto.getId(), + this.scId); + this.curStockNum = productStock == null ? 0 : productStock.getStockNum(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustSheetFullBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustSheetFullBo.java new file mode 100644 index 0000000..8955330 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/StockAdjustSheetFullBo.java @@ -0,0 +1,320 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.stock; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.enums.StockAdjustSheetStatus; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustReasonService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +/** + *

+ * 库存调整单 GetBo + *

+ * + * @author zmj + */ +@Data +public class StockAdjustSheetFullBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @EnumConvert + private Integer bizType; + + /** + * 调整原因ID + */ + @ApiModelProperty("调整原因ID") + private String reasonId; + + /** + * 调整原因 + */ + @ApiModelProperty("调整原因") + private String reasonName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 明细 + */ + @ApiModelProperty("明细") + private List details; + + /** + * 发起人编号 + */ + @ApiModelProperty("发起人编号") + private String createCode; + + public StockAdjustSheetFullBo(StockAdjustSheetFullDto dto) { + + super(dto); + } + + @Override + public
BaseBo convert(StockAdjustSheetFullDto dto) { + + return super.convert(dto, StockAdjustSheetFullBo::getStatus); + } + + @Override + protected void afterInit(StockAdjustSheetFullDto dto) { + + this.status = dto.getStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + if (!StringUtil.isBlank(dto.getCreateById())){ + this.createCode = userService.findById(dto.getCreateById()).getCode(); + } + StockAdjustReasonService stockAdjustReasonService = ApplicationUtil.getBean(StockAdjustReasonService.class); + StockAdjustReason reason = stockAdjustReasonService.findById(dto.getReasonId()); + this.reasonName = reason.getName(); + + this.details = dto.getDetails().stream().map(t -> new DetailBo(t, this.scId, this.status)) + .collect(Collectors.toList()); + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 调整库存数量 + */ + @ApiModelProperty("调整库存数量") + private Integer stockNum; + + /** + * 当前库存数量 + */ + @ApiModelProperty("当前库存数量") + private Integer curStockNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private String scId; + + /** + * 状态 + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private Integer status; + + public DetailBo(StockAdjustSheetFullDto.DetailDto dto, String scId, Integer status) { + + this.scId = scId; + this.status = status; + + this.init(dto); + } + + @Override + public BaseBo convert( + StockAdjustSheetFullDto.DetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(StockAdjustSheetFullDto.DetailDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.brandName = productBrand.getName(); + this.categoryName = productCategory.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + if (EnumUtil.getByCode(StockAdjustSheetStatus.class, this.status) + != StockAdjustSheetStatus.APPROVE_PASS) { + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(dto.getProductId(), + this.scId); + this.curStockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/GetStockAdjustReasonBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/GetStockAdjustReasonBo.java new file mode 100644 index 0000000..c6449c4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/GetStockAdjustReasonBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.stock.reason; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetStockAdjustReasonBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetStockAdjustReasonBo() { + + } + + public GetStockAdjustReasonBo(StockAdjustReason dto) { + + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/QueryStockAdjustReasonBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/QueryStockAdjustReasonBo.java new file mode 100644 index 0000000..55a4123 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/QueryStockAdjustReasonBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.stock.reason; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryStockAdjustReasonBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryStockAdjustReasonBo() { + + } + + public QueryStockAdjustReasonBo(StockAdjustReason dto) { + + super(dto); + } + + @Override + protected void afterInit(StockAdjustReason dto) { + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/StockAdjustReasonSelectorBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/StockAdjustReasonSelectorBo.java new file mode 100644 index 0000000..fea60da --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/adjust/stock/reason/StockAdjustReasonSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.bo.stock.adjust.stock.reason; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class StockAdjustReasonSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public StockAdjustReasonSelectorBo() { + + } + + public StockAdjustReasonSelectorBo(StockAdjustReason dto) { + + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/QueryProductStockBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/QueryProductStockBo.java new file mode 100644 index 0000000..69ca937 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/QueryProductStockBo.java @@ -0,0 +1,129 @@ +package com.lframework.xingyun.sc.bo.stock.product; + +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.ProductStock; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class QueryProductStockBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 商品类目 + */ + @ApiModelProperty("商品类目") + private String categoryName; + + /** + * 商品品牌 + */ + @ApiModelProperty("商品品牌") + private String brandName; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 含税价格 + */ + @ApiModelProperty("含税价格") + private BigDecimal taxPrice; + + /** + * 含税金额 + */ + @ApiModelProperty("含税金额") + private BigDecimal taxAmount; + + public QueryProductStockBo() { + + } + + public QueryProductStockBo(ProductStock dto) { + + super(dto); + } + + @Override + protected void afterInit(ProductStock dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + + this.taxPrice = NumberUtil.getNumber(dto.getTaxPrice(), 2); + this.taxAmount = NumberUtil.getNumber(dto.getTaxAmount(), 2); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/log/QueryProductStockLogBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/log/QueryProductStockLogBo.java new file mode 100644 index 0000000..ef43b65 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/product/log/QueryProductStockLogBo.java @@ -0,0 +1,190 @@ +package com.lframework.xingyun.sc.bo.stock.product.log; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.ProductStockLog; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryProductStockLogBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 商品类目 + */ + @ApiModelProperty("商品类目") + private String categoryName; + + /** + * 商品品牌 + */ + @ApiModelProperty("商品品牌") + private String brandName; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 原库存数量 + */ + @ApiModelProperty("原库存数量") + private Integer oriStockNum; + + /** + * 现库存数量 + */ + @ApiModelProperty("现库存数量") + private Integer curStockNum; + + /** + * 原含税成本价 + */ + @ApiModelProperty("原含税成本价") + private BigDecimal oriTaxPrice; + + /** + * 现含税成本价 + */ + @ApiModelProperty("现含税成本价") + private BigDecimal curTaxPrice; + + /** + * 含税金额 + */ + @ApiModelProperty("含税金额") + private BigDecimal taxAmount; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + public QueryProductStockLogBo() { + + } + + public QueryProductStockLogBo(ProductStockLog dto) { + + super(dto); + } + + @Override + public BaseBo convert(ProductStockLog dto) { + + return super.convert(dto, QueryProductStockLogBo::getBizType); + } + + @Override + protected void afterInit(ProductStockLog dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + + this.oriTaxPrice = NumberUtil.getNumber(dto.getOriTaxPrice(), 2); + this.curTaxPrice = NumberUtil.getNumber(dto.getCurTaxPrice(), 2); + this.taxAmount = NumberUtil.getNumber(dto.getTaxAmount(), 2); + + this.bizType = dto.getBizType().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/config/GetTakeStockConfigBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/config/GetTakeStockConfigBo.java new file mode 100644 index 0000000..7d79547 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/config/GetTakeStockConfigBo.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.sc.bo.stock.take.config; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 盘点参数 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetTakeStockConfigBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据 + */ + @ApiModelProperty("库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据") + private Boolean showProduct; + + /** + * 库存盘点单是否显示盘点任务创建时商品的系统库存数量 + */ + @ApiModelProperty("库存盘点单是否显示盘点任务创建时商品的系统库存数量") + private Boolean showStock; + + /** + * 盘点差异生成时是否自动调整盘点任务中商品的系统库存数量 + */ + @ApiModelProperty("盘点差异生成时是否自动调整盘点任务中商品的系统库存数量") + private Boolean autoChangeStock; + + /** + * 盘点差异单中的盘点数量是否允许手动修改 + */ + @ApiModelProperty("盘点差异单中的盘点数量是否允许手动修改") + private Boolean allowChangeNum; + + /** + * 盘点任务创建后多少小时内未完成,则自动作废 + */ + @ApiModelProperty("盘点任务创建后多少小时内未完成,则自动作废") + private Integer cancelHours; + + public GetTakeStockConfigBo() { + + } + + public GetTakeStockConfigBo(TakeStockConfig dto) { + + super(dto); + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/GetTakeStockPlanBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/GetTakeStockPlanBo.java new file mode 100644 index 0000000..76c8cb2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/GetTakeStockPlanBo.java @@ -0,0 +1,127 @@ +package com.lframework.xingyun.sc.bo.stock.take.plan; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 盘点任务 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetTakeStockPlanBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点类别 + */ + @ApiModelProperty("盘点类别") + private Integer takeType; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 业务名称 + */ + @ApiModelProperty("业务名称") + private String bizName; + + public GetTakeStockPlanBo() { + + } + + public GetTakeStockPlanBo(TakeStockPlan dto) { + + super(dto); + } + + @Override + public
BaseBo convert(TakeStockPlan dto) { + + return super.convert(dto, GetTakeStockPlanBo::getTakeType, GetTakeStockPlanBo::getTakeStatus); + } + + @Override + protected void afterInit(TakeStockPlan dto) { + + this.takeType = dto.getTakeType().getCode(); + this.takeStatus = dto.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + this.scName = sc.getName(); + + String bizId = dto.getBizId(); + if (dto.getTakeType() == TakeStockPlanType.CATEGORY) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + String[] categoryIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String categoryId : categoryIds) { + ProductCategory productCategory = productCategoryService.findById(categoryId); + builder.append(productCategory.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } else if (dto.getTakeType() == TakeStockPlanType.BRAND) { + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + String[] brandIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String brandId : brandIds) { + ProductBrand productBrand = productBrandService.findById(brandId); + builder.append(productBrand.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanBo.java new file mode 100644 index 0000000..b9a37f5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanBo.java @@ -0,0 +1,162 @@ +package com.lframework.xingyun.sc.bo.stock.take.plan; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 盘点任务 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryTakeStockPlanBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点类别 + */ + @ApiModelProperty("盘点类别") + private Integer takeType; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 盘点内容 + */ + @ApiModelProperty("盘点内容") + private String bizName; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryTakeStockPlanBo() { + + } + + public QueryTakeStockPlanBo(TakeStockPlan dto) { + + super(dto); + } + + @Override + public BaseBo convert(TakeStockPlan dto) { + + return super.convert(dto, QueryTakeStockPlanBo::getTakeType, QueryTakeStockPlanBo::getTakeStatus); + } + + @Override + protected void afterInit(TakeStockPlan dto) { + + this.takeType = dto.getTakeType().getCode(); + this.takeStatus = dto.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + String bizId = dto.getBizId(); + if (dto.getTakeType() == TakeStockPlanType.CATEGORY) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + String[] categoryIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String categoryId : categoryIds) { + ProductCategory productCategory = productCategoryService.findById(categoryId); + builder.append(productCategory.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } else if (dto.getTakeType() == TakeStockPlanType.BRAND) { + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + String[] brandIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String brandId : brandIds) { + ProductBrand productBrand = productBrandService.findById(brandId); + builder.append(productBrand.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanProductBo.java new file mode 100644 index 0000000..f0826a5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/QueryTakeStockPlanProductBo.java @@ -0,0 +1,114 @@ +package com.lframework.xingyun.sc.bo.stock.take.plan; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.dto.stock.take.plan.QueryTakeStockPlanProductDto; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryTakeStockPlanProductBo extends BaseBo { + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 初始库存 + */ + @ApiModelProperty("初始库存") + private Integer stockNum; + + public QueryTakeStockPlanProductBo(QueryTakeStockPlanProductDto dto) { + + super(dto); + } + + @Override + protected void afterInit(QueryTakeStockPlanProductDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + TakeStockConfigService takeStockConfigService = ApplicationUtil.getBean( + TakeStockConfigService.class); + TakeStockConfig config = takeStockConfigService.get(); + if (!config.getShowStock()) { + this.stockNum = null; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanFullBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanFullBo.java new file mode 100644 index 0000000..fbfc4c8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanFullBo.java @@ -0,0 +1,279 @@ +package com.lframework.xingyun.sc.bo.stock.take.plan; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.stock.take.plan.TakeStockPlanFullDto; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class TakeStockPlanFullBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点类别 + */ + @ApiModelProperty("盘点类别") + private Integer takeType; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 明细 + */ + @ApiModelProperty("明细") + private List details; + + public TakeStockPlanFullBo(TakeStockPlanFullDto dto) { + + super(dto); + } + + @Override + public
BaseBo convert(TakeStockPlanFullDto dto) { + + return super.convert(dto, TakeStockPlanFullBo::getTakeType, TakeStockPlanFullBo::getTakeStatus, + TakeStockPlanFullBo::getDetails); + } + + @Override + protected void afterInit(TakeStockPlanFullDto dto) { + + this.takeType = dto.getTakeType().getCode(); + this.takeStatus = dto.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + this.details = CollectionUtil.isEmpty(dto.getDetails()) ? + CollectionUtil.emptyList() : + dto.getDetails().stream().map(t -> new DetailBo(t, this.id)).collect(Collectors.toList()); + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 原盘点数量(通过盘点单统计) + */ + @ApiModelProperty("原盘点数量(通过盘点单统计)") + private Integer oriTakeNum; + + /** + * 修改后的盘点数量 + */ + @ApiModelProperty("修改后的盘点数量") + private Integer takeNum; + + /** + * 出项数量 + */ + @ApiModelProperty("出项数量") + private Integer totalOutNum; + + /** + * 进项数量 + */ + @ApiModelProperty("进项数量") + private Integer totalInNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 差异数量 + */ + @ApiModelProperty("差异数量") + private Integer diffNum; + + /** + * 盘点任务ID + */ + @ApiModelProperty(value = "盘点任务ID", hidden = true) + @JsonIgnore + private String planId; + + public DetailBo(TakeStockPlanFullDto.DetailDto dto, String planId) { + + this.planId = planId; + + this.init(dto); + } + + @Override + public BaseBo convert(TakeStockPlanFullDto.DetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(TakeStockPlanFullDto.DetailDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + if (this.oriTakeNum != null || this.takeNum != null) { + + if (this.takeNum != null) { + this.diffNum = this.takeNum - this.stockNum; + } else { + this.diffNum = this.oriTakeNum - this.stockNum; + } + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanSelectorBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanSelectorBo.java new file mode 100644 index 0000000..23eae19 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/plan/TakeStockPlanSelectorBo.java @@ -0,0 +1,89 @@ +package com.lframework.xingyun.sc.bo.stock.take.plan; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class TakeStockPlanSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点类别 + */ + @ApiModelProperty("盘点类别") + private Integer takeType; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public TakeStockPlanSelectorBo(TakeStockPlan dto) { + + super(dto); + } + + @Override + public BaseBo convert(TakeStockPlan dto) { + + return super.convert(dto, TakeStockPlanSelectorBo::getTakeType, TakeStockPlanSelectorBo::getTakeStatus); + } + + @Override + protected void afterInit(TakeStockPlan dto) { + + this.takeType = dto.getTakeType().getCode(); + this.takeStatus = dto.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/GetPreTakeStockSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/GetPreTakeStockSheetBo.java new file mode 100644 index 0000000..b0ef8da --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/GetPreTakeStockSheetBo.java @@ -0,0 +1,226 @@ +package com.lframework.xingyun.sc.bo.stock.take.pre; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockSheetFullDto; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +/** + *

+ * 预先盘点单 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetPreTakeStockSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 操作人 + */ + @ApiModelProperty("操作人") + private String updateBy; + + /** + * 操作时间 + */ + @ApiModelProperty("操作时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 明细 + */ + @ApiModelProperty("明细") + private List details; + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 初盘数量 + */ + @ApiModelProperty("初盘数量") + private Integer firstNum; + + /** + * 复盘数量 + */ + @ApiModelProperty("复盘数量") + private Integer secondNum; + + /** + * 抽盘数量 + */ + @ApiModelProperty("抽盘数量") + private Integer randNum; + + public SheetDetailBo(PreTakeStockSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + protected void afterInit(PreTakeStockSheetFullDto.SheetDetailDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + } + } + + public GetPreTakeStockSheetBo() { + + } + + public GetPreTakeStockSheetBo(PreTakeStockSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(PreTakeStockSheetFullDto dto) { + + return super.convert(dto, GetPreTakeStockSheetBo::getTakeStatus); + } + + @Override + protected void afterInit(PreTakeStockSheetFullDto dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + this.scId = sc.getId(); + this.scName = sc.getName(); + + this.takeStatus = dto.getTakeStatus().getCode(); + + this.details = dto.getDetails().stream().map(SheetDetailBo::new).collect(Collectors.toList()); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockProductBo.java new file mode 100644 index 0000000..afd5983 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockProductBo.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.sc.bo.stock.take.pre; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockProductDto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class PreTakeStockProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + public PreTakeStockProductBo() { + + } + + public PreTakeStockProductBo(PreTakeStockProductDto dto) { + + super(dto); + } + + @Override + protected void afterInit(PreTakeStockProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockSheetSelectorBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockSheetSelectorBo.java new file mode 100644 index 0000000..da69117 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/PreTakeStockSheetSelectorBo.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.sc.bo.stock.take.pre; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class PreTakeStockSheetSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public PreTakeStockSheetSelectorBo(PreTakeStockSheet dto) { + + super(dto); + } + + @Override + public
BaseBo convert(PreTakeStockSheet dto) { + + return super.convert(dto, PreTakeStockSheetSelectorBo::getTakeStatus); + } + + @Override + protected void afterInit(PreTakeStockSheet dto) { + + this.takeStatus = dto.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetBo.java new file mode 100644 index 0000000..92b66da --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetBo.java @@ -0,0 +1,98 @@ +package com.lframework.xingyun.sc.bo.stock.take.pre; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 预先盘点单 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryPreTakeStockSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + private Integer takeStatus; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public QueryPreTakeStockSheetBo() { + + } + + public QueryPreTakeStockSheetBo(PreTakeStockSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(PreTakeStockSheet dto) { + + return super.convert(dto, QueryPreTakeStockSheetBo::getTakeStatus); + } + + @Override + protected void afterInit(PreTakeStockSheet dto) { + + this.takeStatus = dto.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetProductBo.java new file mode 100644 index 0000000..d1d286d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/pre/QueryPreTakeStockSheetProductBo.java @@ -0,0 +1,143 @@ +package com.lframework.xingyun.sc.bo.stock.take.pre; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.dto.stock.take.pre.QueryPreTakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryPreTakeStockSheetProductBo extends BaseBo { + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 盘点数量 + */ + @ApiModelProperty("盘点数量") + private Integer takeNum; + + public QueryPreTakeStockSheetProductBo(QueryPreTakeStockSheetProductDto dto, String scId) { + + this.scId = scId; + + this.init(dto); + } + + @Override + protected void afterInit(QueryPreTakeStockSheetProductDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + if (dto.getTakeStatus() == PreTakeStockSheetStatus.FIRST_TAKE) { + this.takeNum = dto.getFirstNum(); + } else if (dto.getTakeStatus() == PreTakeStockSheetStatus.SECOND_TAKE) { + this.takeNum = dto.getSecondNum(); + } else if (dto.getTakeStatus() == PreTakeStockSheetStatus.RAND_TAKE) { + this.takeNum = dto.getRandNum(); + } + + TakeStockConfigService takeStockConfigService = ApplicationUtil.getBean( + TakeStockConfigService.class); + TakeStockConfig config = takeStockConfigService.get(); + if (config.getShowStock()) { + ProductStockService productStockService = ApplicationUtil.getBean(ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.productId, this.scId); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/QueryTakeStockSheetBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/QueryTakeStockSheetBo.java new file mode 100644 index 0000000..ea67146 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/QueryTakeStockSheetBo.java @@ -0,0 +1,147 @@ +package com.lframework.xingyun.sc.bo.stock.take.sheet; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.entity.TakeStockSheet; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 盘点单 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryTakeStockSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 盘点任务号 + */ + @ApiModelProperty("盘点任务号") + private String planCode; + + /** + * 仓库编号 + */ + @ApiModelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点任务-盘点类别 + */ + @ApiModelProperty("盘点任务-盘点类别") + private Integer takeType; + + /** + * 盘点任务-盘点状态 + */ + @ApiModelProperty("盘点任务-盘点状态") + private Integer takeStatus; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public QueryTakeStockSheetBo() { + + } + + public QueryTakeStockSheetBo(TakeStockSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(TakeStockSheet dto) { + + return super.convert(dto, QueryTakeStockSheetBo::getTakeStatus, QueryTakeStockSheetBo::getStatus); + } + + @Override + protected void afterInit(TakeStockSheet dto) { + + this.status = dto.getStatus().getCode(); + + TakeStockPlanService takeStockPlanService = ApplicationUtil.getBean(TakeStockPlanService.class); + TakeStockPlan takeStockPlan = takeStockPlanService.getById(dto.getPlanId()); + + this.planCode = takeStockPlan.getCode(); + this.takeStatus = takeStockPlan.getTakeStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.takeType = takeStockPlan.getTakeType().getCode(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetFullBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetFullBo.java new file mode 100644 index 0000000..f9412ca --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetFullBo.java @@ -0,0 +1,351 @@ +package com.lframework.xingyun.sc.bo.stock.take.sheet; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.stock.take.plan.GetTakeStockPlanDetailProductDto; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetFullDto; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import com.lframework.xingyun.sc.service.stock.take.PreTakeStockSheetService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanDetailService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +/** + *

+ * 盘点单详情 Bo + *

+ * + * @author zmj + */ +@Data +public class TakeStockSheetFullBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 盘点任务ID + */ + @ApiModelProperty("盘点任务ID") + private String planId; + + /** + * 盘点任务号 + */ + @ApiModelProperty("盘点任务号") + private String planCode; + + /** + * 预先盘点单ID + */ + @ApiModelProperty("预先盘点单ID") + private String preSheetId; + + /** + * 预先盘点单号 + */ + @ApiModelProperty("预先盘点单号") + private String preSheetCode; + + /** + * 仓库名称 + */ + @ApiModelProperty("仓库名称") + private String scName; + + /** + * 盘点任务-盘点类别 + */ + @ApiModelProperty("盘点任务-盘点类别") + private Integer takeType; + + /** + * 业务名称 + */ + @ApiModelProperty("业务名称") + private String bizName; + + /** + * 盘点任务-盘点状态 + */ + @ApiModelProperty("盘点任务-盘点状态") + private Integer takeStatus; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 拒绝理由 + */ + @ApiModelProperty("拒绝理由") + private String refuseReason; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 明细 + */ + @ApiModelProperty("明细") + private List details; + + public TakeStockSheetFullBo(TakeStockSheetFullDto dto) { + + super(dto); + } + + @Override + public
BaseBo convert(TakeStockSheetFullDto dto) { + + return super.convert(dto, TakeStockSheetFullBo::getTakeStatus, TakeStockSheetFullBo::getStatus); + } + + @Override + protected void afterInit(TakeStockSheetFullDto dto) { + + this.status = dto.getStatus().getCode(); + + TakeStockPlanService takeStockPlanService = ApplicationUtil.getBean(TakeStockPlanService.class); + TakeStockPlan plan = takeStockPlanService.getById(dto.getPlanId()); + this.planCode = plan.getCode(); + this.takeType = plan.getTakeType().getCode(); + this.takeStatus = plan.getTakeStatus().getCode(); + + String bizId = plan.getBizId(); + if (plan.getTakeType() == TakeStockPlanType.CATEGORY) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + String[] categoryIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String categoryId : categoryIds) { + ProductCategory productCategory = productCategoryService.findById(categoryId); + builder.append(productCategory.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } else if (plan.getTakeType() == TakeStockPlanType.BRAND) { + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + String[] brandIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String brandId : brandIds) { + ProductBrand productBrand = productBrandService.findById(brandId); + builder.append(productBrand.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } + + if (!StringUtil.isBlank(dto.getPreSheetId())) { + PreTakeStockSheetService preTakeStockSheetService = ApplicationUtil.getBean( + PreTakeStockSheetService.class); + PreTakeStockSheet preSheet = preTakeStockSheetService.getById(dto.getPreSheetId()); + this.preSheetCode = preSheet.getCode(); + } + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(this.approveBy)) { + this.approveBy = userService.findById(this.approveBy).getName(); + } + + this.details = dto.getDetails().stream().map(t -> new SheetDetailBo(t, this.planId)) + .collect(Collectors.toList()); + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 盘点数量 + */ + @ApiModelProperty("盘点数量") + private Integer takeNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 盘点任务ID + */ + @ApiModelProperty("盘点任务ID") + private String planId; + + public SheetDetailBo(TakeStockSheetFullDto.SheetDetailDto dto, String planId) { + + this.planId = planId; + + this.init(dto); + } + + @Override + protected void afterInit(TakeStockSheetFullDto.SheetDetailDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productId = product.getId(); + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + TakeStockConfigService takeStockConfigService = ApplicationUtil.getBean( + TakeStockConfigService.class); + TakeStockConfig config = takeStockConfigService.get(); + if (config.getShowStock()) { + TakeStockPlanDetailService takeStockPlanDetailService = ApplicationUtil.getBean( + TakeStockPlanDetailService.class); + GetTakeStockPlanDetailProductDto planDetail = takeStockPlanDetailService.getByPlanIdAndProductId( + this.planId, this.productId); + this.stockNum = planDetail.getStockNum(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetProductBo.java new file mode 100644 index 0000000..98035bb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/take/sheet/TakeStockSheetProductBo.java @@ -0,0 +1,128 @@ +package com.lframework.xingyun.sc.bo.stock.take.sheet; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.dto.stock.take.plan.GetTakeStockPlanDetailProductDto; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanDetailService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class TakeStockSheetProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 库存数量 + */ + @ApiModelProperty("库存数量") + private Integer stockNum; + + /** + * 盘点任务ID + */ + @ApiModelProperty(value = "盘点任务ID", hidden = true) + @JsonIgnore + private String planId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", hidden = true) + @JsonIgnore + private String scId; + + public TakeStockSheetProductBo(TakeStockSheetProductDto dto, String planId, String scId) { + + this.planId = planId; + this.scId = scId; + + this.init(dto); + } + + @Override + protected void afterInit(TakeStockSheetProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + + TakeStockConfigService takeStockConfigService = ApplicationUtil.getBean( + TakeStockConfigService.class); + TakeStockConfig config = takeStockConfigService.get(); + if (config.getShowStock()) { + if (!StringUtil.isBlank(this.planId)) { + TakeStockPlanDetailService takeStockPlanDetailService = ApplicationUtil.getBean( + TakeStockPlanDetailService.class); + GetTakeStockPlanDetailProductDto product = takeStockPlanDetailService.getByPlanIdAndProductId( + this.planId, this.productId); + this.stockNum = product.getStockNum(); + } else { + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(this.productId, + this.scId); + this.stockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderBo.java new file mode 100644 index 0000000..d9ce8ac --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderBo.java @@ -0,0 +1,147 @@ +package com.lframework.xingyun.sc.bo.stock.transfer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.ScTransferOrder; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 仓库调拨单 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryScTransferOrderBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 转出仓库编号 + */ + @ApiModelProperty("转出仓库编号") + private String sourceScCode; + + /** + * 转出仓库名称 + */ + @ApiModelProperty("转出仓库名称") + private String sourceScName; + + /** + * 转入仓库编号 + */ + @ApiModelProperty("转入仓库编号") + private String targetScCode; + + /** + * 转入仓库名称 + */ + @ApiModelProperty("转入仓库名称") + private String targetScName; + + /** + * 调拨数量 + */ + @ApiModelProperty("调拨数量") + private Integer totalNum; + + /** + * 调拨成本金额 + */ + @ApiModelProperty("调拨成本金额") + private BigDecimal totalAmount; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public QueryScTransferOrderBo() { + + } + + public QueryScTransferOrderBo(ScTransferOrder dto) { + + super(dto); + } + + @Override + public BaseBo convert(ScTransferOrder dto) { + + return super.convert(dto, QueryScTransferOrderBo::getStatus); + } + + @Override + protected void afterInit(ScTransferOrder dto) { + + this.status = dto.getStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sourceSc = storeCenterService.findById(dto.getSourceScId()); + this.sourceScCode = sourceSc.getCode(); + this.sourceScName = sourceSc.getName(); + + StoreCenter targetSc = storeCenterService.findById(dto.getTargetScId()); + this.targetScCode = targetSc.getCode(); + this.targetScName = targetSc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderDetailReceiveBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderDetailReceiveBo.java new file mode 100644 index 0000000..204d49d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/QueryScTransferOrderDetailReceiveBo.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.sc.bo.stock.transfer; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetailReceive; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryScTransferOrderDetailReceiveBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 收货数量 + */ + @ApiModelProperty("收货数量") + private Integer receiveNum; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + public QueryScTransferOrderDetailReceiveBo() { + } + + public QueryScTransferOrderDetailReceiveBo(ScTransferOrderDetailReceive dto) { + super(dto); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferOrderFullBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferOrderFullBo.java new file mode 100644 index 0000000..c3d8094 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferOrderFullBo.java @@ -0,0 +1,319 @@ +package com.lframework.xingyun.sc.bo.stock.transfer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferOrderFullDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.enums.ScTransferOrderStatus; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.template.core.service.UserService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +/** + *

+ * 仓库调拨单 GetBo + *

+ * + * @author zmj + */ +@Data +public class ScTransferOrderFullBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 转出仓库ID + */ + @ApiModelProperty("转出仓库ID") + private String sourceScId; + + /** + * 转出仓库名称 + */ + @ApiModelProperty("转出仓库名称") + private String sourceScName; + + /** + * 转入仓库ID + */ + @ApiModelProperty("转入仓库ID") + private String targetScId; + + /** + * 转入仓库名称 + */ + @ApiModelProperty("转入仓库名称") + private String targetScName; + + /** + * 调拨数量 + */ + @ApiModelProperty("调拨数量") + private Integer totalNum; + + /** + * 调拨成本金额 + */ + @ApiModelProperty("调拨成本金额") + private BigDecimal totalAmount; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + /** + * 明细 + */ + @ApiModelProperty("明细") + private List details; + + public ScTransferOrderFullBo(ScTransferOrderFullDto dto) { + + super(dto); + } + + @Override + public
BaseBo convert(ScTransferOrderFullDto dto) { + + return super.convert(dto, ScTransferOrderFullBo::getStatus); + } + + @Override + protected void afterInit(ScTransferOrderFullDto dto) { + + this.status = dto.getStatus().getCode(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sourceSc = storeCenterService.findById(dto.getSourceScId()); + this.sourceScName = sourceSc.getName(); + + StoreCenter targetSc = storeCenterService.findById(dto.getTargetScId()); + this.targetScName = targetSc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.details = dto.getDetails().stream().map(t -> new DetailBo(t, this.sourceScId, this.status)) + .collect(Collectors.toList()); + } + + @Data + public static class DetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 调拨数量 + */ + @ApiModelProperty("调拨数量") + private Integer transferNum; + + /** + * 当前库存数量 + */ + @ApiModelProperty("当前库存数量") + private Integer curStockNum; + + /** + * 已收货数量 + */ + @ApiModelProperty("已收货数量") + private Integer receiveNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 仓库ID + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private String scId; + + /** + * 状态 + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private Integer status; + + public DetailBo(ScTransferOrderFullDto.DetailDto dto, String scId, Integer status) { + + this.scId = scId; + this.status = status; + + this.init(dto); + } + + @Override + public BaseBo convert( + ScTransferOrderFullDto.DetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(ScTransferOrderFullDto.DetailDto dto) { + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.brandName = productBrand.getName(); + this.categoryName = productCategory.getName(); + this.skuCode = product.getSkuCode(); + this.externalCode = product.getExternalCode(); + this.spec = product.getSpec(); + this.unit = product.getUnit(); + + if (EnumUtil.getByCode(ScTransferOrderStatus.class, this.status) + != ScTransferOrderStatus.APPROVE_PASS) { + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(dto.getProductId(), + this.scId); + this.curStockNum = productStock == null ? 0 : productStock.getStockNum(); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferProductBo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferProductBo.java new file mode 100644 index 0000000..84dcbae --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/bo/stock/transfer/ScTransferProductBo.java @@ -0,0 +1,105 @@ +package com.lframework.xingyun.sc.bo.stock.transfer; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ScTransferProductBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String productId; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String productCode; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String productName; + + /** + * 类目名称 + */ + @ApiModelProperty("类目名称") + private String categoryName; + + /** + * 品牌名称 + */ + @ApiModelProperty("品牌名称") + private String brandName; + + /** + * SKU + */ + @ApiModelProperty("SKU") + private String skuCode; + + /** + * 外部编号 + */ + @ApiModelProperty("外部编号") + private String externalCode; + + /** + * 规格 + */ + @ApiModelProperty("规格") + private String spec; + + /** + * 单位 + */ + @ApiModelProperty("单位") + private String unit; + + /** + * 当前库存数量 + */ + @ApiModelProperty("当前库存数量") + private Integer curStockNum; + + /** + * 仓库ID + */ + @JsonIgnore + @ApiModelProperty(hidden = true) + private String scId; + + public ScTransferProductBo() { + + } + + public ScTransferProductBo(String scId, ScTransferProductDto dto) { + this.scId = scId; + + this.init(dto); + } + + @Override + protected void afterInit(ScTransferProductDto dto) { + + this.productId = dto.getId(); + this.productCode = dto.getCode(); + this.productName = dto.getName(); + + ProductStockService productStockService = ApplicationUtil.getBean( + ProductStockService.class); + ProductStock productStock = productStockService.getByProductIdAndScId(dto.getId(), + this.scId); + this.curStockNum = productStock == null ? 0 : productStock.getStockNum(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/components/code/GenerateCodeTypePool.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/components/code/GenerateCodeTypePool.java new file mode 100644 index 0000000..f0e6e2e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/components/code/GenerateCodeTypePool.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.sc.components.code; + +import com.lframework.starter.web.components.code.GenerateCodeType; + +public interface GenerateCodeTypePool { + + /** + * 采购订单 + */ + GenerateCodeType PURCHASE_ORDER = GenerateCodeType.FLOW; + + /** + * 采购收货单 + */ + GenerateCodeType RECEIVE_SHEET = GenerateCodeType.FLOW; + + /** + * 采购退单 + */ + GenerateCodeType PURCHASE_RETURN = GenerateCodeType.FLOW; + + /** + * 销售订单 + */ + GenerateCodeType SALE_ORDER = GenerateCodeType.FLOW; + + /** + * 销售出库单 + */ + GenerateCodeType SALE_OUT_SHEET = GenerateCodeType.FLOW; + + /** + * 销售退货单 + */ + GenerateCodeType SALE_RETURN = GenerateCodeType.FLOW; + + /** + * 零售出库单 + */ + GenerateCodeType RETAIL_OUT_SHEET = GenerateCodeType.FLOW; + + /** + * 零售退货单 + */ + GenerateCodeType RETAIL_RETURN = GenerateCodeType.FLOW; + + /** + * 预先盘点单 + */ + GenerateCodeType PRE_TAKE_STOCK_SHEET = GenerateCodeType.FLOW; + + /** + * 盘点任务 + */ + GenerateCodeType TAKE_STOCK_PLAN = GenerateCodeType.FLOW; + + /** + * 盘点单 + */ + GenerateCodeType TAKE_STOCK_SHEET = GenerateCodeType.FLOW; + + /** + * 库存成本调整单 + */ + GenerateCodeType STOCK_COST_ADJUST_SHEET = GenerateCodeType.FLOW; + + /** + * 库存调整单 + */ + GenerateCodeType STOCK_ADJUST_SHEET = GenerateCodeType.FLOW; + + /** + * 仓库调拨单 + */ + GenerateCodeType SC_TRANSFER_ORDER = GenerateCodeType.FLOW; + + /** + * 物流单 + */ + GenerateCodeType LOGISTICS_SHEET = GenerateCodeType.FLOW; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ScSelectorController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ScSelectorController.java new file mode 100644 index 0000000..d5f5158 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ScSelectorController.java @@ -0,0 +1,281 @@ +package com.lframework.xingyun.sc.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.paytype.OrderPayTypeBo; +import com.lframework.xingyun.sc.bo.purchase.PurchaseOrderSelectorBo; +import com.lframework.xingyun.sc.bo.purchase.receive.ReceiveSheetSelectorBo; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.reason.StockAdjustReasonSelectorBo; +import com.lframework.xingyun.sc.bo.stock.take.plan.TakeStockPlanSelectorBo; +import com.lframework.xingyun.sc.bo.stock.take.pre.PreTakeStockSheetSelectorBo; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustReasonService; +import com.lframework.xingyun.sc.service.stock.take.PreTakeStockSheetService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.sc.vo.purchase.PurchaseOrderSelectorVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ReceiveSheetSelectorVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.StockAdjustReasonSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.TakeStockPlanSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.PreTakeStockSheetSelectorVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据选择器 + * + * @author zmj + */ +@Api(tags = "数据选择器") +@Validated +@RestController +@RequestMapping("/selector") +public class ScSelectorController extends DefaultBaseController { + + @Autowired + private PurchaseOrderService purchaseOrderService; + + @Autowired + private ReceiveSheetService receiveSheetService; + + @Autowired + private TakeStockPlanService takeStockPlanService; + + @Autowired + private PreTakeStockSheetService preTakeStockSheetService; + + @Autowired + private OrderPayTypeService orderPayTypeService; + + @Autowired + private StockAdjustReasonService stockAdjustReasonService; + + /** + * 采购订单 + */ + @ApiOperation("采购订单") + @GetMapping("/purchaseorder") + public InvokeResult> selector( + @Valid PurchaseOrderSelectorVo vo) { + + PageResult pageResult = purchaseOrderService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(PurchaseOrderSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载采购订单 + */ + @ApiOperation("加载采购订单") + @PostMapping("/purchaseorder/load") + public InvokeResult> loadPurchaseOrder( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = purchaseOrderService.listByIds(ids); + List results = datas.stream().map(PurchaseOrderSelectorBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 采购收货单 + */ + @ApiOperation("采购收货单") + @GetMapping("/receivesheet") + public InvokeResult> selector( + @Valid ReceiveSheetSelectorVo vo) { + + PageResult pageResult = receiveSheetService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(ReceiveSheetSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载采购收货单 + */ + @ApiOperation("加载采购收货单") + @PostMapping("/receivesheet/load") + public InvokeResult> loadReceiveSheet( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = receiveSheetService.listByIds(ids); + List results = datas.stream().map(ReceiveSheetSelectorBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 盘点任务 + */ + @ApiOperation("盘点任务") + @GetMapping("/takestock/plan") + public InvokeResult> selector( + @Valid TakeStockPlanSelectorVo vo) { + + PageResult pageResult = takeStockPlanService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(TakeStockPlanSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载盘点任务 + */ + @ApiOperation("加载盘点任务") + @PostMapping("/takestock/plan/load") + public InvokeResult> loadTakeStockPlan( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = takeStockPlanService.listByIds(ids); + List results = datas.stream().map(TakeStockPlanSelectorBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 预先盘点单 + */ + @ApiOperation("预先盘点单") + @GetMapping("/takestock/pre") + public InvokeResult> selector( + @Valid PreTakeStockSheetSelectorVo vo) { + + PageResult pageResult = preTakeStockSheetService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(PreTakeStockSheetSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载预先盘点单 + */ + @ApiOperation("加载预先盘点单") + @PostMapping("/takestock/pre/load") + public InvokeResult> loadPreTakeStock( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = preTakeStockSheetService.listByIds(ids); + List results = datas.stream().map(PreTakeStockSheetSelectorBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("订单支付方式") + @GetMapping("/paytype/order") + public InvokeResult> getOrderPayType( + @NotBlank(message = "订单ID不能为空!") String orderId) { + List datas = orderPayTypeService.findByOrderId(orderId); + List results = datas.stream().map(OrderPayTypeBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 库存调整原因 + */ + @ApiOperation("库存调整原因") + @GetMapping("/stock/adjust/reason") + public InvokeResult> selector( + @Valid StockAdjustReasonSelectorVo vo) { + + PageResult pageResult = stockAdjustReasonService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(StockAdjustReasonSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载库存调整原因 + */ + @ApiOperation("加载库存调整原因") + @PostMapping("/stock/adjust/reason/load") + public InvokeResult> loadStockAdjustReason( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().map(t -> stockAdjustReasonService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(StockAdjustReasonSelectorBo::new) + .collect(Collectors.toList()); + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/logistics/LogisticsSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/logistics/LogisticsSheetController.java new file mode 100644 index 0000000..e4a1445 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/logistics/LogisticsSheetController.java @@ -0,0 +1,372 @@ +package com.lframework.xingyun.sc.controller.logistics; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.logistics.GetLogisticsSheetBo; +import com.lframework.xingyun.sc.bo.logistics.GetLogisticsSheetDeliveryBo; +import com.lframework.xingyun.sc.bo.logistics.QueryLogisticsSheetBizOrderBo; +import com.lframework.xingyun.sc.bo.logistics.QueryLogisticsSheetBo; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetBizOrderDto; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetFullDto; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.excel.logistics.LogisticsSheetDeliveryImportListener; +import com.lframework.xingyun.sc.excel.logistics.LogisticsSheetDeliveryImportModel; +import com.lframework.xingyun.sc.excel.logistics.LogisticsSheetExportModel; +import com.lframework.xingyun.sc.excel.logistics.LogisticsSheetImportListener; +import com.lframework.xingyun.sc.excel.logistics.LogisticsSheetImportModel; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailService; +import com.lframework.xingyun.sc.vo.logistics.CreateLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.DeliveryLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.LogisticsSheetCalcWeightOrVolumeVo; +import com.lframework.xingyun.sc.vo.logistics.LogisticsSheetCalcWeightOrVolumeVo.BizOrderVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetBizOrderVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.UpdateLogisticsSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 物流单管理 + * + * @author zmj + */ +@Api(tags = "物流单管理") +@Validated +@RestController +@RequestMapping("/logistics/sheet") +public class LogisticsSheetController extends DefaultBaseController { + + @Autowired + private LogisticsSheetService logisticsSheetService; + + @Autowired + private SaleOutSheetDetailService saleOutSheetDetailService; + + @Autowired + private RetailOutSheetDetailService retailOutSheetDetailService; + + /** + * 物流单列表 + */ + @ApiOperation("物流单列表") + @HasPermission({"logistics:sheet:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryLogisticsSheetVo vo) { + + PageResult pageResult = logisticsSheetService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryLogisticsSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"logistics:sheet:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "物流单ID不能为空!") String id) { + + LogisticsSheetFullDto data = logisticsSheetService.getDetail(id); + + GetLogisticsSheetBo result = new GetLogisticsSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 查询业务单据 + */ + @ApiOperation("查询业务单据") + @HasPermission({"logistics:sheet:add", "logistics:sheet:modify"}) + @GetMapping("/biz") + public InvokeResult> queryBizOrder( + @Valid QueryLogisticsSheetBizOrderVo vo) { + + PageResult pageResult = logisticsSheetService.queryBizOrder( + getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryLogisticsSheetBizOrderBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 计算重量 + */ + @ApiOperation("计算重量") + @HasPermission({"logistics:sheet:add", "logistics:sheet:modify"}) + @PostMapping("/calc/weight") + public InvokeResult calcWeight( + @Valid @RequestBody LogisticsSheetCalcWeightOrVolumeVo vo) { + + BigDecimal totalWeight = BigDecimal.ZERO; + + List saleOutSheetIds = new ArrayList<>(); + List retailOutSheetIds = new ArrayList<>(); + + for (BizOrderVo bizOrder : vo.getBizOrders()) { + LogisticsSheetDetailBizType bizType = EnumUtil.getByCode(LogisticsSheetDetailBizType.class, + bizOrder.getBizType()); + + if (bizType == LogisticsSheetDetailBizType.SALE_OUT_SHEET) { + saleOutSheetIds.add(bizOrder.getBizId()); + } else if (bizType == LogisticsSheetDetailBizType.RETAIL_OUT_SHEET) { + retailOutSheetIds.add(bizOrder.getBizId()); + } + } + + if (CollectionUtil.isNotEmpty(saleOutSheetIds)) { + totalWeight = NumberUtil.add(totalWeight, + saleOutSheetDetailService.getTotalWeightBySheetIds(saleOutSheetIds)); + } + + if (CollectionUtil.isNotEmpty(retailOutSheetIds)) { + totalWeight = NumberUtil.add(totalWeight, + retailOutSheetDetailService.getTotalWeightBySheetIds(retailOutSheetIds)); + } + + return InvokeResultBuilder.success(totalWeight); + } + + /** + * 计算体积 + */ + @ApiOperation("计算体积") + @HasPermission({"logistics:sheet:add", "logistics:sheet:modify"}) + @PostMapping("/calc/volume") + public InvokeResult calcVolume( + @Valid @RequestBody LogisticsSheetCalcWeightOrVolumeVo vo) { + + BigDecimal totalVolume = BigDecimal.ZERO; + + List saleOutSheetIds = new ArrayList<>(); + List retailOutSheetIds = new ArrayList<>(); + + for (BizOrderVo bizOrder : vo.getBizOrders()) { + LogisticsSheetDetailBizType bizType = EnumUtil.getByCode(LogisticsSheetDetailBizType.class, + bizOrder.getBizType()); + + if (bizType == LogisticsSheetDetailBizType.SALE_OUT_SHEET) { + saleOutSheetIds.add(bizOrder.getBizId()); + } else if (bizType == LogisticsSheetDetailBizType.RETAIL_OUT_SHEET) { + retailOutSheetIds.add(bizOrder.getBizId()); + } + } + + if (CollectionUtil.isNotEmpty(saleOutSheetIds)) { + totalVolume = NumberUtil.add(totalVolume, + saleOutSheetDetailService.getTotalVolumeBySheetIds(saleOutSheetIds)); + } + + if (CollectionUtil.isNotEmpty(retailOutSheetIds)) { + totalVolume = NumberUtil.add(totalVolume, + retailOutSheetDetailService.getTotalVolumeBySheetIds(retailOutSheetIds)); + } + + return InvokeResultBuilder.success(totalVolume); + } + + /** + * 创建物流单 + */ + @ApiOperation("创建物流单") + @HasPermission({"logistics:sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateLogisticsSheetVo vo) { + + String id = logisticsSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改物流单 + */ + @ApiOperation("修改物流单") + @HasPermission({"logistics:sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateLogisticsSheetVo vo) { + + logisticsSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除物流单 + */ + @ApiOperation("删除物流单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"logistics:sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "物流单ID不能为空!") String id) { + + logisticsSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除物流单 + */ + @ApiOperation("批量删除物流单") + @HasPermission({"logistics:sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的物流单!") List ids) { + + logisticsSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 查询物流单发货信息 + */ + @ApiOperation("查询物流单发货信息") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"logistics:sheet:delivery"}) + @GetMapping("/delivery") + public InvokeResult queryDelivery( + @NotBlank(message = "ID不能为空!") String id) { + + LogisticsSheet sheet = logisticsSheetService.getById(id); + if (sheet == null) { + throw new DefaultClientException("物流单不存在!"); + } + + return InvokeResultBuilder.success(new GetLogisticsSheetDeliveryBo(sheet)); + } + + /** + * 物流单发货 + */ + @ApiOperation("物流单发货") + @HasPermission({"logistics:sheet:delivery"}) + @PutMapping("/delivery") + public InvokeResult delivery(@Valid DeliveryLogisticsSheetVo vo) { + + logisticsSheetService.delivery(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"logistics:sheet:export"}) + @PostMapping("/export") + public void export(@Valid QueryLogisticsSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("物流单信息", + LogisticsSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = logisticsSheetService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(LogisticsSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + @ApiOperation("下载导入模板") + @HasPermission({"logistics:sheet:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("物流单导入模板", LogisticsSheetImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"logistics:sheet:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + LogisticsSheetImportListener listener = new LogisticsSheetImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, LogisticsSheetImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载批量发货模板") + @HasPermission({"logistics:sheet:delivery"}) + @GetMapping("/import/template/delivery") + public void downloadDeliveryImportTemplate() { + ExcelUtil.exportXls("物流单批量发货模板", LogisticsSheetDeliveryImportModel.class); + } + + @ApiOperation("批量发货") + @HasPermission({"logistics:sheet:delivery"}) + @PostMapping("/import/delivery") + public InvokeResult deliveryImportExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + LogisticsSheetDeliveryImportListener listener = new LogisticsSheetDeliveryImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, LogisticsSheetDeliveryImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseConfigController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseConfigController.java new file mode 100644 index 0000000..d023617 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseConfigController.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.sc.controller.purchase; + +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.bo.purchase.config.GetPurchaseConfigBo; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.vo.purchase.config.UpdatePurchaseConfigVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 采购参数设置 + * + * @author zmj + */ +@Api(tags = "采购参数设置") +@Validated +@RestController +@RequestMapping("/purchase/config") +public class PurchaseConfigController extends DefaultBaseController { + + @Autowired + private PurchaseConfigService purchaseConfigService; + + /** + * 查询详情 + */ + @ApiOperation("查询详情") + @GetMapping + public InvokeResult get() { + + PurchaseConfig config = purchaseConfigService.get(); + GetPurchaseConfigBo result = new GetPurchaseConfigBo(config); + + return InvokeResultBuilder.success(result); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@Valid UpdatePurchaseConfigVo vo) { + + purchaseConfigService.update(vo); + + purchaseConfigService.cleanCacheByKey(null); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseOrderController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseOrderController.java new file mode 100644 index 0000000..5e81bfa --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseOrderController.java @@ -0,0 +1,479 @@ +package com.lframework.xingyun.sc.controller.purchase; + +import cn.hutool.extra.spring.SpringUtil; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.purchase.*; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderWithReceiveDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.excel.purchase.*; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.vo.purchase.*; +import com.lframework.xingyun.template.core.entity.SysUser; +import io.swagger.annotations.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 采购订单管理 + * + * @author zmj + */ +@Api(tags = "采购订单管理") +@Validated +@RestController +@RequestMapping("/purchase/order") +public class PurchaseOrderController extends DefaultBaseController { + + @Autowired + private PurchaseOrderService purchaseOrderService; + + @Autowired + private ProductService productService; + + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:order:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "订单ID不能为空!") String id) { + + PurchaseOrderFullDto data = purchaseOrderService.getDetail(id); + if (data == null) { + throw new DefaultClientException("订单不存在!"); + } + + PrintPurchaseOrderBo result = new PrintPurchaseOrderBo(data); + + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo<>( + "print/purchase-order.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 订单列表 + */ + @ApiOperation("订单列表") + @HasPermission({"purchase:order:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryPurchaseOrderVo vo) { + + PageResult pageResult = purchaseOrderService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryPurchaseOrderBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"purchase:order:export"}) + @PostMapping("/export") + public void export(@Valid QueryPurchaseOrderVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("采购单信息", + PurchaseOrderExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = purchaseOrderService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(PurchaseOrderExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:order:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "订单ID不能为空!") String id) { + + PurchaseOrderFullDto data = purchaseOrderService.getDetail(id); + + GetPurchaseOrderBo result = new GetPurchaseOrderBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID查询(收货业务) + */ + @ApiOperation("根据ID查询(收货业务)") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:receive:add", "purchase:receive:modify"}) + @GetMapping("/receive") + public InvokeResult getWithReceive( + @NotBlank(message = "订单ID不能为空!") String id) { + + PurchaseOrderWithReceiveDto data = purchaseOrderService.getWithReceive(id); + PurchaseOrderWithReceiveBo result = new PurchaseOrderWithReceiveBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 查询列表(收货业务) + */ + @ApiOperation("查询列表(收货业务)") + @HasPermission({"purchase:receive:add", "purchase:receive:modify"}) + @GetMapping("/query/receive") + public InvokeResult> queryWithReceive( + @Valid QueryPurchaseOrderWithReceiveVo vo) { + + PageResult pageResult = purchaseOrderService.queryWithReceive(getPageIndex(vo), + getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryPurchaseOrderWithReceiveBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载列表(收货业务) + */ + @ApiOperation("加载列表(收货业务)") + @HasPermission({"purchase:receive:add", "purchase:receive:modify"}) + @PostMapping("/query/receive/load") + public InvokeResult> loadWithReceive( + @RequestBody(required = false) List ids) { + + List datas = purchaseOrderService.listByIds(ids); + + List results = datas.stream() + .map(QueryPurchaseOrderWithReceiveBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 创建订单 + */ + @ApiOperation("创建订单") + @HasPermission({"purchase:order:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreatePurchaseOrderVo vo) { + + vo.validate(); + + String id = purchaseOrderService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改订单 + */ + @ApiOperation("修改订单") + @HasPermission({"purchase:order:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdatePurchaseOrderVo vo) { + + vo.validate(); + + purchaseOrderService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过订单 + */ + @ApiOperation("审核通过订单") + @HasPermission({"purchase:order:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassPurchaseOrderVo vo) { + + purchaseOrderService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过订单 + */ + @ApiOperation("批量审核通过订单") + @HasPermission({"purchase:order:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassPurchaseOrderVo vo) { + + purchaseOrderService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过订单 + */ + @ApiOperation("直接审核通过订单") + @HasPermission({"purchase:order:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreatePurchaseOrderVo vo) { + + purchaseOrderService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝订单 + */ + @ApiOperation("审核拒绝订单") + @HasPermission({"purchase:order:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefusePurchaseOrderVo vo) { + + purchaseOrderService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝订单 + */ + @ApiOperation("批量审核拒绝订单") + @HasPermission({"purchase:order:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefusePurchaseOrderVo vo) { + + purchaseOrderService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除订单 + */ + @ApiOperation("删除订单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:order:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "订单ID不能为空!") String id) { + + purchaseOrderService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除订单 + */ + @ApiOperation("批量删除订单") + @HasPermission({"purchase:order:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的订单!") List ids) { + + purchaseOrderService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 取消审核订单 + */ + @ApiOperation("取消审核订单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:order:approve"}) + @PatchMapping("/approve/cancel") + public InvokeResult cancelApprovePass(@NotBlank(message = "订单ID不能为空!") String id) { + + purchaseOrderService.cancelApprovePass(id); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"purchase:order:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("采购订单导入模板", PurchaseOrderImportModel.class); + } + + @ApiOperation("下载导入约定支付模板") + @HasPermission({"purchase:order:import"}) + @GetMapping("/import/template/paytype") + public void downloadImportPayTypeTemplate() { + ExcelUtil.exportXls("采购订单导入约定支付模板", PurchaseOrderPayTypeImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"purchase:order:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + PurchaseOrderImportListener listener = new PurchaseOrderImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, PurchaseOrderImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("导入约定支付") + @HasPermission({"purchase:order:import"}) + @PostMapping("/import/paytype") + public InvokeResult importPayTypeExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + PurchaseOrderPayTypeImportListener listener = new PurchaseOrderPayTypeImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, PurchaseOrderPayTypeImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } + + /** + * 根据关键字查询商品 + */ + @ApiOperation("根据关键字查询可采购商品") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"purchase:order:add", "purchase:order:modify", "purchase:receive:add", + "purchase:receive:modify", "purchase:return:add", "purchase:return:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchPurchaseProducts( + @NotBlank(message = "仓库ID不能为空!") String scId, String condition) { + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + PageResult pageResult = purchaseOrderService.queryPurchaseByCondition( + getPageIndex(), getPageSize(), condition); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new PurchaseProductBo(scId, t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + + /** + * 根据SKU查询商品 + */ + @ApiOperation("根据SKU查询可采购商品") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "SKU", name = "sku", paramType = "query", required = true)}) + @HasPermission({"purchase:order:add", "purchase:order:modify", "purchase:receive:add", + "purchase:receive:modify", "purchase:return:add", "purchase:return:modify"}) + @GetMapping("/product/sku") + public InvokeResult searchPurchaseProductBySku( + @NotBlank(message = "仓库ID不能为空!") String scId, String sku) { + + if (StringUtil.isBlank(sku)) { + throw new DefaultClientException("SKU不能为空"); + } + + PurchaseProductDto dto = purchaseOrderService.queryPurchaseBySku(sku); + if (dto == null) { + throw new DefaultClientException("该SKU不存在"); + } + PurchaseProductBo bo = new PurchaseProductBo(scId, dto); + + return InvokeResultBuilder.success(bo); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询可采购商品列表") + @HasPermission({"purchase:order:add", "purchase:order:modify", "purchase:receive:add", + "purchase:receive:modify", "purchase:return:add", "purchase:return:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryPurchaseProductList( + @Valid QueryPurchaseProductVo vo) { + + PageResult pageResult = purchaseOrderService.queryPurchaseList( + getPageIndex(vo), + getPageSize(vo), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new PurchaseProductBo(vo.getScId(), t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 发送审批流程给ydool系统 + */ + @ApiOperation("发送审批流程给ydool系统") + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true) + @HasPermission({"purchase:order:send:approve"}) + @PutMapping("/send/approve/{id}") + public InvokeResult sendApprove(@PathVariable("id") String id) { + return purchaseOrderService.sendApprove(id); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseReturnController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseReturnController.java new file mode 100644 index 0000000..dd5d637 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/PurchaseReturnController.java @@ -0,0 +1,273 @@ +package com.lframework.xingyun.sc.controller.purchase; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.purchase.returned.GetPurchaseReturnBo; +import com.lframework.xingyun.sc.bo.purchase.returned.PrintPurchaseReturnBo; +import com.lframework.xingyun.sc.bo.purchase.returned.QueryPurchaseReturnBo; +import com.lframework.xingyun.sc.dto.purchase.returned.PurchaseReturnFullDto; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.excel.purchase.returned.PurchaseReturnExportModel; +import com.lframework.xingyun.sc.service.purchase.PurchaseReturnService; +import com.lframework.xingyun.sc.vo.purchase.returned.ApprovePassPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.ApproveRefusePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.BatchApprovePassPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.BatchApproveRefusePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.CreatePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.QueryPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.UpdatePurchaseReturnVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 采购退单管理 + * + * @author zmj + */ +@Api(tags = "采购退单管理") +@Validated +@RestController +@RequestMapping("/purchase/return") +public class PurchaseReturnController extends DefaultBaseController { + + @Autowired + private PurchaseReturnService purchaseReturnService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:return:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "退单ID不能为空!") String id) { + + PurchaseReturnFullDto data = purchaseReturnService.getDetail(id); + + PrintPurchaseReturnBo result = new PrintPurchaseReturnBo(data); + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo<>( + "print/purchase-return.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 退单列表 + */ + @ApiOperation("退单列表") + @HasPermission({"purchase:return:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryPurchaseReturnVo vo) { + + PageResult pageResult = purchaseReturnService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryPurchaseReturnBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"purchase:return:export"}) + @PostMapping("/export") + public void export(@Valid QueryPurchaseReturnVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("采购退货单信息", + PurchaseReturnExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = purchaseReturnService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(PurchaseReturnExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:return:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "退单ID不能为空!") String id) { + + PurchaseReturnFullDto data = purchaseReturnService.getDetail(id); + + GetPurchaseReturnBo result = new GetPurchaseReturnBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建 + */ + @ApiOperation("创建") + @HasPermission({"purchase:return:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreatePurchaseReturnVo vo) { + + vo.validate(); + + String id = purchaseReturnService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"purchase:return:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdatePurchaseReturnVo vo) { + + vo.validate(); + + purchaseReturnService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"purchase:return:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassPurchaseReturnVo vo) { + + purchaseReturnService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"purchase:return:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassPurchaseReturnVo vo) { + + purchaseReturnService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"purchase:return:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreatePurchaseReturnVo vo) { + + purchaseReturnService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"purchase:return:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefusePurchaseReturnVo vo) { + + purchaseReturnService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"purchase:return:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefusePurchaseReturnVo vo) { + + purchaseReturnService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:return:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "采购退货单ID不能为空!") String id) { + + purchaseReturnService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"purchase:return:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的采购退货单!") List ids) { + + purchaseReturnService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/ReceiveSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/ReceiveSheetController.java new file mode 100644 index 0000000..5b81b35 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/ReceiveSheetController.java @@ -0,0 +1,410 @@ +package com.lframework.xingyun.sc.controller.purchase; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.purchase.receive.GetPaymentDateBo; +import com.lframework.xingyun.sc.bo.purchase.receive.GetReceiveSheetBo; +import com.lframework.xingyun.sc.bo.purchase.receive.PrintReceiveSheetBo; +import com.lframework.xingyun.sc.bo.purchase.receive.QueryReceiveSheetBo; +import com.lframework.xingyun.sc.bo.purchase.receive.QueryReceiveSheetWithReturnBo; +import com.lframework.xingyun.sc.bo.purchase.receive.ReceiveSheetWithReturnBo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetFullDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.excel.purchase.receive.ReceiveSheetExportModel; +import com.lframework.xingyun.sc.excel.purchase.receive.ReceiveSheetImportListener; +import com.lframework.xingyun.sc.excel.purchase.receive.ReceiveSheetImportModel; +import com.lframework.xingyun.sc.excel.purchase.receive.ReceiveSheetPayTypeImportListener; +import com.lframework.xingyun.sc.excel.purchase.receive.ReceiveSheetPayTypeImportModel; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.vo.purchase.receive.ApprovePassReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ApproveRefuseReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.BatchApprovePassReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.BatchApproveRefuseReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.CreateReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.purchase.receive.UpdateReceiveSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 采购收货单管理 + * + * @author zmj + */ +@Api(tags = "采购收货单管理") +@Validated +@RestController +@RequestMapping("/purchase/receive/sheet") +public class ReceiveSheetController extends DefaultBaseController { + + @Autowired + private ReceiveSheetService receiveSheetService; + + @Autowired + private PurchaseConfigService purchaseConfigService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:receive:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "订单ID不能为空!") String id) { + + ReceiveSheetFullDto data = receiveSheetService.getDetail(id); + + PrintReceiveSheetBo result = new PrintReceiveSheetBo(data); + + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo( + "print/receive-sheet.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 订单列表 + */ + @ApiOperation("订单列表") + @HasPermission({"purchase:receive:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryReceiveSheetVo vo) { + + PageResult pageResult = receiveSheetService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryReceiveSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"purchase:receive:export"}) + @PostMapping("/export") + public void export(@Valid QueryReceiveSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("采购收货单信息", + ReceiveSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = receiveSheetService.query(pageIndex, getExportSize(), + vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(ReceiveSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:receive:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "订单ID不能为空!") String id) { + + ReceiveSheetFullDto data = receiveSheetService.getDetail(id); + + GetReceiveSheetBo result = new GetReceiveSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据供应商ID查询默认付款日期 + */ + @ApiOperation("根据供应商ID查询默认付款日期") + @ApiImplicitParam(value = "供应商ID", name = "supplierId", paramType = "query", required = true) + @HasPermission({"purchase:receive:add", "purchase:receive:modify"}) + @GetMapping("/paymentdate") + public InvokeResult getPaymentDate( + @NotBlank(message = "供应商ID不能为空!") String supplierId) { + + GetPaymentDateDto data = receiveSheetService.getPaymentDate(supplierId); + + GetPaymentDateBo result = new GetPaymentDateBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID查询(采购退货业务) + */ + @ApiOperation("根据ID查询(采购退货业务)") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:return:add", "purchase:return:modify"}) + @GetMapping("/return") + public InvokeResult getWithReturn( + @NotBlank(message = "收货单ID不能为空!") String id) { + + ReceiveSheetWithReturnDto data = receiveSheetService.getWithReturn(id); + ReceiveSheetWithReturnBo result = new ReceiveSheetWithReturnBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 查询列表(采购退货业务) + */ + @ApiOperation("查询列表(采购退货业务)") + @HasPermission({"purchase:return:add", "purchase:return:modify"}) + @GetMapping("/query/return") + public InvokeResult> queryWithReturn( + @Valid QueryReceiveSheetWithReturnVo vo) { + + PageResult pageResult = receiveSheetService.queryWithReturn(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryReceiveSheetWithReturnBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载列表(采购退货业务) + */ + @ApiOperation("加载列表(采购退货业务)") + @HasPermission({"purchase:return:add", "purchase:return:modify"}) + @PostMapping("/query/return/load") + public InvokeResult> loadWithReturn( + @RequestBody(required = false) List ids) { + + List datas = receiveSheetService.listByIds(ids); + + List results = datas.stream() + .map(QueryReceiveSheetWithReturnBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 创建 + */ + @ApiOperation("创建") + @HasPermission({"purchase:receive:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateReceiveSheetVo vo) { + + vo.validate(); + + String id = receiveSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"purchase:receive:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateReceiveSheetVo vo) { + + vo.validate(); + + receiveSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"purchase:receive:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassReceiveSheetVo vo) { + + receiveSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"purchase:receive:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassReceiveSheetVo vo) { + + receiveSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"purchase:receive:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateReceiveSheetVo vo) { + + receiveSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"purchase:receive:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseReceiveSheetVo vo) { + + receiveSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"purchase:receive:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseReceiveSheetVo vo) { + + receiveSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"purchase:receive:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "采购收货单ID不能为空!") String id) { + + receiveSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"purchase:receive:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的采购收货单!") List ids) { + + receiveSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("下载导入模板") + @HasPermission({"purchase:receive:import"}) + @GetMapping("/import/template") + public void downloadImportTemplate() { + ExcelUtil.exportXls("采购收货单导入模板", ReceiveSheetImportModel.class); + } + + @ApiOperation("下载导入支付方式模板") + @HasPermission({"purchase:receive:import"}) + @GetMapping("/import/template/paytype") + public void downloadImportPayTypeTemplate() { + ExcelUtil.exportXls("采购收货单导入支付方式模板", ReceiveSheetPayTypeImportModel.class); + } + + @ApiOperation("导入") + @HasPermission({"purchase:receive:import"}) + @PostMapping("/import") + public InvokeResult importExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + PurchaseConfig config = purchaseConfigService.get(); + if (config.getReceiveRequirePurchase()) { + throw new DefaultClientException("“采购收货单是否关联采购订单”必须设置为“否”才可以导入!"); + } + + ReceiveSheetImportListener listener = new ReceiveSheetImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, ReceiveSheetImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("导入支付方式") + @HasPermission({"purchase:receive:import"}) + @PostMapping("/import/paytype") + public InvokeResult importPayTypeExcel(@NotBlank(message = "ID不能为空") String id, + @NotNull(message = "请上传文件") MultipartFile file) { + + ReceiveSheetPayTypeImportListener listener = new ReceiveSheetPayTypeImportListener(); + listener.setTaskId(id); + ExcelUtil.read(file, ReceiveSheetPayTypeImportModel.class, listener).sheet().doRead(); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailConfigController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailConfigController.java new file mode 100644 index 0000000..ffc2315 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailConfigController.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.sc.controller.retail; + +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.bo.retail.config.GetRetailConfigBo; +import com.lframework.xingyun.sc.entity.RetailConfig; +import com.lframework.xingyun.sc.service.retail.RetailConfigService; +import com.lframework.xingyun.sc.vo.retail.config.UpdateRetailConfigVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 零售参数设置 + * + * @author zmj + */ +@Api(tags = "零售参数设置") +@Validated +@RestController +@RequestMapping("/retail/config") +public class RetailConfigController extends DefaultBaseController { + + @Autowired + private RetailConfigService retailConfigService; + + /** + * 查询详情 + */ + @ApiOperation("查询详情") + @GetMapping + public InvokeResult get() { + + RetailConfig config = retailConfigService.get(); + GetRetailConfigBo result = new GetRetailConfigBo(config); + + return InvokeResultBuilder.success(result); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@Valid UpdateRetailConfigVo vo) { + + retailConfigService.update(vo); + + retailConfigService.cleanCacheByKey(null); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailOutSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailOutSheetController.java new file mode 100644 index 0000000..fba188d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailOutSheetController.java @@ -0,0 +1,425 @@ +package com.lframework.xingyun.sc.controller.retail; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.purchase.receive.GetPaymentDateBo; +import com.lframework.xingyun.sc.bo.retail.RetailProductBo; +import com.lframework.xingyun.sc.bo.retail.out.GetRetailOutSheetBo; +import com.lframework.xingyun.sc.bo.retail.out.PrintRetailOutSheetBo; +import com.lframework.xingyun.sc.bo.retail.out.QueryRetailOutSheetBo; +import com.lframework.xingyun.sc.bo.retail.out.QueryRetailOutSheetWithReturnBo; +import com.lframework.xingyun.sc.bo.retail.out.RetailOutSheetWithReturnBo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetFullDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.excel.retail.out.RetailOutSheetExportModel; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.vo.retail.out.ApprovePassRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.ApproveRefuseRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.BatchApprovePassRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.BatchApproveRefuseRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.CreateRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailProductVo; +import com.lframework.xingyun.sc.vo.retail.out.UpdateRetailOutSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 零售出库单管理 + * + * @author zmj + */ +@Api(tags = "零售出库单管理") +@Validated +@RestController +@RequestMapping("/retail/out/sheet") +public class RetailOutSheetController extends DefaultBaseController { + + @Autowired + private RetailOutSheetService retailOutSheetService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:out:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "订单ID不能为空!") String id) { + + RetailOutSheetFullDto data = retailOutSheetService.getDetail(id); + if (data == null) { + throw new DefaultClientException("零售出库单不存在!"); + } + + PrintRetailOutSheetBo result = new PrintRetailOutSheetBo(data); + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo<>( + "print/retail-out-sheet.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 订单列表 + */ + @ApiOperation("订单列表") + @HasPermission({"retail:out:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryRetailOutSheetVo vo) { + + PageResult pageResult = retailOutSheetService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(QueryRetailOutSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"retail:out:export"}) + @PostMapping("/export") + public void export(@Valid QueryRetailOutSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("零售出库单信息", + RetailOutSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = retailOutSheetService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(RetailOutSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:out:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "订单ID不能为空!") String id) { + + RetailOutSheetFullDto data = retailOutSheetService.getDetail(id); + + GetRetailOutSheetBo result = new GetRetailOutSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据会员ID查询默认付款日期 + */ + @ApiOperation("根据会员ID查询默认付款日期") + @ApiImplicitParam(value = "会员ID", name = "memberId", paramType = "query") + @HasPermission({"retail:out:add", "retail:out:modify"}) + @GetMapping("/paymentdate") + public InvokeResult getPaymentDate(String memberId) { + + GetPaymentDateDto data = retailOutSheetService.getPaymentDate(memberId); + + GetPaymentDateBo result = new GetPaymentDateBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID查询(零售退货业务) + */ + @ApiOperation("根据ID查询(零售退货业务)") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:return:add", "retail:return:modify"}) + @GetMapping("/return") + public InvokeResult getWithReturn( + @NotBlank(message = "出库单ID不能为空!") String id) { + + RetailOutSheetWithReturnDto data = retailOutSheetService.getWithReturn(id); + RetailOutSheetWithReturnBo result = new RetailOutSheetWithReturnBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 查询列表(零售退货业务) + */ + @ApiOperation("查询列表(零售退货业务)") + @HasPermission({"retail:return:add", "retail:return:modify"}) + @GetMapping("/query/return") + public InvokeResult> queryWithReturn( + @Valid QueryRetailOutSheetWithReturnVo vo) { + + PageResult pageResult = retailOutSheetService.queryWithReturn(getPageIndex(vo), + getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryRetailOutSheetWithReturnBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载列表(零售退货业务) + */ + @ApiOperation("加载列表(零售退货业务)") + @HasPermission({"retail:return:add", "retail:return:modify"}) + @PostMapping("/query/return/load") + public InvokeResult> loadWithReturn( + @RequestBody(required = false) List ids) { + + List datas = retailOutSheetService.listByIds(ids); + + List results = datas.stream() + .map(QueryRetailOutSheetWithReturnBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 创建 + */ + @ApiOperation("创建") + @HasPermission({"retail:out:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateRetailOutSheetVo vo) { + + vo.validate(); + + String id = retailOutSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"retail:out:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateRetailOutSheetVo vo) { + + vo.validate(); + + retailOutSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"retail:out:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassRetailOutSheetVo vo) { + + retailOutSheetService.approvePass(vo); + + RetailOutSheet outSheet = retailOutSheetService.getById(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"retail:out:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassRetailOutSheetVo vo) { + + retailOutSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"retail:out:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateRetailOutSheetVo vo) { + + retailOutSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"retail:out:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseRetailOutSheetVo vo) { + + retailOutSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"retail:out:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseRetailOutSheetVo vo) { + + retailOutSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:out:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "零售出库单ID不能为空!") String id) { + + retailOutSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"retail:out:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的零售出库单!") List ids) { + + retailOutSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 根据关键字查询商品 + */ + @ApiOperation("根据关键字查询可零售商品") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"retail:out:add", "retail:out:modify", "retail:return:add", + "retail:return:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchRetailProducts( + @NotBlank(message = "仓库ID不能为空!") String scId, String condition, Boolean isReturn) { + + if (isReturn == null) { + isReturn = false; + } + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + PageResult pageResult = retailOutSheetService.queryRetailByCondition( + getPageIndex(), + getPageSize(), condition, isReturn); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new RetailProductBo(scId, t)).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询可零售商品列表") + @HasPermission({"retail:out:add", "retail:out:modify", "retail:return:add", + "retail:return:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryRetailProductList( + @Valid QueryRetailProductVo vo) { + + PageResult pageResult = retailOutSheetService.queryRetailList( + getPageIndex(vo), + getPageSize(vo), vo); + List results = null; + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new RetailProductBo(vo.getScId(), t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 发送审批流程给ydool系统 + */ + @ApiOperation("发送审批流程给ydool系统") + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true) + @HasPermission({"retail:out:send:approve"}) + @PutMapping("/send/approve/{id}") + public InvokeResult sendApprove(@PathVariable("id") String id) { + return retailOutSheetService.sendApprove(id); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailReturnController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailReturnController.java new file mode 100644 index 0000000..bb3aedb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/retail/RetailReturnController.java @@ -0,0 +1,279 @@ +package com.lframework.xingyun.sc.controller.retail; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.retail.returned.GetRetailReturnBo; +import com.lframework.xingyun.sc.bo.retail.returned.PrintRetailReturnBo; +import com.lframework.xingyun.sc.bo.retail.returned.QueryRetailReturnBo; +import com.lframework.xingyun.sc.dto.retail.returned.RetailReturnFullDto; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.excel.retail.returned.RetailReturnExportModel; +import com.lframework.xingyun.sc.service.retail.RetailReturnService; +import com.lframework.xingyun.sc.vo.retail.returned.ApprovePassRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.ApproveRefuseRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.BatchApprovePassRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.BatchApproveRefuseRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.CreateRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.QueryRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.UpdateRetailReturnVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 零售退单管理 + * + * @author zmj + */ +@Api(tags = "零售退单管理") +@Validated +@RestController +@RequestMapping("/retail/return") +public class RetailReturnController extends DefaultBaseController { + + @Autowired + private RetailReturnService retailReturnService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:return:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "退单ID不能为空!") String id) { + + RetailReturnFullDto data = retailReturnService.getDetail(id); + if (data == null) { + throw new DefaultClientException("零售退货单不存在!"); + } + + PrintRetailReturnBo result = new PrintRetailReturnBo(data); + + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo<>( + "print/retail-return.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 退单列表 + */ + @ApiOperation("退单列表") + @HasPermission({"retail:return:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryRetailReturnVo vo) { + + PageResult pageResult = retailReturnService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryRetailReturnBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"retail:return:export"}) + @PostMapping("/export") + public void export(@Valid QueryRetailReturnVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("零售退货单信息", + RetailReturnExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = retailReturnService.query(pageIndex, getExportSize(), + vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(RetailReturnExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:return:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "退单ID不能为空!") String id) { + + RetailReturnFullDto data = retailReturnService.getDetail(id); + + GetRetailReturnBo result = new GetRetailReturnBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建 + */ + @ApiOperation("创建") + @HasPermission({"retail:return:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateRetailReturnVo vo) { + + vo.validate(); + + String id = retailReturnService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"retail:return:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateRetailReturnVo vo) { + + vo.validate(); + + retailReturnService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"retail:return:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassRetailReturnVo vo) { + + retailReturnService.approvePass(vo); + + RetailReturn r = retailReturnService.getById(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"retail:return:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassRetailReturnVo vo) { + + retailReturnService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"retail:return:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateRetailReturnVo vo) { + + retailReturnService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"retail:return:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseRetailReturnVo vo) { + + retailReturnService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"retail:return:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseRetailReturnVo vo) { + + retailReturnService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"retail:return:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "零售退货单ID不能为空!") String id) { + + retailReturnService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"retail:return:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的零售退货单!") List ids) { + + retailReturnService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleConfigController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleConfigController.java new file mode 100644 index 0000000..fad5cb0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleConfigController.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.sc.controller.sale; + +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.bo.sale.config.GetSaleConfigBo; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.vo.sale.config.UpdateSaleConfigVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 销售参数设置 + * + * @author zmj + */ +@Api(tags = "销售参数设置") +@Validated +@RestController +@RequestMapping("/sale/config") +public class SaleConfigController extends DefaultBaseController { + + @Autowired + private SaleConfigService saleConfigService; + + /** + * 查询详情 + */ + @ApiOperation("查询详情") + @GetMapping + public InvokeResult get() { + + SaleConfig config = saleConfigService.get(); + GetSaleConfigBo result = new GetSaleConfigBo(config); + + return InvokeResultBuilder.success(result); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@Valid UpdateSaleConfigVo vo) { + + saleConfigService.update(vo); + + saleConfigService.cleanCacheByKey(null); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOrderController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOrderController.java new file mode 100644 index 0000000..7346ab9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOrderController.java @@ -0,0 +1,398 @@ +package com.lframework.xingyun.sc.controller.sale; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.sale.GetSaleOrderBo; +import com.lframework.xingyun.sc.bo.sale.PrintSaleOrderBo; +import com.lframework.xingyun.sc.bo.sale.QuerySaleOrderBo; +import com.lframework.xingyun.sc.bo.sale.QuerySaleOrderWithOutBo; +import com.lframework.xingyun.sc.bo.sale.SaleOrderWithOutBo; +import com.lframework.xingyun.sc.bo.sale.SaleProductBo; +import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto; +import com.lframework.xingyun.sc.dto.sale.SaleOrderWithOutDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.excel.sale.SaleOrderExportModel; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.vo.sale.ApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.ApproveRefuseSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.BatchApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.BatchApproveRefuseSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.CreateSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderWithOutVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleProductVo; +import com.lframework.xingyun.sc.vo.sale.UpdateSaleOrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 销售订单管理 + * + * @author zmj + */ +@Api(tags = "销售订单管理") +@Validated +@RestController +@RequestMapping("/sale/order") +public class SaleOrderController extends DefaultBaseController { + + @Autowired + private SaleOrderService saleOrderService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:order:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "订单ID不能为空!") String id) { + + SaleOrderFullDto data = saleOrderService.getDetail(id); + if (data == null) { + throw new DefaultClientException("订单不存在!"); + } + + PrintSaleOrderBo result = new PrintSaleOrderBo(data); + + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo<>( + "print/sale-order.ftl", + result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 订单列表 + */ + @ApiOperation("订单列表") + @HasPermission({"sale:order:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySaleOrderVo vo) { + + PageResult pageResult = saleOrderService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySaleOrderBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"sale:order:export"}) + @PostMapping("/export") + public void export(@Valid QuerySaleOrderVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("销售单信息", + SaleOrderExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = saleOrderService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SaleOrderExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:order:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "订单ID不能为空!") String id) { + + SaleOrderFullDto data = saleOrderService.getDetail(id); + + GetSaleOrderBo result = new GetSaleOrderBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID查询(出库业务) + */ + @ApiOperation("根据ID查询(出库业务)") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:out:add", "sale:out:modify"}) + @GetMapping("/out") + public InvokeResult getWithOut( + @NotBlank(message = "订单ID不能为空!") String id) { + + SaleOrderWithOutDto data = saleOrderService.getWithOut(id); + SaleOrderWithOutBo result = new SaleOrderWithOutBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 查询列表(出库业务) + */ + @ApiOperation("查询列表(出库业务)") + @HasPermission({"sale:out:add", "sale:out:modify"}) + @GetMapping("/query/out") + public InvokeResult> queryWithOut( + @Valid QuerySaleOrderWithOutVo vo) { + + PageResult pageResult = saleOrderService.queryWithOut(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySaleOrderWithOutBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载列表(出库业务) + */ + @ApiOperation("加载列表(出库业务)") + @HasPermission({"sale:out:add", "sale:out:modify"}) + @PostMapping("/query/out/load") + public InvokeResult> getWithOut( + @RequestBody(required = false) List ids) { + + List datas = saleOrderService.listByIds(ids); + + List results = datas.stream() + .map(QuerySaleOrderWithOutBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 创建订单 + */ + @ApiOperation("创建订单") + @HasPermission({"sale:order:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSaleOrderVo vo) { + + vo.validate(); + + String id = saleOrderService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改订单 + */ + @ApiOperation("修改订单") + @HasPermission({"sale:order:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSaleOrderVo vo) { + + vo.validate(); + + saleOrderService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过订单 + */ + @ApiOperation("审核通过订单") + @HasPermission({"sale:order:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSaleOrderVo vo) { + + saleOrderService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过订单 + */ + @ApiOperation("批量审核通过订单") + @HasPermission({"sale:order:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass(@RequestBody @Valid BatchApprovePassSaleOrderVo vo) { + + saleOrderService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过订单 + */ + @ApiOperation("直接审核通过订单") + @HasPermission({"sale:order:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSaleOrderVo vo) { + + saleOrderService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝订单 + */ + @ApiOperation("审核拒绝订单") + @HasPermission({"sale:order:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSaleOrderVo vo) { + + saleOrderService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝订单 + */ + @ApiOperation("批量审核拒绝订单") + @HasPermission({"sale:order:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseSaleOrderVo vo) { + + saleOrderService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除订单 + */ + @ApiOperation("删除订单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:order:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "订单ID不能为空!") String id) { + + saleOrderService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除订单 + */ + @ApiOperation("批量删除订单") + @HasPermission({"sale:order:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的订单!") List ids) { + + saleOrderService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 根据关键字查询商品 + */ + @ApiOperation("根据关键字查询可销售商品") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"sale:order:add", "sale:order:modify", "sale:out:add", "sale:out:modify", + "sale:return:add", "sale:return:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchSaleProducts( + @NotBlank(message = "仓库ID不能为空!") String scId, String condition, Boolean isReturn) { + + if (isReturn == null) { + isReturn = false; + } + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + PageResult pageResult = saleOrderService.querySaleByCondition(getPageIndex(), + getPageSize(), condition, isReturn); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new SaleProductBo(scId, t)).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询可销售商品列表") + @HasPermission({"sale:order:add", "sale:order:modify", "sale:out:add", "sale:out:modify", + "sale:return:add", "sale:return:modify"}) + @GetMapping("/product/list") + public InvokeResult> querySaleProductList( + @Valid QuerySaleProductVo vo) { + + PageResult pageResult = saleOrderService.querySaleList(getPageIndex(vo), + getPageSize(vo), vo); + List results = null; + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new SaleProductBo(vo.getScId(), t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 发送审批流程给ydool系统 + */ + @ApiOperation("发送审批流程给ydool系统") + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true) + @HasPermission({"sale:order:send:approve"}) + @PutMapping("/send/approve/{id}") + public InvokeResult sendApprove(@PathVariable("id") String id) { + return saleOrderService.sendApprove(id); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOutSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOutSheetController.java new file mode 100644 index 0000000..da5755f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleOutSheetController.java @@ -0,0 +1,358 @@ +package com.lframework.xingyun.sc.controller.sale; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.purchase.receive.GetPaymentDateBo; +import com.lframework.xingyun.sc.bo.sale.out.GetSaleOutSheetBo; +import com.lframework.xingyun.sc.bo.sale.out.PrintSaleOutSheetBo; +import com.lframework.xingyun.sc.bo.sale.out.QuerySaleOutSheetBo; +import com.lframework.xingyun.sc.bo.sale.out.QuerySaleOutSheetWithReturnBo; +import com.lframework.xingyun.sc.bo.sale.out.SaleOutSheetWithReturnBo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetFullDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.excel.sale.out.SaleOutSheetExportModel; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.sc.vo.sale.out.ApprovePassSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.ApproveRefuseSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.BatchApprovePassSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.BatchApproveRefuseSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.CreateSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.sale.out.UpdateSaleOutSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 销售出库单管理 + * + * @author zmj + */ +@Api(tags = "销售出库单管理") +@Validated +@RestController +@RequestMapping("/sale/out/sheet") +public class SaleOutSheetController extends DefaultBaseController { + + @Autowired + private SaleOutSheetService saleOutSheetService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:out:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "订单ID不能为空!") String id) { + + SaleOutSheetFullDto data = saleOutSheetService.getDetail(id); + if (data == null) { + throw new DefaultClientException("销售出库单不存在!"); + } + + PrintSaleOutSheetBo result = new PrintSaleOutSheetBo(data); + + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo<>( + "print/sale-out-sheet.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 订单列表 + */ + @ApiOperation("订单列表") + @HasPermission({"sale:out:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySaleOutSheetVo vo) { + + PageResult pageResult = saleOutSheetService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySaleOutSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"sale:out:export"}) + @PostMapping("/export") + public void export(@Valid QuerySaleOutSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("销售出库单信息", + SaleOutSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = saleOutSheetService.query(pageIndex, getExportSize(), + vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SaleOutSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:out:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "订单ID不能为空!") String id) { + + SaleOutSheetFullDto data = saleOutSheetService.getDetail(id); + + GetSaleOutSheetBo result = new GetSaleOutSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据客户ID查询默认付款日期 + */ + @ApiOperation("根据客户ID查询默认付款日期") + @ApiImplicitParam(value = "客户ID", name = "customerId", paramType = "query", required = true) + @HasPermission({"sale:out:add", "sale:out:modify"}) + @GetMapping("/paymentdate") + public InvokeResult getPaymentDate( + @NotBlank(message = "客户ID不能为空!") String customerId) { + + GetPaymentDateDto data = saleOutSheetService.getPaymentDate(customerId); + + GetPaymentDateBo result = new GetPaymentDateBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID查询(销售退货业务) + */ + @ApiOperation("根据ID查询(销售退货业务)") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:return:add", "sale:return:modify"}) + @GetMapping("/return") + public InvokeResult getWithReturn( + @NotBlank(message = "出库单ID不能为空!") String id) { + + SaleOutSheetWithReturnDto data = saleOutSheetService.getWithReturn(id); + SaleOutSheetWithReturnBo result = new SaleOutSheetWithReturnBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 查询列表(销售退货业务) + */ + @ApiOperation("查询列表(销售退货业务)") + @HasPermission({"sale:return:add", "sale:return:modify"}) + @GetMapping("/query/return") + public InvokeResult> queryWithReturn( + @Valid QuerySaleOutSheetWithReturnVo vo) { + + PageResult pageResult = saleOutSheetService.queryWithReturn(getPageIndex(vo), + getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySaleOutSheetWithReturnBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载列表(销售退货业务) + */ + @ApiOperation("加载列表(销售退货业务)") + @HasPermission({"sale:return:add", "sale:return:modify"}) + @PostMapping("/query/return/load") + public InvokeResult> loadWithReturn( + @RequestBody(required = false) List ids) { + + List datas = saleOutSheetService.listByIds(ids); + + List results = datas.stream() + .map(QuerySaleOutSheetWithReturnBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 创建 + */ + @ApiOperation("创建") + @HasPermission({"sale:out:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSaleOutSheetVo vo) { + + vo.validate(); + + String id = saleOutSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"sale:out:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSaleOutSheetVo vo) { + + vo.validate(); + + saleOutSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"sale:out:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSaleOutSheetVo vo) { + + saleOutSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"sale:out:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassSaleOutSheetVo vo) { + + saleOutSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"sale:out:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSaleOutSheetVo vo) { + + saleOutSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"sale:out:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSaleOutSheetVo vo) { + + saleOutSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"sale:out:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseSaleOutSheetVo vo) { + + saleOutSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:out:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "销售出库单ID不能为空!") String id) { + + saleOutSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"sale:out:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的销售出库单!") List ids) { + + saleOutSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleReturnController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleReturnController.java new file mode 100644 index 0000000..6d39a37 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/sale/SaleReturnController.java @@ -0,0 +1,276 @@ +package com.lframework.xingyun.sc.controller.sale; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.bo.print.A4ExcelPortraitPrintBo; +import com.lframework.xingyun.sc.bo.sale.returned.GetSaleReturnBo; +import com.lframework.xingyun.sc.bo.sale.returned.PrintSaleReturnBo; +import com.lframework.xingyun.sc.bo.sale.returned.QuerySaleReturnBo; +import com.lframework.xingyun.sc.dto.sale.returned.SaleReturnFullDto; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.excel.sale.returned.SaleReturnExportModel; +import com.lframework.xingyun.sc.service.sale.SaleReturnService; +import com.lframework.xingyun.sc.vo.sale.returned.ApprovePassSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.ApproveRefuseSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.BatchApprovePassSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.BatchApproveRefuseSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.CreateSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.QuerySaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.UpdateSaleReturnVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 销售退单管理 + * + * @author zmj + */ +@Api(tags = "销售退单管理") +@Validated +@RestController +@RequestMapping("/sale/return") +public class SaleReturnController extends DefaultBaseController { + + @Autowired + private SaleReturnService saleReturnService; + + /** + * 打印 + */ + @ApiOperation("打印") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:return:query"}) + @GetMapping("/print") + public InvokeResult> print( + @NotBlank(message = "退单ID不能为空!") String id) { + + SaleReturnFullDto data = saleReturnService.getDetail(id); + + if (data == null) { + throw new DefaultClientException("销售退单不存在!"); + } + + PrintSaleReturnBo result = new PrintSaleReturnBo(data); + + A4ExcelPortraitPrintBo printResult = new A4ExcelPortraitPrintBo( + "print/sale-return.ftl", result); + + return InvokeResultBuilder.success(printResult); + } + + /** + * 退单列表 + */ + @ApiOperation("退单列表") + @HasPermission({"sale:return:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySaleReturnVo vo) { + + PageResult pageResult = saleReturnService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySaleReturnBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"sale:return:export"}) + @PostMapping("/export") + public void export(@Valid QuerySaleReturnVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("销售退货单信息", + SaleReturnExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = saleReturnService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SaleReturnExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:return:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "退单ID不能为空!") String id) { + + SaleReturnFullDto data = saleReturnService.getDetail(id); + + GetSaleReturnBo result = new GetSaleReturnBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建 + */ + @ApiOperation("创建") + @HasPermission({"sale:return:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSaleReturnVo vo) { + + vo.validate(); + + String id = saleReturnService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"sale:return:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSaleReturnVo vo) { + + vo.validate(); + + saleReturnService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"sale:return:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSaleReturnVo vo) { + + saleReturnService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"sale:return:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass(@RequestBody @Valid BatchApprovePassSaleReturnVo vo) { + + saleReturnService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"sale:return:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSaleReturnVo vo) { + + saleReturnService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"sale:return:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSaleReturnVo vo) { + + saleReturnService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"sale:return:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseSaleReturnVo vo) { + + saleReturnService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"sale:return:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "销售退货单ID不能为空!") String id) { + + saleReturnService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"sale:return:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的销售退货单!") List ids) { + + saleReturnService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockController.java new file mode 100644 index 0000000..0567ceb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockController.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.sc.controller.stock; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.product.QueryProductStockBo; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.excel.stock.ProductStockExportModel; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.stock.QueryProductStockVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 商品库存 + * + * @author zmj + */ +@Api(tags = "商品库存") +@Validated +@RestController +@RequestMapping("/stock/product") +public class ProductStockController extends DefaultBaseController { + + @Autowired + private ProductStockService productStockService; + + /** + * 查询商品库存 + */ + @ApiOperation("查询商品库存") + @HasPermission({"stock:product:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryProductStockVo vo) { + + PageResult pageResult = productStockService.query(getPageIndex(vo), + getPageSize(vo), vo); + List results = null; + + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryProductStockBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出商品库存 + */ + @ApiOperation("导出商品库存") + @HasPermission({"stock:product:export"}) + @GetMapping("/export") + public void export(@Valid QueryProductStockVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("商品库存信息", + ProductStockExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = productStockService.query(pageIndex, getExportSize(), + vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(ProductStockExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockLogController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockLogController.java new file mode 100644 index 0000000..68e25fd --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/ProductStockLogController.java @@ -0,0 +1,93 @@ +package com.lframework.xingyun.sc.controller.stock; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.product.log.QueryProductStockLogBo; +import com.lframework.xingyun.sc.entity.ProductStockLog; +import com.lframework.xingyun.sc.excel.stock.ProductStockLogExportModel; +import com.lframework.xingyun.sc.service.stock.ProductStockLogService; +import com.lframework.xingyun.sc.vo.stock.log.QueryProductStockLogVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 商品库存变动记录 + * + * @author zmj + */ +@Api(tags = "商品库存变动记录") +@Validated +@RestController +@RequestMapping("/stock/product/log") +public class ProductStockLogController extends DefaultBaseController { + + @Autowired + private ProductStockLogService productStockLogService; + + /** + * 查询商品库存变动记录 + */ + @ApiOperation("查询商品库存变动记录") + @HasPermission({"stock:product-log:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryProductStockLogVo vo) { + + PageResult pageResult = productStockLogService.query(getPageIndex(vo), + getPageSize(vo), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryProductStockLogBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出商品库存变动记录 + */ + @ApiOperation("导出商品库存变动记录") + @HasPermission({"stock:product-log:export"}) + @GetMapping("/export") + public void export(@Valid QueryProductStockLogVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("商品库存变动记录信息", + ProductStockLogExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = productStockLogService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(ProductStockLogExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustReasonController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustReasonController.java new file mode 100644 index 0000000..a94bf6e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustReasonController.java @@ -0,0 +1,157 @@ +package com.lframework.xingyun.sc.controller.stock.adjust; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.reason.GetStockAdjustReasonBo; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.reason.QueryStockAdjustReasonBo; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustReasonService; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.CreateStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.QueryStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.UpdateStockAdjustReasonVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 库存调整原因 + * + * @author zmj + */ +@Api(tags = "库存调整原因") +@Validated +@RestController +@RequestMapping("/stock/adjust/reason") +public class StockAdjustReasonController extends DefaultBaseController { + + @Autowired + private StockAdjustReasonService stockAdjustReasonService; + + /** + * 库存调整原因列表 + */ + @ApiOperation("库存调整原因列表") + @HasPermission({"stock:adjust:reason:query", "stock:adjust:reason:add", + "stock:adjust:reason:modify"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryStockAdjustReasonVo vo) { + + PageResult pageResult = stockAdjustReasonService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryStockAdjustReasonBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询库存调整原因 + */ + @ApiOperation("查询库存调整原因") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:adjust:reason:query", "stock:adjust:reason:add", + "stock:adjust:reason:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + StockAdjustReason data = stockAdjustReasonService.findById(id); + if (data == null) { + throw new DefaultClientException("库存调整原因不存在!"); + } + + GetStockAdjustReasonBo result = new GetStockAdjustReasonBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用库存调整原因 + */ + @ApiOperation("批量停用库存调整原因") + @HasPermission({"stock:adjust:reason:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的库存调整原因!") @RequestBody List ids) { + + stockAdjustReasonService.batchUnable(ids); + + for (String id : ids) { + stockAdjustReasonService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用库存调整原因 + */ + @ApiOperation("批量启用库存调整原因") + @HasPermission({"stock:adjust:reason:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的库存调整原因!") @RequestBody List ids) { + + stockAdjustReasonService.batchEnable(ids); + + for (String id : ids) { + stockAdjustReasonService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增库存调整原因 + */ + @ApiOperation("新增库存调整原因") + @HasPermission({"stock:adjust:reason:add"}) + @PostMapping + public InvokeResult create(@Valid CreateStockAdjustReasonVo vo) { + + stockAdjustReasonService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改库存调整原因 + */ + @ApiOperation("修改库存调整原因") + @HasPermission({"stock:adjust:reason:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateStockAdjustReasonVo vo) { + + stockAdjustReasonService.update(vo); + + stockAdjustReasonService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustSheetController.java new file mode 100644 index 0000000..5064192 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockAdjustSheetController.java @@ -0,0 +1,347 @@ +package com.lframework.xingyun.sc.controller.stock.adjust; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.QueryStockAdjustSheetBo; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.StockAdjustProductBo; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.StockAdjustSheetFullBo; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockAdjustSheet; +import com.lframework.xingyun.sc.excel.stock.adjust.StockAdjustSheetExportModel; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustSheetService; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.ApprovePassStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.ApproveRefuseStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.BatchApprovePassStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.BatchApproveRefuseStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.CreateStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.UpdateStockAdjustSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 库存调整单 Controller + * + * @author zmj + */ +@Api(tags = "库存调整单") +@Validated +@RestController +@RequestMapping("/stock/adjust") +public class StockAdjustSheetController extends DefaultBaseController { + + @Autowired + private StockAdjustSheetService stockAdjustSheetService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"stock:adjust:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryStockAdjustSheetVo vo) { + + PageResult pageResult = stockAdjustSheetService.query( + getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryStockAdjustSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:adjust:query"}) + @GetMapping("/detail") + public InvokeResult getDetail( + @NotBlank(message = "id不能为空!") String id) { + + StockAdjustSheetFullDto data = stockAdjustSheetService.getDetail(id); + if (data == null) { + throw new DefaultClientException("库存调整单不存在!"); + } + + StockAdjustSheetFullBo result = new StockAdjustSheetFullBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"stock:adjust:export"}) + @PostMapping("/export") + public void export(@Valid QueryStockAdjustSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("库存调整单信息", + StockAdjustSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = stockAdjustSheetService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(StockAdjustSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据关键字查询商品列表 + */ + @ApiOperation("根据关键字查询商品列表") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"stock:adjust:add", "stock:adjust:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchProducts( + @NotBlank(message = "仓库ID不能为空!") String scId, + String condition) { + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + PageResult pageResult = stockAdjustSheetService.queryStockAdjustByCondition( + getPageIndex(), getPageSize(), scId, condition); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new StockAdjustProductBo(scId, t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据扫码信息SKU查询商品信息 + */ + @ApiOperation("根据扫码信息SKU查询商品信息") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "SKU", name = "SKU", paramType = "query", required = true)}) + @HasPermission({"stock:adjust:add", "stock:adjust:modify"}) + @GetMapping("/product/sku") + public InvokeResult searchProductBySku( + @NotBlank(message = "仓库ID不能为空!") String scId, + String sku) { + + if (StringUtil.isBlank(sku)) { + throw new DefaultClientException("请输入商品SKU信息"); + } + + StockAdjustProductDto stockAdjustProductDto = stockAdjustSheetService.queryStockAdjustBySku(scId, sku); + if (stockAdjustProductDto == null) { + throw new DefaultClientException("商品不存在!"); + } + StockAdjustProductBo stockAdjustProductBo = new StockAdjustProductBo(scId, stockAdjustProductDto); + + return InvokeResultBuilder.success(stockAdjustProductBo); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询商品列表") + @HasPermission({"stock:adjust:add", "stock:adjust:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryProductList( + @Valid QueryStockAdjustProductVo vo) { + + PageResult pageResult = stockAdjustSheetService.queryStockAdjustList( + getPageIndex(), + getPageSize(), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new StockAdjustProductBo(vo.getScId(), t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"stock:adjust:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateStockAdjustSheetVo vo) { + + vo.validate(); + + stockAdjustSheetService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:adjust:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateStockAdjustSheetVo vo) { + + vo.validate(); + + stockAdjustSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:adjust:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "id不能为空!") String id) { + + stockAdjustSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"stock:adjust:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的库存调整单!") List ids) { + + stockAdjustSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"stock:adjust:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassStockAdjustSheetVo vo) { + + stockAdjustSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"stock:adjust:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassStockAdjustSheetVo vo) { + + stockAdjustSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"stock:adjust:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateStockAdjustSheetVo vo) { + + stockAdjustSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"stock:adjust:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseStockAdjustSheetVo vo) { + + stockAdjustSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"stock:adjust:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseStockAdjustSheetVo vo) { + + stockAdjustSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + + /** + * 发送审批流程给ydool系统 + */ + @ApiOperation("发送审批流程给ydool系统") + @ApiImplicitParam(value = "ID", name = "id", paramType = "path", required = true) + @HasPermission({"stock:adjust:send:approve"}) + @PutMapping("/send/approve/{id}") + public InvokeResult sendApprove(@PathVariable("id") String id) { + return stockAdjustSheetService.sendApprove(id); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockCostAdjustSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockCostAdjustSheetController.java new file mode 100644 index 0000000..a428991 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/adjust/StockCostAdjustSheetController.java @@ -0,0 +1,314 @@ +package com.lframework.xingyun.sc.controller.stock.adjust; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.adjust.cost.QueryStockCostAdjustSheetBo; +import com.lframework.xingyun.sc.bo.stock.adjust.cost.StockCostAdjustProductBo; +import com.lframework.xingyun.sc.bo.stock.adjust.cost.StockCostAdjustSheetFullBo; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheet; +import com.lframework.xingyun.sc.excel.stock.adjust.StockCostAdjustSheetExportModel; +import com.lframework.xingyun.sc.service.stock.adjust.StockCostAdjustSheetService; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.ApprovePassStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.ApproveRefuseStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.BatchApprovePassStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.BatchApproveRefuseStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.CreateStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.UpdateStockCostAdjustSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 库存成本调整单 Controller + * + * @author zmj + */ +@Api(tags = "库存成本调整单") +@Validated +@RestController +@RequestMapping("/stock/adjust/cost") +public class StockCostAdjustSheetController extends DefaultBaseController { + + @Autowired + private StockCostAdjustSheetService stockCostAdjustSheetService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"stock:adjust:cost:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryStockCostAdjustSheetVo vo) { + + PageResult pageResult = stockCostAdjustSheetService.query( + getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryStockCostAdjustSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:adjust:cost:query"}) + @GetMapping("/detail") + public InvokeResult getDetail( + @NotBlank(message = "id不能为空!") String id) { + + StockCostAdjustSheetFullDto data = stockCostAdjustSheetService.getDetail(id); + if (data == null) { + throw new DefaultClientException("库存成本调整单不存在!"); + } + + StockCostAdjustSheetFullBo result = new StockCostAdjustSheetFullBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"stock:adjust:cost:export"}) + @PostMapping("/export") + public void export(@Valid QueryStockCostAdjustSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("库存成本调整单信息", + StockCostAdjustSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = stockCostAdjustSheetService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(StockCostAdjustSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据关键字查询商品列表 + */ + @ApiOperation("根据关键字查询商品列表") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"stock:adjust:cost:add", "stock:adjust:cost:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchProducts( + @NotBlank(message = "仓库ID不能为空!") String scId, + String condition) { + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + PageResult pageResult = stockCostAdjustSheetService.queryStockCostAdjustByCondition( + getPageIndex(), getPageSize(), scId, condition); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(StockCostAdjustProductBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询商品列表") + @HasPermission({"stock:adjust:cost:add", "stock:adjust:cost:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryProductList( + @Valid QueryStockCostAdjustProductVo vo) { + + PageResult pageResult = stockCostAdjustSheetService.queryStockCostAdjustList( + getPageIndex(), + getPageSize(), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(StockCostAdjustProductBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"stock:adjust:cost:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateStockCostAdjustSheetVo vo) { + + vo.validate(); + + stockCostAdjustSheetService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:adjust:cost:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateStockCostAdjustSheetVo vo) { + + vo.validate(); + + stockCostAdjustSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:adjust:cost:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "id不能为空!") String id) { + + stockCostAdjustSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"stock:adjust:cost:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的库存成本调整单!") List ids) { + + stockCostAdjustSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"stock:adjust:cost:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassStockCostAdjustSheetVo vo) { + + stockCostAdjustSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"stock:adjust:cost:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassStockCostAdjustSheetVo vo) { + + stockCostAdjustSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"stock:adjust:cost:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateStockCostAdjustSheetVo vo) { + + stockCostAdjustSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"stock:adjust:cost:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseStockCostAdjustSheetVo vo) { + + stockCostAdjustSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"stock:adjust:cost:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseStockCostAdjustSheetVo vo) { + + stockCostAdjustSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/PreTakeStockSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/PreTakeStockSheetController.java new file mode 100644 index 0000000..744b7c2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/PreTakeStockSheetController.java @@ -0,0 +1,272 @@ +package com.lframework.xingyun.sc.controller.stock.take; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.take.pre.GetPreTakeStockSheetBo; +import com.lframework.xingyun.sc.bo.stock.take.pre.PreTakeStockProductBo; +import com.lframework.xingyun.sc.bo.stock.take.pre.QueryPreTakeStockSheetBo; +import com.lframework.xingyun.sc.bo.stock.take.pre.QueryPreTakeStockSheetProductBo; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockProductDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.QueryPreTakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import com.lframework.xingyun.sc.excel.stock.take.pre.PreTakeStockSheetExportModel; +import com.lframework.xingyun.sc.service.stock.take.PreTakeStockSheetService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.sc.vo.stock.take.pre.CreatePreTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockProductVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.UpdatePreTakeStockSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 预先盘点单 Controller + * + * @author zmj + */ +@Api(tags = "预先盘点单") +@Validated +@RestController +@RequestMapping("/stock/take/pre") +public class PreTakeStockSheetController extends DefaultBaseController { + + @Autowired + private PreTakeStockSheetService preTakeStockSheetService; + + @Autowired + private TakeStockPlanService takeStockPlanService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"stock:take:pre:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryPreTakeStockSheetVo vo) { + + PageResult pageResult = preTakeStockSheetService.query(getPageIndex(vo), + getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryPreTakeStockSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出列表 + */ + @ApiOperation("导出列表") + @HasPermission({"stock:take:pre:export"}) + @PostMapping("/export") + public void export(@Valid QueryPreTakeStockSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("预先盘点单信息", + PreTakeStockSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = preTakeStockSheetService.query(pageIndex, + getExportSize(), + vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(PreTakeStockSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:pre:query"}) + @GetMapping + public InvokeResult getDetail(@NotBlank(message = "id不能为空!") String id) { + + PreTakeStockSheetFullDto data = preTakeStockSheetService.getDetail(id); + if (data == null) { + throw new DefaultClientException("预先盘点单不存在!"); + } + + GetPreTakeStockSheetBo result = new GetPreTakeStockSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据预先盘点单、盘点任务查询商品信息 + */ + @ApiOperation("根据预先盘点单、盘点任务查询商品信息") + @ApiImplicitParams({ + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true), + @ApiImplicitParam(value = "盘点任务ID", name = "planId", paramType = "query", required = true)}) + @HasPermission({"stock:take:sheet:add", "stock:take:sheet:modify"}) + @GetMapping("/products") + public InvokeResult> getProducts( + @NotBlank(message = "ID不能为空!") String id, + @NotBlank(message = "盘点任务ID不能为空!") String planId) { + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(planId); + if (takeStockPlan.getTakeType() == TakeStockPlanType.SIMPLE) { + planId = null; + } + + List datas = preTakeStockSheetService.getProducts(id, planId); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream() + .map(t -> new QueryPreTakeStockSheetProductBo(t, takeStockPlan.getScId())) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"stock:take:pre:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreatePreTakeStockSheetVo vo) { + + vo.validate(); + + preTakeStockSheetService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:take:pre:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdatePreTakeStockSheetVo vo) { + + vo.validate(); + + preTakeStockSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:pre:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "ID不能为空!") String id) { + + preTakeStockSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @HasPermission({"stock:take:pre:delete"}) + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择要执行操作的预先盘点单!") @RequestBody List ids) { + + preTakeStockSheetService.batchDelete(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 根据关键字查询商品列表 + */ + @ApiOperation("根据关键字查询预先盘点单商品列表") + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true) + @HasPermission({"stock:take:pre:add", "stock:take:pre:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchProducts(String condition) { + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + PageResult pageResult = preTakeStockSheetService.queryPreTakeStockByCondition( + getPageIndex(), getPageSize(), condition); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(PreTakeStockProductBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询预先盘点单商品列表") + @HasPermission({"stock:take:pre:add", "stock:take:pre:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryProductList( + @Valid QueryPreTakeStockProductVo vo) { + + PageResult pageResult = preTakeStockSheetService.queryPreTakeStockList( + getPageIndex(vo), getPageSize(vo), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(PreTakeStockProductBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockConfigController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockConfigController.java new file mode 100644 index 0000000..81ba12b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockConfigController.java @@ -0,0 +1,68 @@ +package com.lframework.xingyun.sc.controller.stock.take; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.bo.stock.take.config.GetTakeStockConfigBo; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import com.lframework.xingyun.sc.vo.stock.take.config.UpdateTakeStockConfigVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 盘点参数 Controller + * + * @author zmj + */ +@Api(tags = "盘点参数") +@Validated +@RestController +@RequestMapping("/stock/take/config") +public class TakeStockConfigController extends DefaultBaseController { + + @Autowired + private TakeStockConfigService takeStockConfigService; + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @HasPermission({"stock:take:config:modify", "stock:take:plan:handle:diff"}) + @GetMapping + public InvokeResult get() { + + TakeStockConfig data = takeStockConfigService.get(); + if (data == null) { + throw new DefaultClientException("盘点参数不存在!"); + } + + GetTakeStockConfigBo result = new GetTakeStockConfigBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:take:config:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateTakeStockConfigVo vo) { + + takeStockConfigService.update(vo); + + takeStockConfigService.cleanCacheByKey(null); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockPlanController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockPlanController.java new file mode 100644 index 0000000..f459b85 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockPlanController.java @@ -0,0 +1,284 @@ +package com.lframework.xingyun.sc.controller.stock.take; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.common.threads.DefaultRunnable; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.CronUtil; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.take.plan.GetTakeStockPlanBo; +import com.lframework.xingyun.sc.bo.stock.take.plan.QueryTakeStockPlanBo; +import com.lframework.xingyun.sc.bo.stock.take.plan.QueryTakeStockPlanProductBo; +import com.lframework.xingyun.sc.bo.stock.take.plan.TakeStockPlanFullBo; +import com.lframework.xingyun.sc.dto.stock.take.plan.QueryTakeStockPlanProductDto; +import com.lframework.xingyun.sc.dto.stock.take.plan.TakeStockPlanFullDto; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.excel.stock.take.plan.TakeStockPlanExportModel; +import com.lframework.xingyun.sc.impl.stock.take.TakeStockPlanServiceImpl; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.sc.vo.stock.take.plan.CancelTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.CreateTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.HandleTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.QueryTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.UpdateTakeStockPlanVo; +import com.lframework.xingyun.template.core.components.qrtz.QrtzHandler; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 盘点任务 Controller + * + * @author zmj + */ +@Api(tags = "盘点任务") +@Validated +@RestController +@RequestMapping("/stock/take/plan") +public class TakeStockPlanController extends DefaultBaseController { + + @Autowired + private TakeStockPlanService takeStockPlanService; + + @Autowired + private TakeStockConfigService takeStockConfigService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"stock:take:plan:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryTakeStockPlanVo vo) { + + PageResult pageResult = takeStockPlanService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryTakeStockPlanBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出列表 + */ + @ApiOperation("导出列表") + @HasPermission({"stock:take:plan:export"}) + @PostMapping("/export") + public void export(@Valid QueryTakeStockPlanVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("盘点任务信息", + TakeStockPlanExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = takeStockPlanService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(TakeStockPlanExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:plan:query", "stock:take:sheet:add", "stock:take:sheet:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + TakeStockPlan data = takeStockPlanService.getById(id); + if (data == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + GetTakeStockPlanBo result = new GetTakeStockPlanBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询详情") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:plan:query", "stock:take:sheet:add", "stock:take:sheet:modify"}) + @GetMapping("/detail") + public InvokeResult getDetail(@NotBlank(message = "id不能为空!") String id) { + + TakeStockPlanFullDto data = takeStockPlanService.getDetail(id); + if (data == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + TakeStockPlanFullBo result = new TakeStockPlanFullBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据盘点任务ID查询商品信息 + */ + @ApiOperation("根据盘点任务ID查询商品信息") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:sheet:add", "stock:take:sheet:modify"}) + @GetMapping("/products") + public InvokeResult> getProducts( + @NotBlank(message = "id不能为空!") String id) { + + TakeStockConfig config = takeStockConfigService.get(); + if (!config.getShowProduct()) { + // 如果不显示商品的话,则显示emptyList + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = takeStockPlanService.getProducts(id); + if (CollectionUtil.isEmpty(datas)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List results = datas.stream().map(QueryTakeStockPlanProductBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"stock:take:plan:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateTakeStockPlanVo vo) { + + vo.validate(); + + String id = takeStockPlanService.create(vo); + + TakeStockConfig config = takeStockConfigService.get(); + + Map params = new HashMap<>(); + params.put("id", id); + params.put(StringPool.TENANT_ID_QRTZ, TenantContextHolder.getTenantId()); + + ThreadUtil.execAsync(new DefaultRunnable(() -> { + // 自动作废 + QrtzHandler.addJob(TakeStockPlanServiceImpl.AutoCancelJob.class, + CronUtil.getDateTimeCron(LocalDateTime.now().plusHours(config.getCancelHours())), params); + })); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:take:plan:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateTakeStockPlanVo vo) { + + takeStockPlanService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 差异生成 + */ + @ApiOperation("差异生成") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:plan:create-diff"}) + @PatchMapping("/diff") + public InvokeResult createDiff(@NotBlank(message = "ID不能为空!") String id) { + + takeStockPlanService.createDiff(id); + + return InvokeResultBuilder.success(); + } + + /** + * 差异处理 + */ + @ApiOperation("差异处理") + @HasPermission({"stock:take:plan:handle-diff"}) + @PatchMapping("/handle") + public InvokeResult handleDiff(@Valid @RequestBody HandleTakeStockPlanVo vo) { + + takeStockPlanService.handleDiff(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 作废 + */ + @ApiOperation("作废") + @HasPermission({"stock:take:plan:cancel"}) + @PatchMapping("/cancel") + public InvokeResult cancel(@Valid CancelTakeStockPlanVo vo) { + + takeStockPlanService.cancel(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:plan:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "ID不能为空!") String id) { + + takeStockPlanService.deleteById(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockSheetController.java new file mode 100644 index 0000000..83d6005 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/take/TakeStockSheetController.java @@ -0,0 +1,342 @@ +package com.lframework.xingyun.sc.controller.stock.take; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.take.sheet.QueryTakeStockSheetBo; +import com.lframework.xingyun.sc.bo.stock.take.sheet.TakeStockSheetFullBo; +import com.lframework.xingyun.sc.bo.stock.take.sheet.TakeStockSheetProductBo; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.entity.TakeStockSheet; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import com.lframework.xingyun.sc.excel.stock.take.sheet.TakeStockSheetExportModel; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockSheetService; +import com.lframework.xingyun.sc.vo.stock.take.sheet.ApprovePassTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.ApproveRefuseTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.BatchApprovePassTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.BatchApproveRefuseTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.CreateTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetProductVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.UpdateTakeStockSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 盘点单 Controller + * + * @author zmj + */ +@Api(tags = "盘点单") +@Validated +@RestController +@RequestMapping("/stock/take/sheet") +public class TakeStockSheetController extends DefaultBaseController { + + @Autowired + private TakeStockSheetService takeStockSheetService; + + @Autowired + private TakeStockPlanService takeStockPlanService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"stock:take:sheet:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryTakeStockSheetVo vo) { + + PageResult pageResult = takeStockSheetService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryTakeStockSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出列表 + */ + @ApiOperation("导出列表") + @HasPermission({"stock:take:sheet:export"}) + @PostMapping("/export") + public void export(@Valid QueryTakeStockSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("库存盘点单信息", + TakeStockSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = takeStockSheetService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(TakeStockSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:sheet:query"}) + @GetMapping("/detail") + public InvokeResult getDetail(@NotBlank(message = "id不能为空!") String id) { + + TakeStockSheetFullDto data = takeStockSheetService.getDetail(id); + if (data == null) { + throw new DefaultClientException("盘点单不存在!"); + } + + TakeStockSheetFullBo result = new TakeStockSheetFullBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据关键字查询商品列表 + */ + @ApiOperation("根据关键字查询商品列表") + @ApiImplicitParams({ + @ApiImplicitParam(value = "盘点任务ID", name = "planId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"stock:take:sheet:add", "stock:take:sheet:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchProducts( + @NotBlank(message = "盘点任务ID不能为空!") String planId, + String condition) { + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(planId); + if (takeStockPlan.getTakeType() == TakeStockPlanType.SIMPLE) { + planId = null; + } + PageResult pageResult = takeStockSheetService.queryTakeStockByCondition( + getPageIndex(), + getPageSize(), planId, condition); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + String finalPlanId = planId; + results = datas.stream() + .map(t -> new TakeStockSheetProductBo(t, finalPlanId, takeStockPlan.getScId())) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询商品列表") + @HasPermission({"stock:take:sheet:add", "stock:take:sheet:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryProductList( + @Valid QueryTakeStockSheetProductVo vo) { + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(vo.getPlanId()); + if (takeStockPlan.getTakeType() == TakeStockPlanType.SIMPLE) { + vo.setPlanId(null); + } + + PageResult pageResult = takeStockSheetService.queryTakeStockList( + getPageIndex(), + getPageSize(), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream() + .map(t -> new TakeStockSheetProductBo(t, vo.getPlanId(), takeStockPlan.getScId())) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"stock:take:sheet:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateTakeStockSheetVo vo) { + + takeStockSheetService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:take:sheet:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateTakeStockSheetVo vo) { + + takeStockSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"stock:take:sheet:approve"}) + @PostMapping("/approve/direct") + public InvokeResult directApprovePass(@Valid @RequestBody CreateTakeStockSheetVo vo) { + + takeStockSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"stock:take:sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@Valid ApprovePassTakeStockSheetVo vo) { + + takeStockSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"stock:take:sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @Valid @RequestBody BatchApprovePassTakeStockSheetVo vo) { + + takeStockSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"stock:take:sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@Valid ApproveRefuseTakeStockSheetVo vo) { + + takeStockSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"stock:take:sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @Valid @RequestBody BatchApproveRefuseTakeStockSheetVo vo) { + + takeStockSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 取消审核 + */ + @ApiOperation("取消审核") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:sheet:cancel-approve"}) + @PatchMapping("/approve/cancel") + public InvokeResult cancelApprovePass(@NotBlank(message = "ID不能为空!") String id) { + + takeStockSheetService.cancelApprovePass(id); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + */ + @ApiOperation("删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:take:sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "ID不能为空!") String id) { + + takeStockSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"stock:take:sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择要执行操作的库存盘点单!") @RequestBody List ids) { + + takeStockSheetService.batchDelete(ids); + + return InvokeResultBuilder.success(); + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/transfer/ScTransferOrderController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/transfer/ScTransferOrderController.java new file mode 100644 index 0000000..9f9c1d5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/stock/transfer/ScTransferOrderController.java @@ -0,0 +1,367 @@ +package com.lframework.xingyun.sc.controller.stock.transfer; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.bo.stock.transfer.QueryScTransferOrderBo; +import com.lframework.xingyun.sc.bo.stock.transfer.QueryScTransferOrderDetailReceiveBo; +import com.lframework.xingyun.sc.bo.stock.transfer.ScTransferOrderFullBo; +import com.lframework.xingyun.sc.bo.stock.transfer.ScTransferProductBo; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferOrderFullDto; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferProductDto; +import com.lframework.xingyun.sc.entity.ScTransferOrder; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetailReceive; +import com.lframework.xingyun.sc.excel.stock.transfer.ScTransferOrderExportModel; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderDetailReceiveService; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderService; +import com.lframework.xingyun.sc.vo.stock.transfer.ApprovePassScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ApproveRefuseScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.BatchApprovePassScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.BatchApproveRefuseScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.CreateScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferOrderDetailReceiveVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferProductVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ReceiveScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.UpdateScTransferOrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 仓库调拨单 Controller + * + * @author zmj + */ +@Api(tags = "仓库调拨单") +@Validated +@RestController +@RequestMapping("/stock/transfer/sc") +public class ScTransferOrderController extends DefaultBaseController { + + @Autowired + private ScTransferOrderService scTransferOrderService; + + @Autowired + private ScTransferOrderDetailReceiveService scTransferOrderDetailReceiveService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"stock:sc-transfer:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryScTransferOrderVo vo) { + + PageResult pageResult = scTransferOrderService.query( + getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryScTransferOrderBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:sc-transfer:query"}) + @GetMapping("/detail") + public InvokeResult getDetail( + @NotBlank(message = "id不能为空!") String id) { + + ScTransferOrderFullDto data = scTransferOrderService.getDetail(id); + if (data == null) { + throw new DefaultClientException("仓库调拨单不存在!"); + } + + ScTransferOrderFullBo result = new ScTransferOrderFullBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"stock:sc-transfer:export"}) + @PostMapping("/export") + public void export(@Valid QueryScTransferOrderVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("仓库调拨单信息", + ScTransferOrderExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = scTransferOrderService.query(pageIndex, + getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(ScTransferOrderExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据关键字查询商品列表 + */ + @ApiOperation("根据关键字查询商品列表") + @ApiImplicitParams({ + @ApiImplicitParam(value = "仓库ID", name = "scId", paramType = "query", required = true), + @ApiImplicitParam(value = "关键字", name = "condition", paramType = "query", required = true)}) + @HasPermission({"stock:sc-transfer:add", "stock:sc-transfer:modify"}) + @GetMapping("/product/search") + public InvokeResult> searchProducts( + @NotBlank(message = "仓库ID不能为空!") String scId, + String condition) { + + if (StringUtil.isBlank(condition)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + PageResult pageResult = scTransferOrderService.queryScTransferByCondition( + getPageIndex(), getPageSize(), scId, condition); + List results = CollectionUtil.emptyList(); + List datas = pageResult.getDatas(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new ScTransferProductBo(scId, t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 查询商品列表 + */ + @ApiOperation("查询商品列表") + @HasPermission({"stock:sc-transfer:add", "stock:sc-transfer:modify"}) + @GetMapping("/product/list") + public InvokeResult> queryProductList( + @Valid QueryScTransferProductVo vo) { + + PageResult pageResult = scTransferOrderService.queryScTransferList( + getPageIndex(), + getPageSize(), vo); + List results = null; + List datas = pageResult.getDatas(); + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(t -> new ScTransferProductBo(vo.getScId(), t)) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"stock:sc-transfer:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateScTransferOrderVo vo) { + + vo.validate(); + + scTransferOrderService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"stock:sc-transfer:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateScTransferOrderVo vo) { + + vo.validate(); + + scTransferOrderService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"stock:sc-transfer:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "id不能为空!") String id) { + + scTransferOrderService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除 + */ + @ApiOperation("批量删除") + @HasPermission({"stock:sc-transfer:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的仓库调拨单!") List ids) { + + scTransferOrderService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过 + */ + @ApiOperation("审核通过") + @HasPermission({"stock:sc-transfer:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassScTransferOrderVo vo) { + + scTransferOrderService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过 + */ + @ApiOperation("批量审核通过") + @HasPermission({"stock:sc-transfer:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassScTransferOrderVo vo) { + + scTransferOrderService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过 + */ + @ApiOperation("直接审核通过") + @HasPermission({"stock:sc-transfer:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateScTransferOrderVo vo) { + + scTransferOrderService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝 + */ + @ApiOperation("审核拒绝") + @HasPermission({"stock:sc-transfer:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseScTransferOrderVo vo) { + + scTransferOrderService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝 + */ + @ApiOperation("批量审核拒绝") + @HasPermission({"stock:sc-transfer:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseScTransferOrderVo vo) { + + scTransferOrderService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 收货 + */ + @ApiOperation("收货") + @HasPermission({"stock:sc-transfer:receive"}) + @PatchMapping("/receive") + public InvokeResult receive(@RequestBody @Valid ReceiveScTransferOrderVo vo) { + + scTransferOrderService.receive(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 收货记录 + */ + @ApiOperation("收货记录") + @HasPermission({"stock:sc-transfer:query"}) + @GetMapping("/receive/detail") + public InvokeResult> receiveDetail( + @Valid QueryScTransferOrderDetailReceiveVo vo) { + + Wrapper queryWrapper = Wrappers.lambdaQuery( + ScTransferOrderDetailReceive.class) + .eq(ScTransferOrderDetailReceive::getOrderId, vo.getOrderId()) + .eq(ScTransferOrderDetailReceive::getDetailId, vo.getDetailId()) + .orderByAsc(ScTransferOrderDetailReceive::getCreateTime); + + Page page = new Page<>(getPageIndex(vo), getPageSize(vo)); + Page pageInfo = scTransferOrderDetailReceiveService.page(page, + queryWrapper); + PageResult pageResult = PageResultUtil.convert(pageInfo); + List datas = pageResult.getDatas(); + List results = datas.stream() + .map(QueryScTransferOrderDetailReceiveBo::new).collect( + Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolPurchaseOrderController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolPurchaseOrderController.java new file mode 100644 index 0000000..39ad38e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolPurchaseOrderController.java @@ -0,0 +1,46 @@ +package com.lframework.xingyun.sc.controller.ydool; + +import com.lframework.starter.web.annotations.OpenApi; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + * 云朵里采购订单管理 + * + * @author zmj + */ +@Api(tags = "云朵里采购订单管理") +@Validated +@RestController +@RequestMapping("/ydool/purchase/order") +public class YdoolPurchaseOrderController extends DefaultBaseController { + + @Autowired + private PurchaseOrderService purchaseOrderService; + + @Autowired + private ProductService productService; + + /** + * ydool将审批结果推送过来 + */ + @ApiOperation("ydool将审批结果推送过来") + @OpenApi + @PostMapping("/approve") + public InvokeResult approve(@RequestBody @Valid YdoolApproveOrderVo vo) { + purchaseOrderService.approve(vo); + return InvokeResultBuilder.success(); + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolRetailOutSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolRetailOutSheetController.java new file mode 100644 index 0000000..392fc9a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolRetailOutSheetController.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.sc.controller.ydool; + +import com.lframework.starter.web.annotations.OpenApi; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * 云朵里零售出库单管理 + * + * @author zmj + */ +@Api(tags = "云朵里零售出库单管理") +@Validated +@RestController +@RequestMapping("/ydool/retail/out/sheet") +public class YdoolRetailOutSheetController extends DefaultBaseController { + + @Autowired + private RetailOutSheetService retailOutSheetService; + + /** + * ydool将审批结果推送过来 + */ + @ApiOperation("ydool将审批结果推送过来") + @OpenApi + @PostMapping("/approve") + public InvokeResult approve(@RequestBody @Valid YdoolApproveOrderVo vo) { + retailOutSheetService.approve(vo); + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolSaleOrderController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolSaleOrderController.java new file mode 100644 index 0000000..52d0e84 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolSaleOrderController.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.controller.ydool; + +import com.lframework.starter.web.annotations.OpenApi; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * 云朵里销售订单管理 + * + * @author zmj + */ +@Api(tags = "云朵里销售订单管理") +@Validated +@RestController +@RequestMapping("/ydool/sale/order") +public class YdoolSaleOrderController extends DefaultBaseController { + @Autowired + private SaleOrderService saleOrderService; + + /** + * ydool将审批结果推送过来 + */ + @ApiOperation("ydool将审批结果推送过来") + @OpenApi + @PostMapping("/approve") + public InvokeResult approve(@RequestBody @Valid YdoolApproveOrderVo vo) { + saleOrderService.approve(vo); + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolStockAdjustSheetController.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolStockAdjustSheetController.java new file mode 100644 index 0000000..e317aea --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/ydool/YdoolStockAdjustSheetController.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.sc.controller.ydool; + +import com.lframework.starter.web.annotations.OpenApi; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustSheetService; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * 云朵里库存调整单 Controller + * + * @author zmj + */ +@Api(tags = "云朵里库存调整单") +@Validated +@RestController +@RequestMapping("/ydool/stock/adjust") +public class YdoolStockAdjustSheetController extends DefaultBaseController { + + @Autowired + private StockAdjustSheetService stockAdjustSheetService; + + /** + * ydool将审批结果推送过来 + */ + @ApiOperation("ydool将审批结果推送过来") + @OpenApi + @PostMapping("/approve") + public InvokeResult approve(@RequestBody @Valid YdoolApproveOrderVo vo) { + stockAdjustSheetService.approve(vo); + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetBizOrderDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetBizOrderDto.java new file mode 100644 index 0000000..db750fc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetBizOrderDto.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.dto.logistics; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class LogisticsSheetBizOrderDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据ID + */ + private String bizId; + + /** + * 业务单据号 + */ + private String bizCode; + + /** + * 仓库ID + */ + private String scId; + + /** + * 收货人ID + */ + private String receiverId; + + /** + * 业务类型 + */ + private LogisticsSheetDetailBizType bizType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetFullDto.java new file mode 100644 index 0000000..44cc19e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/logistics/LogisticsSheetFullDto.java @@ -0,0 +1,182 @@ +package com.lframework.xingyun.sc.dto.logistics; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.enums.LogisticsSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class LogisticsSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 物流单号 + */ + private String logisticsNo; + + /** + * 物流公司ID + */ + private String logisticsCompanyId; + + /** + * 寄件人姓名 + */ + private String senderName; + + /** + * 寄件人联系电话 + */ + private String senderTelephone; + + /** + * 寄件人省 + */ + private String senderProvinceId; + + /** + * 寄件人市 + */ + private String senderCityId; + + /** + * 寄件人区 + */ + private String senderDistrictId; + + /** + * 寄件人地址 + */ + private String senderAddress; + + /** + * 收件人姓名 + */ + private String receiverName; + + /** + * 收件人联系电话 + */ + private String receiverTelephone; + + /** + * 收件人省 + */ + private String receiverProvinceId; + + /** + * 收件人市 + */ + private String receiverCityId; + + /** + * 收件人区 + */ + private String receiverDistrictId; + + /** + * 收件人地址 + */ + private String receiverAddress; + + /** + * 状态 + */ + private LogisticsSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 总重量 + */ + private BigDecimal totalWeight; + + /** + * 总体积 + */ + private BigDecimal totalVolume; + + /** + * 物流费 + */ + private BigDecimal totalAmount; + + /** + * 发货人 + */ + private String deliveryBy; + + /** + * 发货时间 + */ + private LocalDateTime deliveryTime; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 物流单ID + */ + private String sheetId; + + /** + * 业务单据ID + */ + private String bizId; + + /** + * 业务类型 + */ + private LogisticsSheetDetailBizType bizType; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderFullDto.java new file mode 100644 index 0000000..27a1d61 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderFullDto.java @@ -0,0 +1,164 @@ +package com.lframework.xingyun.sc.dto.purchase; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class PurchaseOrderFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 预计到货日期 + */ + private LocalDate expectArriveDate; + + /** + * 采购数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 采购金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建人ID + */ + private String createById; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private PurchaseOrderStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + + /** + * 订单明细 + */ + private List details; + + + @Data + public static class OrderDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 采购数量 + */ + private Integer orderNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率 + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderWithReceiveDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderWithReceiveDto.java new file mode 100644 index 0000000..a041cff --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseOrderWithReceiveDto.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.sc.dto.purchase; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +/** + * 采购订单在收货业务的Dto + */ +@Data +public class PurchaseOrderWithReceiveDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 采购数量 + */ + private Integer orderNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已收货数量 + */ + private Integer receiveNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseProductDto.java new file mode 100644 index 0000000..3fe2776 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/PurchaseProductDto.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.dto.purchase; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class PurchaseProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 采购价 + */ + private BigDecimal purchasePrice; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 状态 + */ + private Boolean available; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/GetPaymentDateDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/GetPaymentDateDto.java new file mode 100644 index 0000000..4cb36f6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/GetPaymentDateDto.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.sc.dto.purchase.receive; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.time.LocalDate; +import lombok.Data; + +@Data +public class GetPaymentDateDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 是否允许修改付款日期 + */ + private Boolean allowModify; + + /** + * 默认付款日期 + */ + private LocalDate paymentDate; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetFullDto.java new file mode 100644 index 0000000..702a781 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetFullDto.java @@ -0,0 +1,178 @@ +package com.lframework.xingyun.sc.dto.purchase.receive; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class ReceiveSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 采购订单ID + */ + private String purchaseOrderId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 到货日期 + */ + private LocalDate receiveDate; + + /** + * 采购数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 采购金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private ReceiveSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class OrderDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 收货数量 + */ + private Integer orderNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率 + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 采购订单明细ID + */ + private String purchaseOrderDetailId; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetWithReturnDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetWithReturnDto.java new file mode 100644 index 0000000..a73d1ef --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/receive/ReceiveSheetWithReturnDto.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.sc.dto.purchase.receive; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +/** + * 采购收货单在采购退货业务的Dto + */ +@Data +public class ReceiveSheetWithReturnDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 收货数量 + */ + private Integer orderNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已退货数量 + */ + private Integer returnNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/returned/PurchaseReturnFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/returned/PurchaseReturnFullDto.java new file mode 100644 index 0000000..fe1d0dc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/purchase/returned/PurchaseReturnFullDto.java @@ -0,0 +1,173 @@ +package com.lframework.xingyun.sc.dto.purchase.returned; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.PurchaseReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class PurchaseReturnFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 收货单ID + */ + private String receiveSheetId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 退货金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private PurchaseReturnStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 退单明细 + */ + private List details; + + @Data + public static class ReturnDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 退货数量 + */ + private Integer returnNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率 + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 收货单明细ID + */ + private String receiveSheetDetailId; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/RetailProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/RetailProductDto.java new file mode 100644 index 0000000..f46b615 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/RetailProductDto.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.dto.retail; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class RetailProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 零售价 + */ + private BigDecimal retailPrice; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 状态 + */ + private Boolean available; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetDetailLotDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetDetailLotDto.java new file mode 100644 index 0000000..aac3927 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetDetailLotDto.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.dto.retail.out; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class RetailOutSheetDetailLotDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 明细ID + */ + private String detailId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 已退货数量 + */ + private Integer returnNum; + + /** + * 含税成本金额 + */ + private BigDecimal costTaxAmount; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetFullDto.java new file mode 100644 index 0000000..b1962f4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetFullDto.java @@ -0,0 +1,193 @@ +package com.lframework.xingyun.sc.dto.retail.out; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.RetailOutSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class RetailOutSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 会员ID + */ + private String memberId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 出库总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建人ID + */ + private String createById; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private RetailOutSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 商品ID + */ + private String productId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 销售订单明细ID + */ + private String saleOrderDetailId; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetWithReturnDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetWithReturnDto.java new file mode 100644 index 0000000..cf96f1b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/out/RetailOutSheetWithReturnDto.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.sc.dto.retail.out; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +@Data +public class RetailOutSheetWithReturnDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 会员ID + */ + private String memberId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已退货数量 + */ + private Integer returnNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/returned/RetailReturnFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/returned/RetailReturnFullDto.java new file mode 100644 index 0000000..c37de0d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/retail/returned/RetailReturnFullDto.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.sc.dto.retail.returned; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.RetailReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class RetailReturnFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 会员ID + */ + private String memberId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 退货总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private RetailReturnStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 零售出库单ID + */ + private String outSheetId; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class ReturnDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 退货数量 + */ + private Integer returnNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 零售出库单明细ID + */ + private String outSheetDetailId; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderFullDto.java new file mode 100644 index 0000000..3c1f32d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderFullDto.java @@ -0,0 +1,171 @@ +package com.lframework.xingyun.sc.dto.sale; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SaleOrderStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SaleOrderFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 销售总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建人ID + */ + private String createById; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SaleOrderStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class OrderDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 商品ID + */ + private String productId; + + /** + * 采购数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderWithOutDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderWithOutDto.java new file mode 100644 index 0000000..71fc2b9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleOrderWithOutDto.java @@ -0,0 +1,107 @@ +package com.lframework.xingyun.sc.dto.sale; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +/** + * 销售订单在出库业务的Dto + */ +@Data +public class SaleOrderWithOutDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 商品ID + */ + private String productId; + + /** + * 销售数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已出库数量 + */ + private Integer outNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleProductDto.java new file mode 100644 index 0000000..a1b27b6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/SaleProductDto.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.dto.sale; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SaleProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 销售价 + */ + private BigDecimal salePrice; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 状态 + */ + private Boolean available; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetDetailLotDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetDetailLotDto.java new file mode 100644 index 0000000..95b411d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetDetailLotDto.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.dto.sale.out; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SaleOutSheetDetailLotDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 明细ID + */ + private String detailId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 已退货数量 + */ + private Integer returnNum; + + /** + * 含税成本金额 + */ + private BigDecimal costTaxAmount; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetFullDto.java new file mode 100644 index 0000000..5580f24 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetFullDto.java @@ -0,0 +1,193 @@ +package com.lframework.xingyun.sc.dto.sale.out; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SaleOutSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SaleOutSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 出库总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SaleOutSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 销售订单ID + */ + private String saleOrderId; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 商品ID + */ + private String productId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 销售订单明细ID + */ + private String saleOrderDetailId; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetWithReturnDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetWithReturnDto.java new file mode 100644 index 0000000..3df6549 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/out/SaleOutSheetWithReturnDto.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.sc.dto.sale.out; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +@Data +public class SaleOutSheetWithReturnDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已退货数量 + */ + private Integer returnNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/returned/SaleReturnFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/returned/SaleReturnFullDto.java new file mode 100644 index 0000000..fef7952 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/sale/returned/SaleReturnFullDto.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.sc.dto.sale.returned; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SaleReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SaleReturnFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 退货总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SaleReturnStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 销售出库单ID + */ + private String outSheetId; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 订单明细 + */ + private List details; + + @Data + public static class ReturnDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 退货数量 + */ + private Integer returnNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 销售出库单明细ID + */ + private String outSheetDetailId; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustDiffDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustDiffDto.java new file mode 100644 index 0000000..4f92c49 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustDiffDto.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.dto.stock.adjust.cost; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class StockCostAdjustDiffDto implements Serializable, BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * 库存数量 + */ + private Integer stockNum = 0; + + /** + * 原价 + */ + private BigDecimal oriPrice = BigDecimal.ZERO; + + /** + * 调整金额 + */ + private BigDecimal diffAmount = BigDecimal.ZERO; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustProductDto.java new file mode 100644 index 0000000..c39774e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustProductDto.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.dto.stock.adjust.cost; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class StockCostAdjustProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 档案采购价 + */ + private BigDecimal purchasePrice; + + /** + * 库存数量 + */ + private Integer stockNum; + + /** + * 调价前成本价 + */ + private BigDecimal oriPrice; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustSheetFullDto.java new file mode 100644 index 0000000..d905966 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/cost/StockCostAdjustSheetFullDto.java @@ -0,0 +1,134 @@ +package com.lframework.xingyun.sc.dto.stock.adjust.cost; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.StockCostAdjustSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +/** + *

+ * 库存成本调整单详情 Dto + *

+ * + * @author zmj + */ +@Data +public class StockCostAdjustSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 调价品种数 + */ + private Integer productNum; + + /** + * 库存调价差额 + */ + private BigDecimal diffAmount; + + /** + * 状态 + */ + private StockCostAdjustSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 档案采购价 + */ + private BigDecimal purchasePrice; + + /** + * 库存数量 + */ + private Integer stockNum; + + /** + * 调整前成本价 + */ + private BigDecimal oriPrice; + + /** + * 调整后成本价 + */ + private BigDecimal price; + + /** + * 库存调价差额 + */ + private BigDecimal diffAmount; + + /** + * 备注 + */ + private String description; + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustProductDto.java new file mode 100644 index 0000000..b3efb21 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustProductDto.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.sc.dto.stock.adjust.stock; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class StockAdjustProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 当前库存数量 + */ + private Integer curStockNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustSheetFullDto.java new file mode 100644 index 0000000..b16dd38 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/adjust/stock/StockAdjustSheetFullDto.java @@ -0,0 +1,119 @@ +package com.lframework.xingyun.sc.dto.stock.adjust.stock; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.StockAdjustSheetBizType; +import com.lframework.xingyun.sc.enums.StockAdjustSheetStatus; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +/** + *

+ * 库存成本调整单详情 Dto + *

+ * + * @author zmj + */ +@Data +public class StockAdjustSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 业务类型 + */ + private StockAdjustSheetBizType bizType; + + /** + * 调整原因ID + */ + private String reasonId; + + /** + * 状态 + */ + private StockAdjustSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 创建人ID + */ + private String createById; + + /** + * 明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 调整库存数量 + */ + private Integer stockNum; + + /** + * 备注 + */ + private String description; + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/GetTakeStockPlanDetailProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/GetTakeStockPlanDetailProductDto.java new file mode 100644 index 0000000..5ca2ac2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/GetTakeStockPlanDetailProductDto.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.dto.stock.take.plan; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +/** + * 查询盘点任务详情中的商品信息 Dto + */ +@Data +public class GetTakeStockPlanDetailProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 详情ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 库存数量 + */ + private Integer stockNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/QueryTakeStockPlanProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/QueryTakeStockPlanProductDto.java new file mode 100644 index 0000000..07836bd --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/QueryTakeStockPlanProductDto.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.dto.stock.take.plan; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryTakeStockPlanProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + private String productId; + + /** + * 初始库存 + */ + private Integer stockNum; + + /** + * 出项数量 + */ + private Integer totalOutNum; + + /** + * 入项数量 + */ + private Integer totalInNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/TakeStockPlanFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/TakeStockPlanFullDto.java new file mode 100644 index 0000000..89d1a50 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/plan/TakeStockPlanFullDto.java @@ -0,0 +1,123 @@ +package com.lframework.xingyun.sc.dto.stock.take.plan; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class TakeStockPlanFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 盘点类别 + */ + private TakeStockPlanType takeType; + + /** + * 备注 + */ + private String description; + + /** + * 盘点状态 + */ + private TakeStockPlanStatus takeStatus; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 库存数量 + */ + private Integer stockNum; + + /** + * 盘点数量 + */ + private Integer oriTakeNum; + + /** + * 修改后的盘点数量 + */ + private Integer takeNum; + + /** + * 出项数量 + */ + private Integer totalOutNum; + + /** + * 进项数量 + */ + private Integer totalInNum; + + /** + * 成本价 + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String description; + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockProductDto.java new file mode 100644 index 0000000..577264a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockProductDto.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.sc.dto.stock.take.pre; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class PreTakeStockProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockSheetFullDto.java new file mode 100644 index 0000000..70ce79c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/PreTakeStockSheetFullDto.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.sc.dto.stock.take.pre; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +/** + *

+ * 预先盘点单 Dto + *

+ * + * @author zmj + */ +@Data +public class PreTakeStockSheetFullDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "PreTakeStockSheetFullDto"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 盘点状态 + */ + private PreTakeStockSheetStatus takeStatus; + + /** + * 备注 + */ + private String description; + + /** + * 操作人ID + */ + private String updateBy; + + /** + * 操作时间 + */ + private LocalDateTime updateTime; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 初盘数量 + */ + private Integer firstNum; + + /** + * 复盘数量 + */ + private Integer secondNum; + + /** + * 抽盘数量 + */ + private Integer randNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/QueryPreTakeStockSheetProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/QueryPreTakeStockSheetProductDto.java new file mode 100644 index 0000000..84e82ef --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/pre/QueryPreTakeStockSheetProductDto.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.dto.stock.take.pre; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryPreTakeStockSheetProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + private String productId; + + /** + * 初盘数量 + */ + private Integer firstNum; + + /** + * 复盘数量 + */ + private Integer secondNum; + + /** + * 抽盘数量 + */ + private Integer randNum; + + /** + * 预先盘点单状态 + */ + private PreTakeStockSheetStatus takeStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetFullDto.java new file mode 100644 index 0000000..b13f197 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetFullDto.java @@ -0,0 +1,123 @@ +package com.lframework.xingyun.sc.dto.stock.take.sheet; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.TakeStockSheetStatus; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +/** + *

+ * 盘点单详情 Dto + *

+ * + * @author zmj + */ +@Data +public class TakeStockSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 盘点任务ID + */ + private String planId; + + /** + * 预先盘点单ID + */ + private String preSheetId; + + /** + * 仓库ID + */ + private String scId; + + /** + * 状态 + */ + private TakeStockSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 拒绝理由 + */ + private String refuseReason; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 明细 + */ + private List details; + + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 盘点数量 + */ + private Integer takeNum; + + /** + * 备注 + */ + private String description; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetProductDto.java new file mode 100644 index 0000000..b154ad6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/take/sheet/TakeStockSheetProductDto.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.sc.dto.stock.take.sheet; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class TakeStockSheetProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferOrderFullDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferOrderFullDto.java new file mode 100644 index 0000000..877783b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferOrderFullDto.java @@ -0,0 +1,124 @@ +package com.lframework.xingyun.sc.dto.stock.transfer; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.ScTransferOrderStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +/** + *

+ * 仓库调拨单详情 Dto + *

+ * + * @author zmj + */ +@Data +public class ScTransferOrderFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 转出仓库ID + */ + private String sourceScId; + + /** + * 转入仓库ID + */ + private String targetScId; + + /** + * 调拨数量 + */ + private Integer totalNum; + + /** + * 调拨成本金额 + */ + private BigDecimal totalAmount; + + /** + * 状态 + */ + private ScTransferOrderStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 明细 + */ + private List details; + + @Data + public static class DetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 商品ID + */ + private String productId; + + /** + * 调拨数量 + */ + private Integer transferNum; + + /** + * 已收货数量 + */ + private Integer receiveNum; + + /** + * 备注 + */ + private String description; + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferProductDto.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferProductDto.java new file mode 100644 index 0000000..f9d36ec --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/dto/stock/transfer/ScTransferProductDto.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.sc.dto.stock.transfer; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class ScTransferProductDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 类目ID + */ + private String categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 品牌ID + */ + private String brandId; + + /** + * 品牌名称 + */ + private String brandName; + + /** + * SKU + */ + private String skuCode; + + /** + * 外部编号 + */ + private String externalCode; + + /** + * 规格 + */ + private String spec; + + /** + * 单位 + */ + private String unit; + + /** + * 当前库存数量 + */ + private Integer curStockNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheet.java new file mode 100644 index 0000000..8749af1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheet.java @@ -0,0 +1,178 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.LogisticsSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 物流单 + *

+ * + * @author zmj + * @since 2023-06-13 + */ +@Data +@TableName("tbl_logistics_sheet") +public class LogisticsSheet extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "LogisticsSheet"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 物流单号 + */ + private String logisticsNo; + + /** + * 物流公司ID + */ + private String logisticsCompanyId; + + /** + * 寄件人姓名 + */ + private String senderName; + + /** + * 寄件人联系电话 + */ + private String senderTelephone; + + /** + * 寄件人省 + */ + private String senderProvinceId; + + /** + * 寄件人市 + */ + private String senderCityId; + + /** + * 寄件人区 + */ + private String senderDistrictId; + + /** + * 寄件人地址 + */ + private String senderAddress; + + /** + * 收件人姓名 + */ + private String receiverName; + + /** + * 收件人联系电话 + */ + private String receiverTelephone; + + /** + * 收件人省 + */ + private String receiverProvinceId; + + /** + * 收件人市 + */ + private String receiverCityId; + + /** + * 收件人区 + */ + private String receiverDistrictId; + + /** + * 收件人地址 + */ + private String receiverAddress; + + /** + * 总重量 + */ + private BigDecimal totalWeight; + + /** + * 总体积 + */ + private BigDecimal totalVolume; + + /** + * 物流费 + */ + private BigDecimal totalAmount; + + /** + * 状态 + */ + private LogisticsSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 发货人 + */ + private String deliveryBy; + + /** + * 发货时间 + */ + private LocalDateTime deliveryTime; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheetDetail.java new file mode 100644 index 0000000..7071ac3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/LogisticsSheetDetail.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import lombok.Data; + +/** + *

+ * 物流单 + *

+ * + * @author zmj + * @since 2023-06-13 + */ +@Data +@TableName("tbl_logistics_sheet_detail") +public class LogisticsSheetDetail extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "LogisticsSheetDetail"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 物流单ID + */ + private String sheetId; + + /** + * 业务单据ID + */ + private String bizId; + + /** + * 业务类型 + */ + private LogisticsSheetDetailBizType bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/OrderPayType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/OrderPayType.java new file mode 100644 index 0000000..f87626f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/OrderPayType.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2023-03-28 + */ +@Data +@TableName("tbl_order_pay_type") +public class OrderPayType extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "OrderPayType"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 订单ID + */ + private String orderId; + + /** + * 支付方式ID + */ + private String payTypeId; + + /** + * 支付金额 + */ + private BigDecimal payAmount; + + /** + * 支付内容 + */ + private String text; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheet.java new file mode 100644 index 0000000..c4c506c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheet.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 预先盘点单 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_pre_take_stock_sheet") +public class PreTakeStockSheet extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "PreTakeStockSheet"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 盘点状态 + */ + private PreTakeStockSheetStatus takeStatus; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheetDetail.java new file mode 100644 index 0000000..687d84f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PreTakeStockSheetDetail.java @@ -0,0 +1,56 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 预先盘点单详情 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_pre_take_stock_sheet_detail") +public class PreTakeStockSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 预先盘点单ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 初盘数量 + */ + private Integer firstNum; + + /** + * 复盘数量 + */ + private Integer secondNum; + + /** + * 抽盘数量 + */ + private Integer randNum; + + /** + * 排序 + */ + private Integer orderNo; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStock.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStock.java new file mode 100644 index 0000000..f9090fe --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStock.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-09-12 + */ +@Data +@TableName("tbl_product_stock") +public class ProductStock extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 商品ID + */ + private String productId; + + /** + * 库存数量 + */ + private Integer stockNum; + + /** + * 含税价格 + */ + private BigDecimal taxPrice; + + /** + * 含税金额 + */ + private BigDecimal taxAmount; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStockLog.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStockLog.java new file mode 100644 index 0000000..a85f046 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ProductStockLog.java @@ -0,0 +1,111 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-14 + */ +@Data +@TableName("tbl_product_stock_log") +public class ProductStockLog extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 仓库ID + */ + private String scId; + + /** + * 商品ID + */ + private String productId; + + /** + * 原库存数量 + */ + private Integer oriStockNum; + + /** + * 现库存数量 + */ + private Integer curStockNum; + + /** + * 原含税成本价 + */ + private BigDecimal oriTaxPrice; + + /** + * 现含税成本价 + */ + private BigDecimal curTaxPrice; + + /** + * 变动库存数量 + */ + private Integer stockNum; + + /** + * 变动含税金额 + */ + private BigDecimal taxAmount; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 业务单据ID + */ + private String bizId; + + /** + * 业务单据号 + */ + private String bizCode; + + /** + * 业务单据明细ID + */ + private String bizDetailId; + + /** + * 业务类型 + */ + private ProductStockBizType bizType; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseConfig.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseConfig.java new file mode 100644 index 0000000..9e0ee93 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseConfig.java @@ -0,0 +1,46 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-09-12 + */ +@Data +@TableName("tbl_purchase_config") +public class PurchaseConfig extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "PurchaseConfig"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 采购收货单是否关联采购订单 + */ + private Boolean receiveRequirePurchase; + + /** + * 采购收货单是否多次关联采购订单 + */ + private Boolean receiveMultipleRelatePurchase; + + /** + * 采购退货单是否关联采购收货单 + */ + private Boolean purchaseReturnRequireReceive; + + /** + * 采购退货单是否多次关联采购收货单 + */ + private Boolean purchaseReturnMultipleRelateReceive; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrder.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrder.java new file mode 100644 index 0000000..4a26855 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrder.java @@ -0,0 +1,133 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-09-12 + */ +@Data +@TableName("tbl_purchase_order") +public class PurchaseOrder extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 预计到货日期 + */ + private LocalDate expectArriveDate; + + /** + * 采购数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 采购金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private PurchaseOrderStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrderDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrderDetail.java new file mode 100644 index 0000000..0155721 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseOrderDetail.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-09-12 + */ +@Data +@TableName("tbl_purchase_order_detail") +public class PurchaseOrderDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 订单ID + */ + private String orderId; + + /** + * 商品ID + */ + private String productId; + + /** + * 采购数量 + */ + private Integer orderNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已收货数量 + */ + private Integer receiveNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturn.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturn.java new file mode 100644 index 0000000..f0086cf --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturn.java @@ -0,0 +1,146 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.PurchaseReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-16 + */ +@Data +@TableName("tbl_purchase_return") +public class PurchaseReturn extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 收货单ID + */ + private String receiveSheetId; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 退货金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private PurchaseReturnStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturnDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturnDetail.java new file mode 100644 index 0000000..c76d8f6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/PurchaseReturnDetail.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-16 + */ +@Data +@TableName("tbl_purchase_return_detail") +public class PurchaseReturnDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 收货单ID + */ + private String returnId; + + /** + * 商品ID + */ + private String productId; + + /** + * 退货数量 + */ + private Integer returnNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 收货单明细ID + */ + private String receiveSheetDetailId; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheet.java new file mode 100644 index 0000000..5b2012f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheet.java @@ -0,0 +1,149 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-09 + */ +@Data +@TableName("tbl_receive_sheet") +public class ReceiveSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 采购员ID + */ + private String purchaserId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 到货日期 + */ + private LocalDate receiveDate; + + /** + * 采购单ID + */ + private String purchaseOrderId; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 收货金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private ReceiveSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheetDetail.java new file mode 100644 index 0000000..21c4c55 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ReceiveSheetDetail.java @@ -0,0 +1,79 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-09 + */ +@Data +@TableName("tbl_receive_sheet_detail") +public class ReceiveSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 收货单ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 采购数量 + */ + private Integer orderNum; + + /** + * 采购价 + */ + private BigDecimal taxPrice; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 采购订单明细ID + */ + private String purchaseOrderDetailId; + + /** + * 已退货数量 + */ + private Integer returnNum; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailConfig.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailConfig.java new file mode 100644 index 0000000..fb25457 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailConfig.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-09-12 + */ +@Data +@TableName("tbl_retail_config") +public class RetailConfig extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "RetailConfig"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 零售出库单上的会员是否必填 + */ + private Boolean retailOutSheetRequireMember; + + /** + * 零售退货单是否关联零售出库单 + */ + private Boolean retailReturnRequireOutStock; + + /** + * 零售退货单是否多次关联零售出库单 + */ + private Boolean retailReturnMultipleRelateOutStock; + + /** + * 零售退货单上的会员是否必填 + */ + private Boolean retailReturnRequireMember; + + /** + * 零售出库单是否需要发货 + */ + private Boolean retailOutSheetRequireLogistics; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheet.java new file mode 100644 index 0000000..25aac1f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheet.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.RetailOutSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-26 + */ +@Data +@TableName("tbl_retail_out_sheet") +public class RetailOutSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 会员ID + */ + private String memberId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 出库金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private RetailOutSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetail.java new file mode 100644 index 0000000..54eabcd --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetail.java @@ -0,0 +1,93 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-26 + */ +@Data +@TableName("tbl_retail_out_sheet_detail") +public class RetailOutSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 出库单ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣率(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 已退货数量 + */ + private Integer returnNum; + + /** + * 组合商品原始明细ID + */ + private String oriBundleDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailBundle.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailBundle.java new file mode 100644 index 0000000..2182b2a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailBundle.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2023-05-26 + */ +@Data +@TableName("tbl_retail_out_sheet_detail_bundle") +public class RetailOutSheetDetailBundle extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "RetailOutSheetDetailBundle"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 出库单ID + */ + private String sheetId; + + /** + * 明细ID + */ + private String detailId; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 组合商品数量 + */ + private Integer orderNum; + + /** + * 单品ID + */ + private String productId; + + /** + * 单品数量 + */ + private Integer productOrderNum; + + /** + * 单品原价 + */ + private BigDecimal productOriPrice; + + /** + * 单品含税价格 + */ + private BigDecimal productTaxPrice; + + /** + * 单品税率 + */ + private BigDecimal productTaxRate; + + /** + * 单品明细ID + */ + private String productDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailLot.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailLot.java new file mode 100644 index 0000000..1f4c535 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailOutSheetDetailLot.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-03 + */ +@Data +@TableName("tbl_retail_out_sheet_detail_lot") +public class RetailOutSheetDetailLot extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 明细ID + */ + private String detailId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 已退货数量 + */ + private Integer returnNum; + + /** + * 含税成本金额 + */ + private BigDecimal costTaxAmount; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturn.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturn.java new file mode 100644 index 0000000..14a18d9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturn.java @@ -0,0 +1,146 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.RetailReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-04 + */ +@Data +@TableName("tbl_retail_return") +public class RetailReturn extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 会员ID + */ + private String memberId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 出库单ID + */ + private String outSheetId; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 退货金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private RetailReturnStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturnDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturnDetail.java new file mode 100644 index 0000000..c3e875d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/RetailReturnDetail.java @@ -0,0 +1,90 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-04 + */ +@Data +@TableName("tbl_retail_return_detail") +public class RetailReturnDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 退货单ID + */ + private String returnId; + + /** + * 商品ID + */ + private String productId; + + /** + * 退货数量 + */ + private Integer returnNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣率(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 出库单明细ID + */ + private String outSheetDetailId; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleConfig.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleConfig.java new file mode 100644 index 0000000..cd62683 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleConfig.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-09-12 + */ +@Data +@TableName("tbl_sale_config") +public class SaleConfig extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SaleConfig"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 销售出库单是否关联销售订单 + */ + private Boolean outStockRequireSale; + + /** + * 销售出库单是否多次关联销售订单 + */ + private Boolean outStockMultipleRelateSale; + + /** + * 销售退货单是否关联销售出库单 + */ + private Boolean saleReturnRequireOutStock; + + /** + * 销售退货单是否多次关联销售出库单 + */ + private Boolean saleReturnMultipleRelateOutStock; + + /** + * 销售出库单是否需要物流单 + */ + private Boolean outStockRequireLogistics; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrder.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrder.java new file mode 100644 index 0000000..2e0a232 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrder.java @@ -0,0 +1,129 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SaleOrderStatus; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-21 + */ +@Data +@TableName("tbl_sale_order") +public class SaleOrder extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 销售数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 销售金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SaleOrderStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetail.java new file mode 100644 index 0000000..84209fe --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetail.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-21 + */ +@Data +@TableName("tbl_sale_order_detail") +public class SaleOrderDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 订单ID + */ + private String orderId; + + /** + * 商品ID + */ + private String productId; + + /** + * 销售数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣率(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 已出库数量 + */ + private Integer outNum; + + /** + * 组合商品原始明细ID + */ + private String oriBundleDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetailBundle.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetailBundle.java new file mode 100644 index 0000000..7fe1f7f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOrderDetailBundle.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2023-05-26 + */ +@Data +@TableName("tbl_sale_order_detail_bundle") +public class SaleOrderDetailBundle extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SaleOrderDetailBundle"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 销售单ID + */ + private String orderId; + + /** + * 明细ID + */ + private String detailId; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 组合商品数量 + */ + private Integer orderNum; + + /** + * 单品ID + */ + private String productId; + + /** + * 单品数量 + */ + private Integer productOrderNum; + + /** + * 单品原价 + */ + private BigDecimal productOriPrice; + + /** + * 单品含税价格 + */ + private BigDecimal productTaxPrice; + + /** + * 单品税率 + */ + private BigDecimal productTaxRate; + + /** + * 单品明细ID + */ + private String productDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheet.java new file mode 100644 index 0000000..7d8c73c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheet.java @@ -0,0 +1,144 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SaleOutSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-26 + */ +@Data +@TableName("tbl_sale_out_sheet") +public class SaleOutSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 销售单ID + */ + private String saleOrderId; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 出库金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SaleOutSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetail.java new file mode 100644 index 0000000..4cd348e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetail.java @@ -0,0 +1,98 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-10-26 + */ +@Data +@TableName("tbl_sale_out_sheet_detail") +public class SaleOutSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 出库单ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣率(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 销售订单明细ID + */ + private String saleOrderDetailId; + + /** + * 已退货数量 + */ + private Integer returnNum; + + /** + * 组合商品原始明细ID + */ + private String oriBundleDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailBundle.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailBundle.java new file mode 100644 index 0000000..ffd3da3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailBundle.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2023-05-26 + */ +@Data +@TableName("tbl_sale_out_sheet_detail_bundle") +public class SaleOutSheetDetailBundle extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SaleOutSheetDetailBundle"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 出库单ID + */ + private String sheetId; + + /** + * 明细ID + */ + private String detailId; + + /** + * 组合商品ID + */ + private String mainProductId; + + /** + * 组合商品数量 + */ + private Integer orderNum; + + /** + * 单品ID + */ + private String productId; + + /** + * 单品数量 + */ + private Integer productOrderNum; + + /** + * 单品原价 + */ + private BigDecimal productOriPrice; + + /** + * 单品含税价格 + */ + private BigDecimal productTaxPrice; + + /** + * 单品税率 + */ + private BigDecimal productTaxRate; + + /** + * 单品明细ID + */ + private String productDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailLot.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailLot.java new file mode 100644 index 0000000..98428aa --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleOutSheetDetailLot.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-03 + */ +@Data +@TableName("tbl_sale_out_sheet_detail_lot") +public class SaleOutSheetDetailLot extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 明细ID + */ + private String detailId; + + /** + * 出库数量 + */ + private Integer orderNum; + + /** + * 已退货数量 + */ + private Integer returnNum; + + /** + * 含税成本金额 + */ + private BigDecimal costTaxAmount; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturn.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturn.java new file mode 100644 index 0000000..a6024e9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturn.java @@ -0,0 +1,146 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SaleReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-04 + */ +@Data +@TableName("tbl_sale_return") +public class SaleReturn extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 客户ID + */ + private String customerId; + + /** + * 销售员ID + */ + private String salerId; + + /** + * 付款日期 + */ + private LocalDate paymentDate; + + /** + * 出库单ID + */ + private String outSheetId; + + /** + * 商品数量 + */ + private Integer totalNum; + + /** + * 赠品数量 + */ + private Integer totalGiftNum; + + /** + * 退货金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SaleReturnStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturnDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturnDetail.java new file mode 100644 index 0000000..733aac4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/SaleReturnDetail.java @@ -0,0 +1,90 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.SettleStatus; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-04 + */ +@Data +@TableName("tbl_sale_return_detail") +public class SaleReturnDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 退货单ID + */ + private String returnId; + + /** + * 商品ID + */ + private String productId; + + /** + * 退货数量 + */ + private Integer returnNum; + + /** + * 原价 + */ + private BigDecimal oriPrice; + + /** + * 现价 + */ + private BigDecimal taxPrice; + + /** + * 折扣率(%) + */ + private BigDecimal discountRate; + + /** + * 是否赠品 + */ + private Boolean isGift; + + /** + * 税率(%) + */ + private BigDecimal taxRate; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 出库单明细ID + */ + private String outSheetDetailId; + + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrder.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrder.java new file mode 100644 index 0000000..3f05317 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrder.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.ScTransferOrderStatus; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 仓库调拨单 + *

+ * + * @author zmj + * @since 2023-04-18 + */ +@Data +@TableName("tbl_sc_transfer_order") +public class ScTransferOrder extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 转出仓库ID + */ + private String sourceScId; + + /** + * 转入仓库ID + */ + private String targetScId; + + /** + * 调拨数量 + */ + private Integer totalNum; + + /** + * 调拨成本金额 + */ + private BigDecimal totalAmount; + + /** + * 状态 + */ + private ScTransferOrderStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + private String refuseReason; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetail.java new file mode 100644 index 0000000..fb162fa --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetail.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * 仓库调拨单明细 + *

+ * + * @author zmj + * @since 2023-04-18 + */ +@Data +@TableName("tbl_sc_transfer_order_detail") +public class ScTransferOrderDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 调拨单ID + */ + private String orderId; + + /** + * 商品ID + */ + private String productId; + + /** + * 调拨数量 + */ + private Integer transferNum; + + /** + * 成本价 + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String description; + + /** + * 排序 + */ + private Integer orderNo; + + /** + * 已收货数量 + */ + private Integer receiveNum; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetailReceive.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetailReceive.java new file mode 100644 index 0000000..5b27dc3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/ScTransferOrderDetailReceive.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 仓库调拨单收货明细 + *

+ * + * @author zmj + * @since 2023-05-24 + */ +@Data +@TableName("tbl_sc_transfer_order_detail_receive") +public class ScTransferOrderDetailReceive extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 调拨单ID + */ + private String orderId; + + /** + * 明细ID + */ + private String detailId; + + /** + * 收货数量 + */ + private Integer receiveNum; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustReason.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustReason.java new file mode 100644 index 0000000..be0aa61 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustReason.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 库存调整原因 + *

+ * + * @author zmj + * @since 2023-04-18 + */ +@Data +@TableName("tbl_stock_adjust_reason") +public class StockAdjustReason extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "StockAdjustReason"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheet.java new file mode 100644 index 0000000..0b894e8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheet.java @@ -0,0 +1,113 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.StockAdjustSheetBizType; +import com.lframework.xingyun.sc.enums.StockAdjustSheetStatus; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 库存调整单 + *

+ * + * @author zmj + * @since 2023-04-18 + */ +@Data +@TableName("tbl_stock_adjust_sheet") +public class StockAdjustSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 业务类型 + */ + private StockAdjustSheetBizType bizType; + + /** + * 调整原因ID + */ + private String reasonId; + + /** + * 状态 + */ + private StockAdjustSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + private String refuseReason; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheetDetail.java new file mode 100644 index 0000000..c0b6b54 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockAdjustSheetDetail.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 库存调整单明细 + *

+ * + * @author zmj + * @since 2023-04-18 + */ +@Data +@TableName("tbl_stock_adjust_sheet_detail") +public class StockAdjustSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单据ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 调整库存数量 + */ + private Integer stockNum; + + /** + * 备注 + */ + private String description; + + /** + * 排序 + */ + private Integer orderNo; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheet.java new file mode 100644 index 0000000..9fbd41c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheet.java @@ -0,0 +1,112 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.StockCostAdjustSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 库存成本调整单 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_stock_cost_adjust_sheet") +public class StockCostAdjustSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 调价品种数 + */ + private Integer productNum; + + /** + * 库存调价差额 + */ + private BigDecimal diffAmount; + + /** + * 状态 + */ + private StockCostAdjustSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝原因 + */ + private String refuseReason; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheetDetail.java new file mode 100644 index 0000000..ef3da73 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/StockCostAdjustSheetDetail.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * 库存成本调整单明细 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_stock_cost_adjust_sheet_detail") +public class StockCostAdjustSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单据ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 库存数量 + */ + private Integer stockNum; + + /** + * 档案采购价 + */ + private BigDecimal purchasePrice; + + /** + * 调整前成本价 + */ + private BigDecimal oriPrice; + + /** + * 调整后成本价 + */ + private BigDecimal price; + + /** + * 库存调价差额 + */ + private BigDecimal diffAmount; + + /** + * 备注 + */ + private String description; + + /** + * 排序 + */ + private Integer orderNo; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockConfig.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockConfig.java new file mode 100644 index 0000000..e5d63c4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockConfig.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 盘点参数 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_take_stock_config") +public class TakeStockConfig extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "TakeStockConfig"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据 + */ + private Boolean showProduct; + + /** + * 库存盘点单是否显示盘点任务创建时商品的系统库存数量 + */ + private Boolean showStock; + + /** + * 盘点差异生成时是否自动调整盘点任务中商品的系统库存数量 + */ + private Boolean autoChangeStock; + + /** + * 盘点差异单中的盘点数量是否允许手动修改 + */ + private Boolean allowChangeNum; + + /** + * 盘点任务创建后多少小时内未完成,则自动作废 + */ + private Integer cancelHours; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlan.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlan.java new file mode 100644 index 0000000..e798491 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlan.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 盘点任务 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_take_stock_plan") +public class TakeStockPlan extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "TakeStockPlan"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 仓库ID + */ + private String scId; + + /** + * 盘点类别 + */ + private TakeStockPlanType takeType; + + /** + * 业务ID + */ + private String bizId; + + /** + * 盘点状态 + */ + private TakeStockPlanStatus takeStatus; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlanDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlanDetail.java new file mode 100644 index 0000000..19c9864 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockPlanDetail.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 盘点任务详情 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_take_stock_plan_detail") +public class TakeStockPlanDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 盘点任务ID + */ + private String planId; + + /** + * 商品ID + */ + private String productId; + + /** + * 初始库存数量 + */ + private Integer stockNum; + + /** + * 盘点数量 + */ + private Integer oriTakeNum; + + /** + * 修改后的盘点数量 + */ + private Integer takeNum; + + /** + * 出项数量 + */ + private Integer totalOutNum; + + /** + * 入项数量 + */ + private Integer totalInNum; + + /** + * 备注 + */ + private String description; + + /** + * 排序 + */ + private Integer orderNo; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheet.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheet.java new file mode 100644 index 0000000..afb34ef --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheet.java @@ -0,0 +1,111 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.sc.enums.TakeStockSheetStatus; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 盘点单 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_take_stock_sheet") +public class TakeStockSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 业务单据号 + */ + private String code; + + /** + * 盘点任务ID + */ + private String planId; + + /** + * 预先盘点单ID + */ + private String preSheetId; + + /** + * 仓库ID + */ + private String scId; + + /** + * 状态 + */ + private TakeStockSheetStatus status; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 拒绝理由 + */ + private String refuseReason; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheetDetail.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheetDetail.java new file mode 100644 index 0000000..0fa12c4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/entity/TakeStockSheetDetail.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.sc.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * 盘点单详情 + *

+ * + * @author zmj + */ +@Data +@TableName("tbl_take_stock_sheet_detail") +public class TakeStockSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 盘点单ID + */ + private String sheetId; + + /** + * 商品ID + */ + private String productId; + + /** + * 盘点数量 + */ + private Integer takeNum; + + /** + * 备注 + */ + private String description; + + /** + * 排序 + */ + private Integer orderNo; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetDetailBizType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetDetailBizType.java new file mode 100644 index 0000000..d7398c4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetDetailBizType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum LogisticsSheetDetailBizType implements BaseEnum { + SALE_OUT_SHEET(1, "销售出库单"), RETAIL_OUT_SHEET(2, "零售出库单"); + + @EnumValue + private final Integer code; + + private final String desc; + + LogisticsSheetDetailBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetStatus.java new file mode 100644 index 0000000..bee571e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/LogisticsSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum LogisticsSheetStatus implements BaseEnum { + CREATED(0, "待发货"), DELIVERY(3, "已发货"); + + @EnumValue + private final Integer code; + + private final String desc; + + LogisticsSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/OrderAddressOrderType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/OrderAddressOrderType.java new file mode 100644 index 0000000..30e743a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/OrderAddressOrderType.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum OrderAddressOrderType implements BaseEnum { + PURCHASE_ORDER(0, "采购订单"), RECEIVE_SHEET(1, "采购收货单"), PURCHASE_RETURN(2, "采购退单"), + SALE_ORDER(3, "采购订单"), OUT_SHEET(4, "销售出库单"), SALE_RETURN(5, "销售退单"), + RETAIL_OUT_SHEET(6, "零售出库单"), RETAIL_RETURN(7, "销售退单"); + + @EnumValue + private final Integer code; + + private final String desc; + + OrderAddressOrderType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PreTakeStockSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PreTakeStockSheetStatus.java new file mode 100644 index 0000000..83f68a5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PreTakeStockSheetStatus.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum PreTakeStockSheetStatus implements BaseEnum { + FIRST_TAKE(0, "初盘"), SECOND_TAKE(1, "复盘"), RAND_TAKE(2, "抽盘"), + ; + + @EnumValue + private final Integer code; + + private final String desc; + + PreTakeStockSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ProductStockBizType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ProductStockBizType.java new file mode 100644 index 0000000..ee9debc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ProductStockBizType.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ProductStockBizType implements BaseEnum { + PURCHASE(1, "采购入库"), PURCHASE_RETURN(2, "采购退货出库"), SALE(3, "销售出库"), SALE_RETURN(4, + "销售退货入库"), RETAIL(5, + "零售出库"), RETAIL_RETURN(6, "零售退货入库"), TAKE_STOCK_IN(7, "盘点入库"), TAKE_STOCK_OUT(8, + "盘点出库"), STOCK_COST_ADJUST( + 9, "库存成本调整"), STOCK_ADJUST(10, "库存调整"), SC_TRANSFER(11, "仓库调拨"); + + @EnumValue + private final Integer code; + + private final String desc; + + ProductStockBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseOrderStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseOrderStatus.java new file mode 100644 index 0000000..840b38e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseOrderStatus.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum PurchaseOrderStatus implements BaseEnum { + CREATED(0, "待审核"), + APPROVE_ING(1, "审核中"), + APPROVE_PASS(3, "审核通过"), + APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private Integer code; + + private String desc; + + PurchaseOrderStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseReturnStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseReturnStatus.java new file mode 100644 index 0000000..dcf6846 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/PurchaseReturnStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum PurchaseReturnStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + PurchaseReturnStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ReceiveSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ReceiveSheetStatus.java new file mode 100644 index 0000000..8719d76 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ReceiveSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ReceiveSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + ReceiveSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailOutSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailOutSheetStatus.java new file mode 100644 index 0000000..63177c2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailOutSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum RetailOutSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"), APPROVE_ING(1, "审核中"); + + @EnumValue + private Integer code; + + private String desc; + + RetailOutSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailReturnStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailReturnStatus.java new file mode 100644 index 0000000..b46a453 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/RetailReturnStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum RetailReturnStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private Integer code; + + private String desc; + + RetailReturnStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOrderStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOrderStatus.java new file mode 100644 index 0000000..0a776ed --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOrderStatus.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SaleOrderStatus implements BaseEnum { + CREATED(0, "待审核"), + APPROVE_ING(1, "审核中"), + APPROVE_PASS(3, "审核通过"), + APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private Integer code; + + private String desc; + + SaleOrderStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOutSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOutSheetStatus.java new file mode 100644 index 0000000..794a8b3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleOutSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SaleOutSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private Integer code; + + private String desc; + + SaleOutSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleReturnStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleReturnStatus.java new file mode 100644 index 0000000..ce8d1c0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SaleReturnStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SaleReturnStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private Integer code; + + private String desc; + + SaleReturnStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScOpLogType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScOpLogType.java new file mode 100644 index 0000000..d755598 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScOpLogType.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.sc.enums; + +public interface ScOpLogType { + + // 物流单管理 + int LOGISTICS = 2000; + + // 采购业务 + int PURCHASE = 2001; + + // 零售业务 + int RETAIL = 2002; + + // 销售业务 + int SALE = 2003; + + // 库存调整 + int STOCK_ADJUST = 2004; + + // 仓库调拨 + int SC_TRANSFER = 2005; + + // 库存盘点 + int TAKE_STOCK = 2006; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScTransferOrderStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScTransferOrderStatus.java new file mode 100644 index 0000000..ca573d5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/ScTransferOrderStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum ScTransferOrderStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"), PART_RECEIVED(9, "部分收货"), RECEIVED(12, "已收货"); + + @EnumValue + private Integer code; + + private String desc; + + ScTransferOrderStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SettleStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SettleStatus.java new file mode 100644 index 0000000..cd6ce64 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/SettleStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleStatus implements BaseEnum { + UN_SETTLE(0, "未结算"), PART_SETTLE(1, "结算中"), SETTLED(3, "已结算"), UN_REQUIRE(6, "无需结算"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetBizType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetBizType.java new file mode 100644 index 0000000..20f2ba0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetBizType.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum StockAdjustSheetBizType implements BaseEnum { + IN(0, "入库"), OUT(2, "出库"); + + @EnumValue + private Integer code; + + private String desc; + + StockAdjustSheetBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + /** + * 根据code返回desc + */ + public static String descByCode(Integer code) { + + for (StockAdjustSheetBizType item : StockAdjustSheetBizType.values()) { + if (item.getCode().equals(code)) { + return item.getDesc(); + } + } + + return null; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetStatus.java new file mode 100644 index 0000000..e7c7cc0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockAdjustSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum StockAdjustSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"), APPROVE_ING(1, "审核中"); + + @EnumValue + private Integer code; + + private String desc; + + StockAdjustSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockCostAdjustSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockCostAdjustSheetStatus.java new file mode 100644 index 0000000..d65c1d0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/StockCostAdjustSheetStatus.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum StockCostAdjustSheetStatus implements BaseEnum { + CREATED(0, "待审核"), + APPROVE_ING(1, "审核中"), + APPROVE_PASS(3, "审核通过"), + APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private Integer code; + + private String desc; + + StockCostAdjustSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanStatus.java new file mode 100644 index 0000000..9a0edd8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum TakeStockPlanStatus implements BaseEnum { + CREATED(0, "盘点任务生成"), DIFF_CREATED(6, "盘点差异生成"), FINISHED(9, "盘点完成"), CANCELED(12, "盘点已作废"); + + @EnumValue + private final Integer code; + + private final String desc; + + TakeStockPlanStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanType.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanType.java new file mode 100644 index 0000000..480cfd4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockPlanType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum TakeStockPlanType implements BaseEnum { + ALL(0, "全场盘点"), SIMPLE(1, "单品盘点"), CATEGORY(2, "类目盘点"), BRAND(3, "品牌盘点"); + + @EnumValue + private final Integer code; + + private final String desc; + + TakeStockPlanType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockSheetStatus.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockSheetStatus.java new file mode 100644 index 0000000..7b962ad --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/enums/TakeStockSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum TakeStockSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + TakeStockSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportListener.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportListener.java new file mode 100644 index 0000000..565fd0d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportListener.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.sc.excel.logistics; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetService; +import com.lframework.xingyun.sc.vo.logistics.DeliveryLogisticsSheetVo; +import java.math.BigDecimal; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class LogisticsSheetDeliveryImportListener extends + ExcelImportListener { + + @Override + protected void doInvoke(LogisticsSheetDeliveryImportModel data, AnalysisContext context) { + + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”不能为空"); + } + + LogisticsSheetService logisticsSheetService = ApplicationUtil.getBean( + LogisticsSheetService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(LogisticsSheet.class) + .eq(LogisticsSheet::getCode, data.getCode()); + LogisticsSheet sheet = logisticsSheetService.getOne(queryWrapper); + if (sheet == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”不存在"); + } + data.setId(sheet.getId()); + + if (data.getTotalAmount() != null) { + if (NumberUtil.lt(data.getTotalAmount(), BigDecimal.ZERO)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“物流费”不能小于0"); + } + if (!NumberUtil.isNumberPrecision(data.getTotalAmount(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“物流费”最多允许2位小数"); + } + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + LogisticsSheetService logisticsSheetService = ApplicationUtil.getBean( + LogisticsSheetService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + LogisticsSheetDeliveryImportModel data = datas.get(i); + + DeliveryLogisticsSheetVo deliveryLogisticsSheetVo = new DeliveryLogisticsSheetVo(); + deliveryLogisticsSheetVo.setId(data.getId()); + deliveryLogisticsSheetVo.setLogisticsNo(data.getLogisticsNo()); + deliveryLogisticsSheetVo.setTotalAmount(data.getTotalAmount()); + + try { + logisticsSheetService.delivery(deliveryLogisticsSheetVo); + } catch (Exception e) { + throw new DefaultClientException( + "第" + (i + 1) + "行发货失败,失败原因:" + e.getMessage()); + } + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportModel.java new file mode 100644 index 0000000..366ae8a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetDeliveryImportModel.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.excel.logistics; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class LogisticsSheetDeliveryImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 单据号 + */ + @ExcelRequired + @ExcelProperty("单据号") + private String code; + + /** + * 物流单号 + */ + @ExcelProperty("物流单号") + private String logisticsNo; + + /** + * 物流费 + */ + @ExcelProperty("物流费(元)") + private BigDecimal totalAmount; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetExportModel.java new file mode 100644 index 0000000..0b5f27e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetExportModel.java @@ -0,0 +1,211 @@ +package com.lframework.xingyun.sc.excel.logistics; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.service.logistics.LogisticsCompanyService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class LogisticsSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("单号") + private String code; + + /** + * 物流单号 + */ + @ExcelProperty("物流单号") + private String logisticsNo; + + /** + * 物流公司 + */ + @ExcelProperty("物流公司") + private String logisticsCompanyName; + + /** + * 寄件人姓名 + */ + @ExcelProperty("寄件人姓名") + private String senderName; + + /** + * 寄件人联系电话 + */ + @ExcelProperty("寄件人联系电话") + private String senderTelephone; + + /** + * 寄件人省 + */ + @ExcelProperty("寄件人省") + private String senderProvinceName; + + /** + * 寄件人市 + */ + @ExcelProperty("寄件人市") + private String senderCityName; + + /** + * 寄件人区 + */ + @ExcelProperty("寄件人区") + private String senderDistrictName; + + /** + * 寄件人地址 + */ + @ExcelProperty("寄件人地址") + private String senderAddress; + + /** + * 收件人姓名 + */ + @ExcelProperty("收件人姓名") + private String receiverName; + + /** + * 收件人联系电话 + */ + @ExcelProperty("收件人联系电话") + private String receiverTelephone; + + /** + * 收件人省 + */ + @ExcelProperty("收件人省") + private String receiverProvinceName; + + /** + * 收件人市 + */ + @ExcelProperty("收件人市") + private String receiverCityName; + + /** + * 收件人区 + */ + @ExcelProperty("收件人区") + private String receiverDistrictName; + + /** + * 收件人地址 + */ + @ExcelProperty("收件人地址") + private String receiverAddress; + + /** + * 状态 + */ + @ExcelProperty("状态") + private String status; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 总重量 + */ + @ExcelProperty("总重量(kg)") + private BigDecimal totalWeight; + + /** + * 总体积 + */ + @ExcelProperty("总体积(cm³)") + private BigDecimal totalVolume; + + /** + * 物流费 + */ + @ExcelProperty("物流费(元)") + private BigDecimal totalAmount; + + /** + * 创建人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 创建时间 + */ + @ExcelProperty("操作时间") + private Date createTime; + + /** + * 发货人 + */ + @ExcelProperty("发货人") + private String deliveryBy; + + /** + * 发货时间 + */ + @ExcelProperty("发货时间") + private Date deliveryTime; + + public LogisticsSheetExportModel() { + + } + + public LogisticsSheetExportModel(LogisticsSheet dto) { + + super(dto); + } + + @Override + protected void afterInit(LogisticsSheet dto) { + + LogisticsCompanyService logisticsCompanyService = ApplicationUtil.getBean( + LogisticsCompanyService.class); + LogisticsCompany logisticsCompany = logisticsCompanyService.findById( + dto.getLogisticsCompanyId()); + this.logisticsCompanyName = logisticsCompany.getName(); + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + DicCityDto senderProvince = dicCityService.findById(dto.getSenderProvinceId()); + this.senderProvinceName = senderProvince.getName(); + + DicCityDto senderCity = dicCityService.findById(dto.getSenderCityId()); + this.senderCityName = senderCity.getName(); + + DicCityDto senderDistrict = dicCityService.findById(dto.getSenderDistrictId()); + this.senderDistrictName = senderDistrict.getName(); + + DicCityDto receiverProvince = dicCityService.findById(dto.getReceiverProvinceId()); + this.receiverProvinceName = receiverProvince.getName(); + + DicCityDto receiverCity = dicCityService.findById(dto.getReceiverCityId()); + this.receiverCityName = receiverCity.getName(); + + DicCityDto receiverDistrict = dicCityService.findById(dto.getReceiverDistrictId()); + this.receiverDistrictName = receiverDistrict.getName(); + + this.status = dto.getStatus().getDesc(); + + if (StringUtil.isNotBlank(dto.getDeliveryBy())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto deliveryBy = userService.findById(dto.getDeliveryBy()); + this.deliveryBy = deliveryBy.getName(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportListener.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportListener.java new file mode 100644 index 0000000..5ef88e7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportListener.java @@ -0,0 +1,336 @@ +package com.lframework.xingyun.sc.excel.logistics; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.xingyun.basedata.entity.LogisticsCompany; +import com.lframework.xingyun.basedata.service.logistics.LogisticsCompanyService; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetDetailService; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.sc.vo.logistics.CreateLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.LogisticsSheetBizOrderVo; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class LogisticsSheetImportListener extends ExcelImportListener { + + @Override + protected void doInvoke(LogisticsSheetImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getSaleOutSheetCodes()) && StringUtil.isBlank( + data.getRetailOutSheetCodes())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + + "行“销售出库单号、零售出库单号”不能同时为空"); + } + + if (StringUtil.isNotBlank(data.getSaleOutSheetCodes())) { + + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + List arr = CollectionUtil.toList( + data.getSaleOutSheetCodes().split(StringPool.STR_SPLIT)); + Wrapper querySaleOutSheetWrapper = Wrappers.lambdaQuery(SaleOutSheet.class) + .in(SaleOutSheet::getCode, arr); + List saleOutSheets = saleOutSheetService.list(querySaleOutSheetWrapper); + if (saleOutSheets.size() != arr.size()) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“销售出库单号(" + arr.stream() + .filter(t -> !saleOutSheets.contains(t)) + .collect(Collectors.joining(StringPool.STR_SPLIT_CN)) + ")”不存在"); + } + + data.setSaleOutSheetIds(new HashMap<>()); + for (SaleOutSheet saleOutSheet : saleOutSheets) { + data.getSaleOutSheetIds().put(saleOutSheet.getId(), saleOutSheet.getCode()); + } + } + + if (StringUtil.isNotBlank(data.getRetailOutSheetCodes())) { + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + List arr = CollectionUtil.toList( + data.getRetailOutSheetCodes().split(StringPool.STR_SPLIT)); + Wrapper queryRetailOutSheetWrapper = Wrappers.lambdaQuery( + RetailOutSheet.class).in(RetailOutSheet::getCode, arr); + List retailOutSheets = retailOutSheetService.list(queryRetailOutSheetWrapper); + if (retailOutSheets.size() != arr.size()) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“零售出库单号(" + arr.stream() + .filter(t -> !retailOutSheets.contains(t)) + .collect(Collectors.joining(StringPool.STR_SPLIT_CN)) + ")”不存在"); + } + + data.setRetailOutSheetIds(new HashMap<>()); + for (RetailOutSheet retailOutSheet : retailOutSheets) { + data.getRetailOutSheetIds().put(retailOutSheet.getId(), retailOutSheet.getCode()); + } + } + + if (StringUtil.isBlank(data.getLogisticsCompanyCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“物流公司编号”不能为空"); + } + LogisticsCompanyService logisticsCompanyService = ApplicationUtil.getBean( + LogisticsCompanyService.class); + Wrapper queryLogisticsCompanyWrapper = Wrappers.lambdaQuery( + LogisticsCompany.class).eq(LogisticsCompany::getCode, data.getLogisticsCompanyCode()); + LogisticsCompany logisticsCompany = logisticsCompanyService.getOne( + queryLogisticsCompanyWrapper); + if (logisticsCompany == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“物流公司编号”不存在"); + } + data.setLogisticsCompanyId(logisticsCompany.getId()); + + if (StringUtil.isBlank(data.getSenderName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人姓名”不能为空"); + } + if (StringUtil.isBlank(data.getSenderTelephone())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人联系电话”不能为空"); + } + if (StringUtil.isBlank(data.getSenderProvinceName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人省”不能为空"); + } + if (StringUtil.isBlank(data.getSenderCityName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人市”不能为空"); + } + if (StringUtil.isBlank(data.getSenderDistrictName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人区”不能为空"); + } + + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class); + List allCitys = dicCityService.getAll(); + DicCityDto senderProvince = allCitys.stream() + .filter(t -> StringUtil.isEmpty(t.getParentId()) && t.getName() + .equals(data.getSenderProvinceName())) + .findFirst().orElse(null); + if (senderProvince == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人省”不存在"); + } + data.setSenderProvinceId(senderProvince.getId()); + + DicCityDto senderCity = allCitys.stream() + .filter(t -> senderProvince.getId().equals(t.getParentId()) && t.getName() + .equals(data.getSenderCityName())) + .findFirst().orElse(null); + if (senderCity == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人市”不存在"); + } + data.setSenderCityId(senderCity.getId()); + + DicCityDto senderDistrict = allCitys.stream() + .filter(t -> senderCity.getId().equals(t.getParentId()) && t.getName() + .equals(data.getSenderDistrictName())) + .findFirst().orElse(null); + if (senderDistrict == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人区”错误不存在"); + } + data.setSenderDistrictId(senderDistrict.getId()); + + if (StringUtil.isBlank(data.getSenderAddress())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“寄件人地址”不能为空"); + } + + if (StringUtil.isBlank(data.getReceiverName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人姓名”不能为空"); + } + if (StringUtil.isBlank(data.getReceiverTelephone())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人联系电话”不能为空"); + } + if (StringUtil.isBlank(data.getReceiverProvinceName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人省”不能为空"); + } + if (StringUtil.isBlank(data.getReceiverCityName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人市”不能为空"); + } + if (StringUtil.isBlank(data.getReceiverDistrictName())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人区”不能为空"); + } + + DicCityDto receiverProvince = allCitys.stream() + .filter(t -> StringUtil.isEmpty(t.getParentId()) && t.getName() + .equals(data.getReceiverProvinceName())) + .findFirst().orElse(null); + if (receiverProvince == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人省”不存在"); + } + data.setReceiverProvinceId(receiverProvince.getId()); + + DicCityDto receiverCity = allCitys.stream() + .filter(t -> receiverProvince.getId().equals(t.getParentId()) && t.getName() + .equals(data.getReceiverCityName())) + .findFirst().orElse(null); + if (receiverCity == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人市”不存在"); + } + data.setReceiverCityId(receiverCity.getId()); + + DicCityDto receiverDistrict = allCitys.stream() + .filter(t -> receiverCity.getId().equals(t.getParentId()) && t.getName() + .equals(data.getReceiverDistrictName())) + .findFirst().orElse(null); + if (receiverDistrict == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人区”错误不存在"); + } + data.setReceiverDistrictId(receiverDistrict.getId()); + + if (StringUtil.isBlank(data.getReceiverAddress())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收件人地址”不能为空"); + } + if (data.getTotalWeight() != null) { + if (NumberUtil.lt(data.getTotalWeight(), BigDecimal.ZERO)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“总重量”不能小于0"); + } + if (!NumberUtil.isNumberPrecision(data.getTotalWeight(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“总重量”最多允许2位小数"); + } + } + + if (data.getTotalVolume() != null) { + if (NumberUtil.lt(data.getTotalVolume(), BigDecimal.ZERO)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“总体积”不能小于0"); + } + if (!NumberUtil.isNumberPrecision(data.getTotalVolume(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“总体积”最多允许2位小数"); + } + } + + if (data.getTotalAmount() != null) { + if (NumberUtil.lt(data.getTotalAmount(), BigDecimal.ZERO)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“物流费”不能小于0"); + } + if (!NumberUtil.isNumberPrecision(data.getTotalAmount(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“物流费”最多允许2位小数"); + } + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + LogisticsSheetService logisticsSheetService = ApplicationUtil.getBean( + LogisticsSheetService.class); + + LogisticsSheetDetailService logisticsSheetDetailService = ApplicationUtil.getBean( + LogisticsSheetDetailService.class); + + List datas = this.getDatas(); + for (int i = 0; i < datas.size(); i++) { + LogisticsSheetImportModel data = datas.get(i); + if (CollectionUtil.isNotEmpty(data.getSaleOutSheetIds())) { + for (Entry entry : data.getSaleOutSheetIds().entrySet()) { + if (logisticsSheetDetailService.getByBizId(entry.getKey(), + LogisticsSheetDetailBizType.SALE_OUT_SHEET) != null) { + throw new DefaultClientException( + "销售出库单【" + entry.getValue() + "】已关联物流单,不允许再次关联物流单"); + } + } + } + + if (CollectionUtil.isNotEmpty(data.getRetailOutSheetIds())) { + for (Entry entry : data.getRetailOutSheetIds().entrySet()) { + if (logisticsSheetDetailService.getByBizId(entry.getKey(), + LogisticsSheetDetailBizType.RETAIL_OUT_SHEET) != null) { + throw new DefaultClientException( + "零售出库单【" + entry.getValue() + "】已关联物流单,不允许再次关联物流单"); + } + } + } + + CreateLogisticsSheetVo createLogisticsSheetVo = new CreateLogisticsSheetVo(); + createLogisticsSheetVo.setLogisticsNo(data.getLogisticsNo()); + createLogisticsSheetVo.setLogisticsCompanyId(data.getLogisticsCompanyId()); + createLogisticsSheetVo.setSenderName(data.getSenderName()); + createLogisticsSheetVo.setSenderTelephone(data.getSenderTelephone()); + createLogisticsSheetVo.setSenderProvinceId(data.getSenderProvinceId()); + createLogisticsSheetVo.setSenderCityId(data.getSenderCityId()); + createLogisticsSheetVo.setSenderDistrictId(data.getSenderDistrictId()); + createLogisticsSheetVo.setSenderAddress(data.getSenderAddress()); + createLogisticsSheetVo.setReceiverName(data.getReceiverName()); + createLogisticsSheetVo.setReceiverTelephone(data.getReceiverTelephone()); + createLogisticsSheetVo.setReceiverProvinceId(data.getReceiverProvinceId()); + createLogisticsSheetVo.setReceiverCityId(data.getReceiverCityId()); + createLogisticsSheetVo.setReceiverDistrictId(data.getReceiverDistrictId()); + createLogisticsSheetVo.setReceiverAddress(data.getReceiverAddress()); + createLogisticsSheetVo.setTotalWeight(data.getTotalWeight()); + createLogisticsSheetVo.setTotalVolume(data.getTotalVolume()); + createLogisticsSheetVo.setTotalAmount(data.getTotalAmount()); + createLogisticsSheetVo.setDescription(data.getDescription()); + createLogisticsSheetVo.setBizOrders(new ArrayList<>()); + if (CollectionUtil.isNotEmpty(data.getSaleOutSheetIds())) { + for (Entry entry : data.getSaleOutSheetIds().entrySet()) { + LogisticsSheetBizOrderVo bizOrderVo = new LogisticsSheetBizOrderVo(); + bizOrderVo.setBizId(entry.getKey()); + bizOrderVo.setBizType(LogisticsSheetDetailBizType.SALE_OUT_SHEET.getCode()); + createLogisticsSheetVo.getBizOrders().add(bizOrderVo); + } + } + + if (CollectionUtil.isNotEmpty(data.getRetailOutSheetIds())) { + for (Entry entry : data.getRetailOutSheetIds().entrySet()) { + LogisticsSheetBizOrderVo bizOrderVo = new LogisticsSheetBizOrderVo(); + bizOrderVo.setBizId(entry.getKey()); + bizOrderVo.setBizType(LogisticsSheetDetailBizType.RETAIL_OUT_SHEET.getCode()); + createLogisticsSheetVo.getBizOrders().add(bizOrderVo); + } + } + + try { + logisticsSheetService.create(createLogisticsSheetVo); + } catch (Exception e) { + throw new DefaultClientException( + "第" + (i + 1) + "行新增失败,失败原因:" + e.getMessage()); + } + + this.setSuccessProcess(i); + } + } + + @Override + protected void doComplete() { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportModel.java new file mode 100644 index 0000000..8535870 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/logistics/LogisticsSheetImportModel.java @@ -0,0 +1,200 @@ +package com.lframework.xingyun.sc.excel.logistics; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import java.util.Map; +import lombok.Data; + +@Data +public class LogisticsSheetImportModel implements ExcelModel { + + /** + * 物流单号 + */ + @ExcelProperty("物流单号") + private String logisticsNo; + + /** + * 销售出库单ID + */ + @ExcelIgnore + private Map saleOutSheetIds; + + /** + * 销售出库单号 + */ + @ExcelProperty("销售出库单号,多个用,分隔") + private String saleOutSheetCodes; + + /** + * 零售出库单ID + */ + @ExcelIgnore + private Map retailOutSheetIds; + + /** + * 零售出库单号 + */ + @ExcelProperty("零售出库单号,多个用,分隔") + private String retailOutSheetCodes; + + /** + * 物流公司ID + */ + @ExcelIgnore + private String logisticsCompanyId; + + /** + * 物流公司编号 + */ + @ExcelRequired + @ExcelProperty("物流公司编号") + private String logisticsCompanyCode; + + /** + * 寄件人姓名 + */ + @ExcelRequired + @ExcelProperty("寄件人姓名") + private String senderName; + + /** + * 寄件人联系电话 + */ + @ExcelRequired + @ExcelProperty("寄件人联系电话") + private String senderTelephone; + + /** + * 寄件人省ID + */ + @ExcelIgnore + private String senderProvinceId; + + /** + * 寄件人省 + */ + @ExcelRequired + @ExcelProperty("寄件人省") + private String senderProvinceName; + + /** + * 寄件人市ID + */ + @ExcelIgnore + private String senderCityId; + + /** + * 寄件人市 + */ + @ExcelRequired + @ExcelProperty("寄件人市") + private String senderCityName; + + /** + * 寄件人区ID + */ + @ExcelIgnore + private String senderDistrictId; + + /** + * 寄件人区 + */ + @ExcelRequired + @ExcelProperty("寄件人区") + private String senderDistrictName; + + /** + * 寄件人地址 + */ + @ExcelRequired + @ExcelProperty("寄件人地址") + private String senderAddress; + + /** + * 收件人姓名 + */ + @ExcelRequired + @ExcelProperty("收件人姓名") + private String receiverName; + + /** + * 收件人联系电话 + */ + @ExcelRequired + @ExcelProperty("收件人联系电话") + private String receiverTelephone; + + /** + * 收件人省ID + */ + @ExcelIgnore + private String receiverProvinceId; + + /** + * 收件人省 + */ + @ExcelRequired + @ExcelProperty("收件人省") + private String receiverProvinceName; + + /** + * 收件人市ID + */ + @ExcelIgnore + private String receiverCityId; + + /** + * 收件人市 + */ + @ExcelRequired + @ExcelProperty("收件人市") + private String receiverCityName; + + /** + * 收件人区ID + */ + @ExcelIgnore + private String receiverDistrictId; + + /** + * 收件人区 + */ + @ExcelRequired + @ExcelProperty("收件人区") + private String receiverDistrictName; + + /** + * 收件人地址 + */ + @ExcelRequired + @ExcelProperty("收件人地址") + private String receiverAddress; + + /** + * 总重量 + */ + @ExcelProperty("总重量(kg)") + private BigDecimal totalWeight; + + /** + * 总体积 + */ + @ExcelProperty("总体积(cm³)") + private BigDecimal totalVolume; + + /** + * 物流费 + */ + @ExcelProperty("物流费(元)") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderExportModel.java new file mode 100644 index 0000000..ab57610 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderExportModel.java @@ -0,0 +1,198 @@ +package com.lframework.xingyun.sc.excel.purchase; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class PurchaseOrderExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ExcelProperty("采购员") + private String purchaserName; + + /** + * 预计到货日期 + */ + @ExcelProperty("预计到货日期") + @DateTimeFormat(StringPool.DATE_PATTERN) + private Date expectArriveDate; + + /** + * 采购数量 + */ + @ExcelProperty("采购数量") + private Integer purchaseNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 采购金额 + */ + @ExcelProperty("采购金额") + private BigDecimal purchaseAmount; + + /** + * 约定支付 + */ + @ExcelProperty("约定支付") + private String payTypeStr; + + /** + * 备注 + */ + @ExcelProperty("订单备注") + private String description; + + /** + * 创建人 + */ + @ExcelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ExcelProperty("创建时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 状态 + */ + @ExcelProperty("状态") + private String status; + + /** + * 拒绝原因 + */ + @ExcelProperty("拒绝原因") + private String refuseReason; + + public PurchaseOrderExportModel() { + + } + + public PurchaseOrderExportModel(PurchaseOrder dto) { + + super(dto); + } + + @Override + public
BaseBo convert(PurchaseOrder dto) { + + return this; + } + + @Override + protected void afterInit(PurchaseOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScName(sc.getName()); + this.setSupplierName(supplier.getName()); + if (!StringUtil.isBlank(dto.getPurchaserId())) { + UserDto purchaser = userService.findById(dto.getPurchaserId()); + this.setPurchaserName(purchaser.getName()); + } + this.setExpectArriveDate(DateUtil.toDate(dto.getExpectArriveDate())); + this.setPurchaseNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setPurchaseAmount(dto.getTotalAmount()); + this.setDescription(dto.getDescription()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + + this.setStatus(dto.getStatus().getDesc()); + this.setRefuseReason(dto.getRefuseReason()); + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + + if (CollectionUtil.isNotEmpty(orderPayTypes)) { + this.payTypeStr = orderPayTypes.stream().map(orderPayType -> { + PayType payType = payTypeService.findById(orderPayType.getPayTypeId()); + return StringUtil.format("{}:{}元", payType.getName(), orderPayType.getPayAmount()); + }).collect(Collectors.joining(";")); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportListener.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportListener.java new file mode 100644 index 0000000..4c123ab --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportListener.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.sc.excel.purchase; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.vo.purchase.CreatePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.PurchaseProductVo; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PurchaseOrderImportListener extends ExcelImportListener { + + @Override + protected void doInvoke(PurchaseOrderImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getScCode())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“仓库编号”不能为空"); + } else { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(StoreCenter.class) + .eq(StoreCenter::getCode, data.getScCode()); + StoreCenter sc = storeCenterService.getOne(queryWrapper); + if (sc == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“仓库编号”不存在"); + } + + data.setScId(sc.getId()); + } + if (StringUtil.isBlank(data.getSupplierCode())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“仓库编号”不能为空"); + } else { + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Supplier.class) + .eq(Supplier::getCode, data.getSupplierCode()); + Supplier supplier = supplierService.getOne(queryWrapper); + if (supplier == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“供应商编号”不存在"); + } + + data.setSupplierId(supplier.getId()); + } + if (!StringUtil.isBlank(data.getPurchaserCode())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto purchaser = userService.findByCode(data.getPurchaserCode()); + if (purchaser == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购员编号”不存在"); + } + data.setPurchaserId(purchaser.getId()); + } + if (data.getExpectArriveDate() == null) { + data.setExpectArriveDate(new Date()); + } + if (StringUtil.isBlank(data.getProductCode())) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“商品编号”不能为空"); + } else { + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getCode, data.getProductCode()); + Product product = productService.getOne(queryWrapper); + if (product == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“商品编号”不存在"); + } + data.setProductId(product.getId()); + } + + if (!"是".equals(data.getGift()) && !"否".equals(data.getGift())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“是否赠品”只能填“是”或“否”"); + } + + boolean isGift = "是".equals(data.getGift()); + if (!isGift) { + // 非赠品 + if (data.getPurchasePrice() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价”不能为空"); + } + if (NumberUtil.le(data.getPurchasePrice(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价”必须大于0"); + } + if (!NumberUtil.isNumberPrecision(data.getPurchasePrice(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价”最多允许2位小数"); + } + } else { + // 赠品 + data.setPurchasePrice(BigDecimal.ZERO); + } + if (data.getPurchaseNum() == null) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“采购数量”不能为空"); + } + if (data.getPurchaseNum() <= 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购数量”必须大于0"); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + // 根据仓库、供应商、采购员、预计到货日期 分组 + Map> groupByMap = this.getDatas().stream().collect( + Collectors.groupingBy( + t -> t.getScCode() + "_" + t.getSupplierCode() + "_" + t.getPurchaserCode() + "_" + + DateUtil.toLocalDate(t.getExpectArriveDate()))); + + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + + int index = 0; + for (List value : groupByMap.values()) { + PurchaseOrderImportModel valueObj = value.get(0); + CreatePurchaseOrderVo createPurchaseOrderVo = new CreatePurchaseOrderVo(); + createPurchaseOrderVo.setScId(valueObj.getScId()); + createPurchaseOrderVo.setSupplierId(valueObj.getSupplierId()); + createPurchaseOrderVo.setPurchaserId(valueObj.getPurchaserId()); + createPurchaseOrderVo.setExpectArriveDate( + DateUtil.toLocalDate(valueObj.getExpectArriveDate())); + createPurchaseOrderVo.setDescription(valueObj.getDescription()); + + List products = new ArrayList<>(); + for (PurchaseOrderImportModel data : value) { + PurchaseProductVo purchaseProductVo = new PurchaseProductVo(); + purchaseProductVo.setProductId(data.getProductId()); + purchaseProductVo.setPurchasePrice(data.getPurchasePrice()); + purchaseProductVo.setPurchaseNum(data.getPurchaseNum()); + purchaseProductVo.setDescription(data.getDetailDescription()); + + products.add(purchaseProductVo); + + index++; + this.setSuccessProcessByIndex(index); + } + createPurchaseOrderVo.setProducts(products); + + purchaseOrderService.create(createPurchaseOrderVo); + } + } + + @Override + protected void doComplete() { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportModel.java new file mode 100644 index 0000000..164a91c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderImportModel.java @@ -0,0 +1,103 @@ +package com.lframework.xingyun.sc.excel.purchase; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class PurchaseOrderImportModel implements ExcelModel { + + /** + * 仓库ID + */ + @ExcelIgnore + private String scId; + + /** + * 仓库编号 + */ + @ExcelRequired + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 供应商ID + */ + @ExcelIgnore + private String supplierId; + + /** + * 供应商编号 + */ + @ExcelRequired + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 采购员ID + */ + @ExcelIgnore + private String purchaserId; + + /** + * 采购员编号 + */ + @ExcelProperty("采购员编号") + private String purchaserCode; + + /** + * 预计到货日期 + */ + @ExcelProperty("预计到货日期") + private Date expectArriveDate; + + /** + * 商品ID + */ + @ExcelIgnore + private String productId; + + /** + * 商品编号 + */ + @ExcelRequired + @ExcelProperty("商品编号") + private String productCode; + + /** + * 采购价 + */ + @ExcelRequired + @ExcelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 采购数量 + */ + @ExcelRequired + @ExcelProperty("采购数量") + private Integer purchaseNum; + + /** + * 是否赠品 + */ + @ExcelRequired + @ExcelProperty("是否赠品") + private String gift; + + /** + * 单据明细备注 + */ + @ExcelProperty("单据明细备注") + private String detailDescription; + + /** + * 单据备注 + */ + @ExcelProperty("单据备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportListener.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportListener.java new file mode 100644 index 0000000..88a7341 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportListener.java @@ -0,0 +1,143 @@ +package com.lframework.xingyun.sc.excel.purchase; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PurchaseOrderPayTypeImportListener extends + ExcelImportListener { + + @Override + protected void doInvoke(PurchaseOrderPayTypeImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”不能为空"); + } + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean(PurchaseOrderService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(PurchaseOrder.class) + .eq(PurchaseOrder::getCode, data.getCode()); + PurchaseOrder order = purchaseOrderService.getOne(queryWrapper); + if (order == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”不存在"); + } + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“单据号”的状态为“" + + PurchaseOrderStatus.APPROVE_PASS.getDesc() + "”,不允许导入支付方式"); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean( + OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(order.getId()); + if (CollectionUtil.isNotEmpty(orderPayTypes)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”已关联支付方式,不允许重复导入"); + } + data.setId(order.getId()); + data.setTotalAmount(order.getTotalAmount()); + + if (StringUtil.isBlank(data.getPayTypeCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付方式编号”不能为空"); + } + + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + Wrapper queryPayTypeWrapper = Wrappers.lambdaQuery(PayType.class) + .eq(PayType::getCode, data.getPayTypeCode()); + PayType payType = payTypeService.getOne(queryPayTypeWrapper); + if (payType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付方式编号”不存在"); + } + + data.setPayTypeId(payType.getId()); + + if (data.getPayAmount() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付金额”不能为空"); + } + + if (NumberUtil.le(data.getPayAmount(), BigDecimal.ZERO)) { + // 如果 <= 0 + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付金额”必须大于0"); + } + + if (!NumberUtil.isNumberPrecision(data.getPayAmount(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付金额”最多允许2位小数"); + } + + if (payType.getRecText()) { + if (StringUtil.isBlank(data.getText())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付内容”不能为空"); + } + } else { + data.setText(null); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + // 根据ID 分组 + Map> groupByMap = this.getDatas().stream() + .collect( + Collectors.groupingBy(PurchaseOrderPayTypeImportModel::getId)); + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean( + OrderPayTypeService.class); + + int index = 0; + for (Entry> entry : groupByMap.entrySet()) { + List value = entry.getValue(); + String id = entry.getKey(); + + BigDecimal totalAmount = value.stream().map(PurchaseOrderPayTypeImportModel::getPayAmount) + .reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(totalAmount, value.get(0).getTotalAmount())) { + throw new DefaultClientException( + "单据号:" + value.get(0).getCode() + "所有支付方式的支付金额不等于含税总金额,请检查"); + } + + orderPayTypeService.create(id, value.stream().map(t -> { + OrderPayTypeVo orderPayTypeVo = new OrderPayTypeVo(); + orderPayTypeVo.setId(t.getPayTypeId()); + orderPayTypeVo.setPayAmount(t.getPayAmount()); + orderPayTypeVo.setText(t.getText()); + + return orderPayTypeVo; + }).collect(Collectors.toList())); + + index++; + this.setSuccessProcessByIndex(index); + } + } + + @Override + protected void doComplete() { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportModel.java new file mode 100644 index 0000000..1025beb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/PurchaseOrderPayTypeImportModel.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.excel.purchase; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class PurchaseOrderPayTypeImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 单据号 + */ + @ExcelRequired + @ExcelProperty("单据号") + private String code; + + /** + * 支付方式ID + */ + @ExcelIgnore + private String payTypeId; + + /** + * 支付方式编号 + */ + @ExcelRequired + @ExcelProperty("支付方式编号") + private String payTypeCode; + + /** + * 支付金额 + */ + @ExcelRequired + @ExcelProperty("支付金额") + private BigDecimal payAmount; + + /** + * 支付内容 + */ + @ExcelProperty("支付内容") + private String text; + + /** + * 单据总金额 + */ + @ExcelIgnore + private BigDecimal totalAmount; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetExportModel.java new file mode 100644 index 0000000..b2488d7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetExportModel.java @@ -0,0 +1,199 @@ +package com.lframework.xingyun.sc.excel.purchase.receive; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class ReceiveSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ExcelProperty("采购员") + private String purchaserName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer receiveNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 实际到货日期 + */ + @ExcelProperty("实际到货日期") + @DateTimeFormat(StringPool.DATE_PATTERN) + private Date receiveDate; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 采购订单号 + */ + @ExcelProperty("采购订单号") + private String purchaseOrderCode; + + public ReceiveSheetExportModel() { + + } + + public ReceiveSheetExportModel(ReceiveSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(ReceiveSheet dto) { + + return this; + } + + @Override + protected void afterInit(ReceiveSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto purchaser = null; + if (!StringUtil.isBlank(dto.getPurchaserId())) { + purchaser = userService.findById(dto.getPurchaserId()); + } + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + this.setSupplierCode(supplier.getCode()); + this.setSupplierName(supplier.getName()); + this.setPurchaserName(purchaser == null ? null : purchaser.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setReceiveNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setReceiveDate(DateUtil.toDate(dto.getReceiveDate())); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(dto.getStatus().getDesc()); + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + this.setSettleStatus(dto.getSettleStatus().getDesc()); + this.setDescription(dto.getDescription()); + if (!StringUtil.isBlank(dto.getPurchaseOrderId())) { + PurchaseOrderService purchaseOrderService = ApplicationUtil.getBean( + PurchaseOrderService.class); + PurchaseOrder purchaseOrder = purchaseOrderService.getById(dto.getPurchaseOrderId()); + this.setPurchaseOrderCode(purchaseOrder.getCode()); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportListener.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportListener.java new file mode 100644 index 0000000..256bc98 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportListener.java @@ -0,0 +1,179 @@ +package com.lframework.xingyun.sc.excel.purchase.receive; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.vo.purchase.receive.CreateReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ReceiveProductVo; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ReceiveSheetImportListener extends ExcelImportListener { + + @Override + protected void doInvoke(ReceiveSheetImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getScCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“仓库编号”不能为空"); + } else { + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(StoreCenter.class) + .eq(StoreCenter::getCode, data.getScCode()); + StoreCenter sc = storeCenterService.getOne(queryWrapper); + if (sc == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“仓库编号”不存在"); + } + + data.setScId(sc.getId()); + } + if (StringUtil.isBlank(data.getSupplierCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“供应商编号”不能为空"); + } else { + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Supplier.class) + .eq(Supplier::getCode, data.getSupplierCode()); + Supplier supplier = supplierService.getOne(queryWrapper); + if (supplier == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“供应商编号”不存在"); + } + + data.setSupplierId(supplier.getId()); + } + if (!StringUtil.isBlank(data.getPurchaserCode())) { + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto purchaser = userService.findByCode(data.getPurchaserCode()); + if (purchaser == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购员编号”不存在"); + } + data.setPurchaserId(purchaser.getId()); + } + if (data.getPaymentDate() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“付款日期”不存在"); + } + if (data.getReceiveDate() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“实际到货日期”不存在"); + } + if (StringUtil.isBlank(data.getProductCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“商品编号”不能为空"); + } else { + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(Product.class) + .eq(Product::getCode, data.getProductCode()); + Product product = productService.getOne(queryWrapper); + if (product == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“商品编号”不存在"); + } + data.setProductId(product.getId()); + } + + if (!"是".equals(data.getGift()) && !"否".equals(data.getGift())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“是否赠品”只能填“是”或“否”"); + } + + boolean isGift = "是".equals(data.getGift()); + if (!isGift) { + // 非赠品 + if (data.getPurchasePrice() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价”不能为空"); + } + if (NumberUtil.le(data.getPurchasePrice(), 0)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价”必须大于0"); + } + if (!NumberUtil.isNumberPrecision(data.getPurchasePrice(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“采购价”最多允许2位小数"); + } + } else { + // 赠品 + data.setPurchasePrice(BigDecimal.ZERO); + } + if (data.getReceiveNum() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收货数量”不能为空"); + } + if (data.getReceiveNum() <= 0) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“收货数量”必须大于0"); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + // 根据仓库、供应商、采购员、预计到货日期 分组 + Map> groupByMap = this.getDatas().stream().collect( + Collectors.groupingBy( + t -> t.getScCode() + "_" + t.getSupplierCode() + "_" + t.getPurchaserCode() + "_" + + DateUtil.toLocalDate(t.getPaymentDate()) + "_" + DateUtil.toLocalDate( + t.getReceiveDate()))); + + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + + int index = 0; + for (List value : groupByMap.values()) { + ReceiveSheetImportModel valueObj = value.get(0); + CreateReceiveSheetVo createReceiveSheetVo = new CreateReceiveSheetVo(); + createReceiveSheetVo.setScId(valueObj.getScId()); + createReceiveSheetVo.setSupplierId(valueObj.getSupplierId()); + createReceiveSheetVo.setPurchaserId(valueObj.getPurchaserId()); + createReceiveSheetVo.setPaymentDate(DateUtil.toLocalDate(valueObj.getPaymentDate())); + createReceiveSheetVo.setAllowModifyPaymentDate(Boolean.TRUE); + createReceiveSheetVo.setReceiveDate(DateUtil.toLocalDate(valueObj.getReceiveDate())); + createReceiveSheetVo.setDescription(valueObj.getDescription()); + createReceiveSheetVo.setRequired(Boolean.FALSE); + + List products = new ArrayList<>(); + for (ReceiveSheetImportModel data : value) { + ReceiveProductVo purchaseProductVo = new ReceiveProductVo(); + purchaseProductVo.setProductId(data.getProductId()); + purchaseProductVo.setPurchasePrice(data.getPurchasePrice()); + purchaseProductVo.setReceiveNum(data.getReceiveNum()); + purchaseProductVo.setDescription(data.getDetailDescription()); + + products.add(purchaseProductVo); + + index++; + this.setSuccessProcessByIndex(index); + } + createReceiveSheetVo.setProducts(products); + + receiveSheetService.create(createReceiveSheetVo); + } + } + + @Override + protected void doComplete() { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportModel.java new file mode 100644 index 0000000..0da2609 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetImportModel.java @@ -0,0 +1,111 @@ +package com.lframework.xingyun.sc.excel.purchase.receive; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class ReceiveSheetImportModel implements ExcelModel { + + /** + * 仓库ID + */ + @ExcelIgnore + private String scId; + + /** + * 仓库编号 + */ + @ExcelRequired + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 供应商ID + */ + @ExcelIgnore + private String supplierId; + + /** + * 供应商编号 + */ + @ExcelRequired + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 采购员ID + */ + @ExcelIgnore + private String purchaserId; + + /** + * 采购员编号 + */ + @ExcelProperty("采购员编号") + private String purchaserCode; + + /** + * 付款日期 + */ + @ExcelRequired + @ExcelProperty("付款日期") + private Date paymentDate; + + /** + * 实际到货日期 + */ + @ExcelRequired + @ExcelProperty("实际到货日期") + private Date receiveDate; + + /** + * 商品ID + */ + @ExcelIgnore + private String productId; + + /** + * 商品编号 + */ + @ExcelRequired + @ExcelProperty("商品编号") + private String productCode; + + /** + * 采购价 + */ + @ExcelRequired + @ExcelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 收货数量 + */ + @ExcelRequired + @ExcelProperty("收货数量") + private Integer receiveNum; + + /** + * 是否赠品 + */ + @ExcelRequired + @ExcelProperty("是否赠品") + private String gift; + + /** + * 单据明细备注 + */ + @ExcelProperty("单据明细备注") + private String detailDescription; + + /** + * 单据备注 + */ + @ExcelProperty("单据备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportListener.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportListener.java new file mode 100644 index 0000000..8535b1e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportListener.java @@ -0,0 +1,133 @@ +package com.lframework.xingyun.sc.excel.purchase.receive; + +import com.alibaba.excel.context.AnalysisContext; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelImportListener; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ReceiveSheetPayTypeImportListener extends + ExcelImportListener { + + @Override + protected void doInvoke(ReceiveSheetPayTypeImportModel data, AnalysisContext context) { + if (StringUtil.isBlank(data.getCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”不能为空"); + } + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery(ReceiveSheet.class) + .eq(ReceiveSheet::getCode, data.getCode()); + ReceiveSheet order = receiveSheetService.getOne(queryWrapper); + if (order == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“单据号”不存在"); + } + if (order.getStatus() == ReceiveSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("第" + context.readRowHolder().getRowIndex() + "行“单据号”的状态为“" + + ReceiveSheetStatus.APPROVE_PASS.getDesc() + "”,不允许导入支付方式"); + } + data.setId(order.getId()); + data.setTotalAmount(order.getTotalAmount()); + + if (StringUtil.isBlank(data.getPayTypeCode())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付方式编号”不能为空"); + } + + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + Wrapper queryPayTypeWrapper = Wrappers.lambdaQuery(PayType.class) + .eq(PayType::getCode, data.getPayTypeCode()); + PayType payType = payTypeService.getOne(queryPayTypeWrapper); + if (payType == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付方式编号”不存在"); + } + + data.setPayTypeId(payType.getId()); + + if (data.getPayAmount() == null) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付金额”不能为空"); + } + + if (NumberUtil.le(data.getPayAmount(), BigDecimal.ZERO)) { + // 如果 <= 0 + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付金额”必须大于0"); + } + + if (!NumberUtil.isNumberPrecision(data.getPayAmount(), 2)) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付金额”最多允许2位小数"); + } + + if (payType.getRecText()) { + if (StringUtil.isBlank(data.getText())) { + throw new DefaultClientException( + "第" + context.readRowHolder().getRowIndex() + "行“支付内容”不能为空"); + } + } else { + data.setText(null); + } + } + + @Override + protected void afterAllAnalysed(AnalysisContext context) { + + // 根据ID 分组 + Map> groupByMap = this.getDatas().stream() + .collect( + Collectors.groupingBy(ReceiveSheetPayTypeImportModel::getId)); + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean( + OrderPayTypeService.class); + + int index = 0; + for (Entry> entry : groupByMap.entrySet()) { + List value = entry.getValue(); + String id = entry.getKey(); + + BigDecimal totalAmount = value.stream().map(ReceiveSheetPayTypeImportModel::getPayAmount) + .reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(totalAmount, value.get(0).getTotalAmount())) { + throw new DefaultClientException( + "单据号:" + value.get(0).getCode() + "所有支付方式的支付金额不等于含税总金额,请检查"); + } + + orderPayTypeService.create(id, value.stream().map(t -> { + OrderPayTypeVo orderPayTypeVo = new OrderPayTypeVo(); + orderPayTypeVo.setId(t.getPayTypeId()); + orderPayTypeVo.setPayAmount(t.getPayAmount()); + orderPayTypeVo.setText(t.getText()); + + return orderPayTypeVo; + }).collect(Collectors.toList())); + + index++; + this.setSuccessProcessByIndex(index); + } + } + + @Override + protected void doComplete() { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportModel.java new file mode 100644 index 0000000..12b22aa --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/receive/ReceiveSheetPayTypeImportModel.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.excel.purchase.receive; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.annotations.excel.ExcelRequired; +import com.lframework.starter.web.components.excel.ExcelModel; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class ReceiveSheetPayTypeImportModel implements ExcelModel { + + /** + * ID + */ + @ExcelIgnore + private String id; + + /** + * 单据号 + */ + @ExcelRequired + @ExcelProperty("单据号") + private String code; + + /** + * 支付方式ID + */ + @ExcelIgnore + private String payTypeId; + + /** + * 支付方式编号 + */ + @ExcelRequired + @ExcelProperty("支付方式编号") + private String payTypeCode; + + /** + * 支付金额 + */ + @ExcelRequired + @ExcelProperty("支付金额") + private BigDecimal payAmount; + + /** + * 支付内容 + */ + @ExcelProperty("支付内容") + private String text; + + /** + * 单据总金额 + */ + @ExcelIgnore + private BigDecimal totalAmount; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/returned/PurchaseReturnExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/returned/PurchaseReturnExportModel.java new file mode 100644 index 0000000..e7ce3bf --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/purchase/returned/PurchaseReturnExportModel.java @@ -0,0 +1,190 @@ +package com.lframework.xingyun.sc.excel.purchase.returned; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class PurchaseReturnExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 供应商编号 + */ + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 采购员姓名 + */ + @ExcelProperty("采购员") + private String purchaserName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer receiveNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 采购收货单号 + */ + @ExcelProperty("采购收货单号") + private String receiveSheetCode; + + public PurchaseReturnExportModel() { + + } + + public PurchaseReturnExportModel(PurchaseReturn dto) { + + super(dto); + } + + @Override + public BaseBo convert(PurchaseReturn dto) { + + return this; + } + + @Override + protected void afterInit(PurchaseReturn dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto purchaser = null; + if (!StringUtil.isBlank(dto.getPurchaserId())) { + purchaser = userService.findById(dto.getPurchaserId()); + } + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + this.setSupplierCode(supplier.getCode()); + this.setSupplierName(supplier.getName()); + this.setPurchaserName(purchaser == null ? null : purchaser.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setReceiveNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(dto.getStatus().getDesc()); + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + this.setSettleStatus(dto.getSettleStatus().getDesc()); + this.setDescription(dto.getDescription()); + if (!StringUtil.isBlank(dto.getReceiveSheetId())) { + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + ReceiveSheet receiveSheet = receiveSheetService.getById(dto.getReceiveSheetId()); + this.setReceiveSheetCode(receiveSheet.getCode()); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/out/RetailOutSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/out/RetailOutSheetExportModel.java new file mode 100644 index 0000000..65fdd38 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/out/RetailOutSheetExportModel.java @@ -0,0 +1,202 @@ +package com.lframework.xingyun.sc.excel.retail.out; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class RetailOutSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ExcelProperty("会员编号") + private String memberCode; + + /** + * 客户名称 + */ + @ExcelProperty("会员名称") + private String memberName; + + /** + * 销售员姓名 + */ + @ExcelProperty("销售员") + private String salerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ExcelProperty("支付方式") + private String payTypeStr; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer receiveNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public RetailOutSheetExportModel() { + + } + + public RetailOutSheetExportModel(RetailOutSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailOutSheet dto) { + + return this; + } + + @Override + protected void afterInit(RetailOutSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = null; + if (!StringUtil.isBlank(dto.getSalerId())) { + saler = userService.findById(dto.getSalerId()); + } + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + this.setMemberCode(member.getCode()); + this.setMemberName(member.getName()); + this.setSalerName(saler == null ? null : saler.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setReceiveNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(dto.getStatus().getDesc()); + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + this.setSettleStatus(dto.getSettleStatus().getDesc()); + this.setDescription(dto.getDescription()); + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + + if (CollectionUtil.isNotEmpty(orderPayTypes)) { + this.payTypeStr = orderPayTypes.stream().map(orderPayType -> { + PayType payType = payTypeService.findById(orderPayType.getPayTypeId()); + return StringUtil.format("{}:{}元", payType.getName(), orderPayType.getPayAmount()); + }).collect(Collectors.joining(";")); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/returned/RetailReturnExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/returned/RetailReturnExportModel.java new file mode 100644 index 0000000..c7cac04 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/retail/returned/RetailReturnExportModel.java @@ -0,0 +1,217 @@ +package com.lframework.xingyun.sc.excel.retail.returned; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class RetailReturnExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 会员编号 + */ + @ExcelProperty("会员编号") + private String memberCode; + + /** + * 会员名称 + */ + @ExcelProperty("会员名称") + private String memberName; + + /** + * 销售员姓名 + */ + @ExcelProperty("销售员") + private String salerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 支付方式 + */ + @ExcelProperty("支付方式") + private String payTypeStr; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 零售出库单号 + */ + @ExcelProperty("零售出库单号") + private String outSheetCode; + + public RetailReturnExportModel() { + + } + + public RetailReturnExportModel(RetailReturn dto) { + + super(dto); + } + + @Override + public BaseBo convert(RetailReturn dto) { + + return this; + } + + @Override + protected void afterInit(RetailReturn dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + MemberService memberService = ApplicationUtil.getBean(MemberService.class); + Member member = memberService.findById(dto.getMemberId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = null; + if (!StringUtil.isBlank(dto.getSalerId())) { + saler = userService.findById(dto.getSalerId()); + } + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + this.setMemberCode(member.getCode()); + this.setMemberName(member.getName()); + this.setSalerName(saler == null ? null : saler.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setTotalNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(dto.getStatus().getDesc()); + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + this.setSettleStatus(dto.getSettleStatus().getDesc()); + this.setDescription(dto.getDescription()); + + if (!StringUtil.isBlank(dto.getOutSheetId())) { + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + RetailOutSheet retailOutSheet = retailOutSheetService.getById(dto.getOutSheetId()); + this.setOutSheetCode(retailOutSheet.getCode()); + } + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + + if (CollectionUtil.isNotEmpty(orderPayTypes)) { + this.payTypeStr = orderPayTypes.stream().map(orderPayType -> { + PayType payType = payTypeService.findById(orderPayType.getPayTypeId()); + return StringUtil.format("{}:{}元", payType.getName(), orderPayType.getPayAmount()); + }).collect(Collectors.joining(";")); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/SaleOrderExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/SaleOrderExportModel.java new file mode 100644 index 0000000..bdfd209 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/SaleOrderExportModel.java @@ -0,0 +1,196 @@ +package com.lframework.xingyun.sc.excel.sale; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.PayType; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.paytype.PayTypeService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class SaleOrderExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scOde; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ExcelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ExcelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ExcelProperty("销售员") + private String salerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 约定支付 + */ + @ExcelProperty("约定支付") + private String payTypeStr; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public SaleOrderExportModel() { + + } + + public SaleOrderExportModel(SaleOrder dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOrder dto) { + + return this; + } + + @Override + protected void afterInit(SaleOrder dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = userService.findById(dto.getSalerId()); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScOde(sc.getCode()); + this.setScName(sc.getName()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + if (saler != null) { + this.setSalerName(saler.getName()); + } + this.setTotalNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setTotalAmount(dto.getTotalAmount()); + this.setDescription(dto.getDescription()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + + this.setStatus(dto.getStatus().getDesc()); + + OrderPayTypeService orderPayTypeService = ApplicationUtil.getBean(OrderPayTypeService.class); + List orderPayTypes = orderPayTypeService.findByOrderId(dto.getId()); + + PayTypeService payTypeService = ApplicationUtil.getBean(PayTypeService.class); + + if (CollectionUtil.isNotEmpty(orderPayTypes)) { + this.payTypeStr = orderPayTypes.stream().map(orderPayType -> { + PayType payType = payTypeService.findById(orderPayType.getPayTypeId()); + return StringUtil.format("{}:{}元", payType.getName(), orderPayType.getPayAmount()); + }).collect(Collectors.joining(";")); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/out/SaleOutSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/out/SaleOutSheetExportModel.java new file mode 100644 index 0000000..ade9d2e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/out/SaleOutSheetExportModel.java @@ -0,0 +1,190 @@ +package com.lframework.xingyun.sc.excel.sale.out; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class SaleOutSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ExcelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ExcelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ExcelProperty("销售员") + private String salerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer receiveNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 采购订单号 + */ + @ExcelProperty("销售订单号") + private String purchaseOrderCode; + + public SaleOutSheetExportModel() { + + } + + public SaleOutSheetExportModel(SaleOutSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleOutSheet dto) { + + return this; + } + + @Override + protected void afterInit(SaleOutSheet dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = null; + if (!StringUtil.isBlank(dto.getSalerId())) { + saler = userService.findById(dto.getSalerId()); + } + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + this.setSalerName(saler == null ? null : saler.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setReceiveNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(dto.getStatus().getDesc()); + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + this.setSettleStatus(dto.getSettleStatus().getDesc()); + this.setDescription(dto.getDescription()); + if (!StringUtil.isBlank(dto.getSaleOrderId())) { + SaleOrderService saleOrderService = ApplicationUtil.getBean(SaleOrderService.class); + SaleOrder saleOrder = saleOrderService.getById(dto.getSaleOrderId()); + this.setPurchaseOrderCode(saleOrder.getCode()); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/returned/SaleReturnExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/returned/SaleReturnExportModel.java new file mode 100644 index 0000000..438a2a7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/sale/returned/SaleReturnExportModel.java @@ -0,0 +1,190 @@ +package com.lframework.xingyun.sc.excel.sale.returned; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class SaleReturnExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 客户编号 + */ + @ExcelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ExcelProperty("客户名称") + private String customerName; + + /** + * 销售员姓名 + */ + @ExcelProperty("销售员") + private String salerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 商品数量 + */ + @ExcelProperty("商品数量") + private Integer totalNum; + + /** + * 赠品数量 + */ + @ExcelProperty("赠品数量") + private Integer giftNum; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 销售出库单号 + */ + @ExcelProperty("销售出库单号") + private String outSheetCode; + + public SaleReturnExportModel() { + + } + + public SaleReturnExportModel(SaleReturn dto) { + + super(dto); + } + + @Override + public BaseBo convert(SaleReturn dto) { + + return this; + } + + @Override + protected void afterInit(SaleReturn dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto saler = null; + if (!StringUtil.isBlank(dto.getSalerId())) { + saler = userService.findById(dto.getSalerId()); + } + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + this.setSalerName(saler == null ? null : saler.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setTotalNum(dto.getTotalNum()); + this.setGiftNum(dto.getTotalGiftNum()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(dto.getStatus().getDesc()); + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + this.setSettleStatus(dto.getSettleStatus().getDesc()); + this.setDescription(dto.getDescription()); + if (!StringUtil.isBlank(dto.getOutSheetId())) { + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + SaleOutSheet saleOutSheet = saleOutSheetService.getById(dto.getOutSheetId()); + this.setOutSheetCode(saleOutSheet.getCode()); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockExportModel.java new file mode 100644 index 0000000..08dd55c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockExportModel.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.sc.excel.stock; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.ProductStock; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class ProductStockExportModel extends BaseBo implements ExcelModel { + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 商品编号 + */ + @ExcelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ExcelProperty("商品名称") + private String productName; + + /** + * 商品类目 + */ + @ExcelProperty("商品类目") + private String categoryName; + + /** + * 商品品牌 + */ + @ExcelProperty("商品品牌") + private String brandName; + + /** + * 库存数量 + */ + @ExcelProperty("库存数量") + private Integer stockNum; + + /** + * 含税价格 + */ + @ExcelProperty("含税价格") + private BigDecimal taxPrice; + + /** + * 含税金额 + */ + @ExcelProperty("含税金额") + private BigDecimal taxAmount; + + public ProductStockExportModel() { + + } + + public ProductStockExportModel(ProductStock dto) { + + super(dto); + } + + @Override + public BaseBo convert(ProductStock dto) { + + return this; + } + + @Override + protected void afterInit(ProductStock dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + + this.setStockNum(dto.getStockNum()); + this.setTaxPrice(NumberUtil.getNumber(dto.getTaxPrice(), 2)); + this.setTaxAmount(NumberUtil.getNumber(dto.getTaxAmount(), 2)); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockLogExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockLogExportModel.java new file mode 100644 index 0000000..d1843c8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/ProductStockLogExportModel.java @@ -0,0 +1,172 @@ +package com.lframework.xingyun.sc.excel.stock; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.ProductStockLog; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class ProductStockLogExportModel extends BaseBo implements ExcelModel { + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 商品编号 + */ + @ExcelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ExcelProperty("商品名称") + private String productName; + + /** + * 商品类目 + */ + @ExcelProperty("商品类目") + private String categoryName; + + /** + * 商品品牌 + */ + @ExcelProperty("商品品牌") + private String brandName; + + /** + * 原库存数量 + */ + @ExcelProperty("变动前库存数量") + private Integer oriStockNum; + + /** + * 现库存数量 + */ + @ExcelProperty("变动后库存数量") + private Integer curStockNum; + + /** + * 库存数量 + */ + @ExcelProperty("变动库存数量") + private Integer stockNum; + + /** + * 原含税成本价 + */ + @ExcelProperty("变动前含税成本价") + private BigDecimal oriTaxPrice; + + /** + * 现含税成本价 + */ + @ExcelProperty("变动后含税成本价") + private BigDecimal curTaxPrice; + + /** + * 含税金额 + */ + @ExcelProperty("变动含税金额") + private BigDecimal taxAmount; + + /** + * 创建时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 创建人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ExcelProperty("业务类型") + private String bizType; + + public ProductStockLogExportModel() { + + } + + public ProductStockLogExportModel(ProductStockLog dto) { + + super(dto); + } + + @Override + public BaseBo convert(ProductStockLog dto) { + + return this; + } + + @Override + protected void afterInit(ProductStockLog dto) { + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.setScCode(sc.getCode()); + this.setScName(sc.getName()); + + ProductService productService = ApplicationUtil.getBean(ProductService.class); + Product product = productService.findById(dto.getProductId()); + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + ProductCategory productCategory = productCategoryService.findById(product.getCategoryId()); + + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + ProductBrand productBrand = productBrandService.findById(product.getBrandId()); + + this.productCode = product.getCode(); + this.productName = product.getName(); + this.categoryName = productCategory.getName(); + this.brandName = productBrand.getName(); + + this.setOriStockNum(dto.getOriStockNum()); + this.setCurStockNum(dto.getCurStockNum()); + this.setStockNum(dto.getStockNum()); + this.setOriTaxPrice(NumberUtil.getNumber(dto.getOriTaxPrice(), 2)); + this.setCurTaxPrice(NumberUtil.getNumber(dto.getCurTaxPrice(), 2)); + this.setTaxAmount(NumberUtil.getNumber(dto.getTaxAmount(), 2)); + + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setBizCode(dto.getBizCode()); + this.setBizType(dto.getBizType().getDesc()); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockAdjustSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockAdjustSheetExportModel.java new file mode 100644 index 0000000..ad6dbd5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockAdjustSheetExportModel.java @@ -0,0 +1,128 @@ +package com.lframework.xingyun.sc.excel.stock.adjust; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.StockAdjustSheet; +import com.lframework.xingyun.sc.entity.StockAdjustSheetDetail; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustSheetDetailService; +import com.lframework.xingyun.template.core.service.UserService; +import java.util.Date; +import java.util.List; +import lombok.Data; + +@Data +public class StockAdjustSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 调整品种数 + */ + @ExcelProperty("调整品种数") + private Integer productNum; + + /** + * 库存调整数量 + */ + @ExcelProperty("库存调整数量") + private Integer diffStockNum; + + /** + * 修改时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("操作时间") + private Date updateTime; + + /** + * 修改人 + */ + @ExcelProperty("操作人") + private String updateBy; + + /** + * 状态 + */ + @ExcelProperty("状态") + private String status; + + /** + * 审核时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("审核时间") + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public StockAdjustSheetExportModel(StockAdjustSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(StockAdjustSheet dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(StockAdjustSheet dto) { + + this.status = dto.getStatus().getDesc(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + StockAdjustSheetDetailService stockAdjustSheetDetailService = ApplicationUtil.getBean( + StockAdjustSheetDetailService.class); + Wrapper queryWrapper = Wrappers.lambdaQuery( + StockAdjustSheetDetail.class).eq(StockAdjustSheetDetail::getSheetId, dto.getId()) + .orderByAsc(StockAdjustSheetDetail::getOrderNo); + List details = stockAdjustSheetDetailService.list(queryWrapper); + this.productNum = details.size(); + this.diffStockNum = details.stream().mapToInt(StockAdjustSheetDetail::getStockNum).sum(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockCostAdjustSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockCostAdjustSheetExportModel.java new file mode 100644 index 0000000..0dd8763 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/adjust/StockCostAdjustSheetExportModel.java @@ -0,0 +1,115 @@ +package com.lframework.xingyun.sc.excel.stock.adjust; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheet; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class StockCostAdjustSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 单号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 调价品种数 + */ + @ExcelProperty("调价品种数") + private Integer productNum; + + /** + * 库存调价差额 + */ + @ExcelProperty("库存调价差额") + private BigDecimal diffAmount; + + /** + * 修改时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("操作时间") + private Date updateTime; + + /** + * 修改人 + */ + @ExcelProperty("操作人") + private String updateBy; + + /** + * 状态 + */ + @ExcelProperty("状态") + private String status; + + /** + * 审核时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("审核时间") + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public StockCostAdjustSheetExportModel(StockCostAdjustSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(StockCostAdjustSheet dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(StockCostAdjustSheet dto) { + + this.status = dto.getStatus().getDesc(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/plan/TakeStockPlanExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/plan/TakeStockPlanExportModel.java new file mode 100644 index 0000000..476cbf9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/plan/TakeStockPlanExportModel.java @@ -0,0 +1,146 @@ +package com.lframework.xingyun.sc.excel.stock.take.plan; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.ProductBrand; +import com.lframework.xingyun.basedata.entity.ProductCategory; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.product.ProductBrandService; +import com.lframework.xingyun.basedata.service.product.ProductCategoryService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import java.util.Date; +import lombok.Data; + +@Data +public class TakeStockPlanExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 盘点类别 + */ + @ExcelProperty("盘点类别") + private String takeType; + + /** + * 业务名称 + */ + @ExcelProperty("业务名称") + private String bizName; + + /** + * 盘点状态 + */ + @ExcelProperty("盘点状态") + private String takeStatus; + + /** + * 创建时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("创建时间") + private Date createTime; + + /** + * 创建人 + */ + @ExcelProperty("创建人") + private String createBy; + + /** + * 操作时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("操作时间") + private Date updateTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String updateBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public TakeStockPlanExportModel(TakeStockPlan dto) { + + super(dto); + } + + @Override + public BaseBo convert(TakeStockPlan dto) { + + return super.convert(dto, TakeStockPlanExportModel::getTakeStatus, TakeStockPlanExportModel::getTakeType); + } + + @Override + protected void afterInit(TakeStockPlan dto) { + + this.takeType = dto.getTakeType().getDesc(); + this.takeStatus = dto.getTakeStatus().getDesc(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + String bizId = dto.getBizId(); + if (dto.getTakeType() == TakeStockPlanType.CATEGORY) { + ProductCategoryService productCategoryService = ApplicationUtil.getBean( + ProductCategoryService.class); + String[] categoryIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String categoryId : categoryIds) { + ProductCategory productCategory = productCategoryService.findById(categoryId); + builder.append(productCategory.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } else if (dto.getTakeType() == TakeStockPlanType.BRAND) { + ProductBrandService productBrandService = ApplicationUtil.getBean(ProductBrandService.class); + String[] brandIds = bizId.split(","); + StringBuilder builder = new StringBuilder(); + for (String brandId : brandIds) { + ProductBrand productBrand = productBrandService.findById(brandId); + builder.append(productBrand.getName()).append(StringPool.STR_SPLIT_CN); + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + } + + this.bizName = builder.toString(); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/pre/PreTakeStockSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/pre/PreTakeStockSheetExportModel.java new file mode 100644 index 0000000..1960bac --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/pre/PreTakeStockSheetExportModel.java @@ -0,0 +1,88 @@ +package com.lframework.xingyun.sc.excel.stock.take.pre; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.template.core.service.UserService; +import java.util.Date; +import lombok.Data; + +@Data +public class PreTakeStockSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 盘点状态 + */ + @ExcelProperty("盘点状态") + private String takeStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 操作时间 + */ + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + @ExcelProperty("操作时间") + private Date updateTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String updateBy; + + public PreTakeStockSheetExportModel(PreTakeStockSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(PreTakeStockSheet dto) { + + return super.convert(dto, PreTakeStockSheetExportModel::getTakeStatus, + PreTakeStockSheetExportModel::getUpdateTime); + } + + @Override + protected void afterInit(PreTakeStockSheet dto) { + + this.takeStatus = dto.getTakeStatus().getDesc(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + this.updateTime = DateUtil.toDate(dto.getUpdateTime()); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/sheet/TakeStockSheetExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/sheet/TakeStockSheetExportModel.java new file mode 100644 index 0000000..7c29acb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/take/sheet/TakeStockSheetExportModel.java @@ -0,0 +1,136 @@ +package com.lframework.xingyun.sc.excel.stock.take.sheet; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.entity.TakeStockSheet; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.template.core.service.UserService; +import java.util.Date; +import lombok.Data; + +@Data +public class TakeStockSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 盘点任务号 + */ + @ExcelProperty("关联盘点任务") + private String planCode; + + /** + * 盘点任务-盘点状态 + */ + @ExcelProperty("盘点状态") + private String takeStatus; + + /** + * 仓库编号 + */ + @ExcelProperty("仓库编号") + private String scCode; + + /** + * 仓库名称 + */ + @ExcelProperty("仓库名称") + private String scName; + + /** + * 盘点任务-盘点类别 + */ + @ExcelProperty("盘点类别") + private String takeType; + + /** + * 状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 修改时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date updateTime; + + /** + * 修改人 + */ + @ExcelProperty("操作人") + private String updateBy; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public TakeStockSheetExportModel(TakeStockSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(TakeStockSheet dto) { + + return super.convert(dto, TakeStockSheetExportModel::getTakeStatus, TakeStockSheetExportModel::getStatus, + TakeStockSheetExportModel::getUpdateTime, TakeStockSheetExportModel::getApproveTime); + } + + @Override + protected void afterInit(TakeStockSheet dto) { + + this.status = dto.getStatus().getDesc(); + + TakeStockPlanService takeStockPlanService = ApplicationUtil.getBean(TakeStockPlanService.class); + TakeStockPlan takeStockPlan = takeStockPlanService.getById(dto.getPlanId()); + + this.planCode = takeStockPlan.getCode(); + this.takeStatus = takeStockPlan.getTakeStatus().getDesc(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sc = storeCenterService.findById(dto.getScId()); + this.scCode = sc.getCode(); + this.scName = sc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.takeType = takeStockPlan.getTakeType().getDesc(); + + this.updateTime = DateUtil.toDate(dto.getUpdateTime()); + this.approveTime = DateUtil.toDate(dto.getApproveTime()); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/transfer/ScTransferOrderExportModel.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/transfer/ScTransferOrderExportModel.java new file mode 100644 index 0000000..aade735 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/excel/stock/transfer/ScTransferOrderExportModel.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.sc.excel.stock.transfer; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.sc.entity.ScTransferOrder; +import com.lframework.xingyun.sc.enums.ScTransferOrderStatus; +import com.lframework.xingyun.template.core.service.UserService; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class ScTransferOrderExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 转出仓库编号 + */ + @ExcelProperty("转出仓库编号") + private String sourceScCode; + + /** + * 转出仓库名称 + */ + @ExcelProperty("转出仓库名称") + private String sourceScName; + + /** + * 转入仓库编号 + */ + @ExcelProperty("转入仓库编号") + private String targetScCode; + + /** + * 转入仓库名称 + */ + @ExcelProperty("转入仓库名称") + private String targetScName; + + /** + * 调拨数量 + */ + @ExcelProperty("调拨数量") + private Integer totalNum; + + /** + * 调拨成本金额 + */ + @ExcelProperty("调拨成本金额") + private BigDecimal totalAmount; + + /** + * 状态 + */ + @ExcelProperty("状态") + private String status; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + /** + * 修改人 + */ + @ExcelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ExcelProperty("修改时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date updateTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + public ScTransferOrderExportModel(ScTransferOrder dto) { + + super(dto); + } + + @Override + public BaseBo convert(ScTransferOrder dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(ScTransferOrder dto) { + + this.status = dto.getStatus().getDesc(); + + StoreCenterService storeCenterService = ApplicationUtil.getBean(StoreCenterService.class); + StoreCenter sourceSc = storeCenterService.findById(dto.getSourceScId()); + this.sourceScCode = sourceSc.getCode(); + this.sourceScName = sourceSc.getName(); + + StoreCenter targetSc = storeCenterService.findById(dto.getTargetScId()); + this.targetScCode = targetSc.getCode(); + this.targetScName = targetSc.getName(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + if (dto.getStatus() != ScTransferOrderStatus.APPROVE_PASS + && dto.getStatus() != ScTransferOrderStatus.PART_RECEIVED + && dto.getStatus() != ScTransferOrderStatus.RECEIVED) { + this.totalAmount = null; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/filter/RequestLoggingFilter.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/filter/RequestLoggingFilter.java new file mode 100644 index 0000000..741c86b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/filter/RequestLoggingFilter.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.sc.filter; + +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.servlet.annotation.WebFilter; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.ServletException; +import java.io.IOException; + +@WebFilter(urlPatterns = "/*") +public class RequestLoggingFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // 初始化代码(如果需要) + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + + // 获取请求的协议 + String scheme = httpRequest.getScheme(); + + // 获取请求的URL + String requestURI = httpRequest.getRequestURI(); + + // 获取请求的方法 + String method = httpRequest.getMethod(); + + // 打印信息 + System.out.println("Scheme: " + scheme); + System.out.println("Request URI: " + requestURI); + System.out.println("Method: " + method); + + // 继续执行过滤链 + chain.doFilter(request, response); + } + + @Override + public void destroy() { + // 清理代码(如果需要) + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetDetailServiceImpl.java new file mode 100644 index 0000000..04807f9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetDetailServiceImpl.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.sc.impl.logistics; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.LogisticsSheetDetail; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.mappers.LogisticsSheetDetailMapper; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class LogisticsSheetDetailServiceImpl extends + BaseMpServiceImpl implements + LogisticsSheetDetailService { + + @Override + public LogisticsSheetDetail getByBizId(String bizId, LogisticsSheetDetailBizType bizType) { + Wrapper queryWrapper = Wrappers.lambdaQuery(LogisticsSheetDetail.class) + .eq(LogisticsSheetDetail::getBizId, bizId).eq(LogisticsSheetDetail::getBizType, bizType); + return this.getOne(queryWrapper); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetServiceImpl.java new file mode 100644 index 0000000..f4e47a3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/logistics/LogisticsSheetServiceImpl.java @@ -0,0 +1,278 @@ +package com.lframework.xingyun.sc.impl.logistics; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetBizOrderDto; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetFullDto; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.sc.entity.LogisticsSheetDetail; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.enums.LogisticsSheetStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.LogisticsSheetMapper; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetDetailService; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetService; +import com.lframework.xingyun.sc.vo.logistics.CreateLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.DeliveryLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.LogisticsSheetSelectorVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetBizOrderVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.UpdateLogisticsSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class LogisticsSheetServiceImpl extends + BaseMpServiceImpl implements LogisticsSheetService { + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private LogisticsSheetDetailService logisticsSheetDetailService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryLogisticsSheetVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryLogisticsSheetVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + LogisticsSheetSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public LogisticsSheetFullDto getDetail(String id) { + LogisticsSheetFullDto sheet = getBaseMapper().getDetail(id); + if (sheet == null) { + throw new InputErrorException("物流单不存在!"); + } + + return sheet; + } + + @Override + public PageResult queryBizOrder(Integer pageIndex, Integer pageSize, + QueryLogisticsSheetBizOrderVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryBizOrder(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = ScOpLogType.LOGISTICS, name = "创建物流单,单号:{}", params = "#code") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateLogisticsSheetVo vo) { + LogisticsSheet sheet = new LogisticsSheet(); + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.LOGISTICS_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(LogisticsSheetStatus.CREATED); + + getBaseMapper().insert(sheet); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + return sheet.getId(); + } + + @OpLog(type = ScOpLogType.LOGISTICS, name = "修改物流单,单号:{}", params = "#code") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateLogisticsSheetVo vo) { + LogisticsSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("物流单不存在!"); + } + + if (sheet.getStatus() != LogisticsSheetStatus.CREATED) { + throw new DefaultClientException("物流单已发货,无法修改!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + LogisticsSheetDetail.class).eq(LogisticsSheetDetail::getSheetId, sheet.getId()); + logisticsSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(LogisticsSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(LogisticsSheetStatus.CREATED); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(LogisticsSheet.class) + .eq(LogisticsSheet::getId, sheet.getId()).in(LogisticsSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("物流单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.LOGISTICS, name = "物流单发货,单号:{}", params = "#code") + @Transactional(rollbackFor = Exception.class) + @Override + public void delivery(DeliveryLogisticsSheetVo vo) { + + LogisticsSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("物流单不存在!"); + } + + if (sheet.getStatus() != LogisticsSheetStatus.CREATED) { + throw new DefaultClientException("物流单已发货,无法重复发货!"); + } + + List statusList = new ArrayList<>(); + statusList.add(LogisticsSheetStatus.CREATED); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(LogisticsSheet.class) + .set(LogisticsSheet::getDeliveryBy, SecurityUtil.getCurrentUser().getId()) + .set(LogisticsSheet::getDeliveryTime, LocalDateTime.now()) + .set(StringUtil.isNotBlank(vo.getLogisticsNo()), LogisticsSheet::getLogisticsNo, + vo.getLogisticsNo()) + .set(vo.getTotalAmount() != null, LogisticsSheet::getTotalAmount, vo.getTotalAmount()) + .set(LogisticsSheet::getStatus, LogisticsSheetStatus.DELIVERY) + .eq(LogisticsSheet::getId, sheet.getId()).in(LogisticsSheet::getStatus, statusList); + if (getBaseMapper().update(updateOrderWrapper) != 1) { + throw new DefaultClientException("物流单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.LOGISTICS, name = "删除物流单,单号:{}", params = "#code") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + LogisticsSheet order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("物流单不存在!"); + } + + if (order.getStatus() != LogisticsSheetStatus.CREATED) { + throw new DefaultClientException("已发货的物流单不允许执行删除操作!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + LogisticsSheetDetail.class).eq(LogisticsSheetDetail::getSheetId, order.getId()); + logisticsSheetDetailService.remove(deleteDetailWrapper); + + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", order.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + LogisticsSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个物流单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + private void create(LogisticsSheet sheet, CreateLogisticsSheetVo vo) { + sheet.setLogisticsNo(vo.getLogisticsNo()); + sheet.setLogisticsCompanyId(vo.getLogisticsCompanyId()); + sheet.setSenderName(vo.getSenderName()); + sheet.setSenderTelephone(vo.getSenderTelephone()); + sheet.setSenderProvinceId(vo.getSenderProvinceId()); + sheet.setSenderCityId(vo.getSenderCityId()); + sheet.setSenderDistrictId(vo.getSenderDistrictId()); + sheet.setSenderAddress(vo.getSenderAddress()); + sheet.setReceiverName(vo.getReceiverName()); + sheet.setReceiverTelephone(vo.getReceiverTelephone()); + sheet.setReceiverProvinceId(vo.getReceiverProvinceId()); + sheet.setReceiverCityId(vo.getReceiverCityId()); + sheet.setReceiverDistrictId(vo.getReceiverDistrictId()); + sheet.setReceiverAddress(vo.getReceiverAddress()); + sheet.setTotalWeight(vo.getTotalWeight()); + sheet.setTotalVolume(vo.getTotalVolume()); + sheet.setTotalAmount(vo.getTotalAmount()); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + List details = vo.getBizOrders().stream().map(t -> { + LogisticsSheetDetail detail = new LogisticsSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setBizId(t.getBizId()); + detail.setBizType(EnumUtil.getByCode(LogisticsSheetDetailBizType.class, t.getBizType())); + + return detail; + }).collect(Collectors.toList()); + + logisticsSheetDetailService.saveBatch(details); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/paytype/OrderPayTypeServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/paytype/OrderPayTypeServiceImpl.java new file mode 100644 index 0000000..5f3289c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/paytype/OrderPayTypeServiceImpl.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.sc.impl.paytype; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.mappers.OrderPayTypeMapper; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class OrderPayTypeServiceImpl extends + BaseMpServiceImpl implements OrderPayTypeService { + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(String orderId, List data) { + Wrapper deleteOrderPayTypeWrapper = Wrappers.lambdaQuery(OrderPayType.class) + .eq(OrderPayType::getOrderId, orderId); + this.remove(deleteOrderPayTypeWrapper); + if (CollectionUtil.isNotEmpty(data)) { + List records = data.stream().map(payTypeVo -> { + OrderPayType orderPayType = new OrderPayType(); + orderPayType.setId(IdUtil.getId()); + orderPayType.setOrderId(orderId); + orderPayType.setPayTypeId(payTypeVo.getId()); + orderPayType.setPayAmount(payTypeVo.getPayAmount()); + if (StringUtil.isNotBlank(payTypeVo.getText())) { + orderPayType.setText(payTypeVo.getText()); + } + + return orderPayType; + }).collect(Collectors.toList()); + this.saveBatch(records); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByOrderId(String orderId) { + Wrapper deleteOrderPayTypeWrapper = Wrappers.lambdaQuery(OrderPayType.class) + .eq(OrderPayType::getOrderId, orderId); + this.remove(deleteOrderPayTypeWrapper); + } + + @Override + public List findByOrderId(String orderId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(OrderPayType.class) + .eq(OrderPayType::getOrderId, orderId); + return this.list(queryWrapper); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseConfigServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseConfigServiceImpl.java new file mode 100644 index 0000000..e3ed26d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseConfigServiceImpl.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.PurchaseConfigMapper; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.vo.purchase.config.UpdatePurchaseConfigVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PurchaseConfigServiceImpl extends + BaseMpServiceImpl + implements PurchaseConfigService { + + @Cacheable(value = PurchaseConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'", unless = "#result == null") + @Override + public PurchaseConfig get() { + + PurchaseConfig config = getBaseMapper().selectOne(Wrappers.query()); + + return config; + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "修改采购参数设置") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdatePurchaseConfigVo vo) { + + PurchaseConfig config = getBaseMapper().selectOne(Wrappers.query()); + config.setReceiveRequirePurchase(vo.getReceiveRequirePurchase()); + config.setReceiveMultipleRelatePurchase(vo.getReceiveMultipleRelatePurchase()); + config.setPurchaseReturnRequireReceive(vo.getPurchaseReturnRequireReceive()); + config.setPurchaseReturnMultipleRelateReceive(vo.getPurchaseReturnMultipleRelateReceive()); + + getBaseMapper().updateById(config); + + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = PurchaseConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderDetailServiceImpl.java new file mode 100644 index 0000000..b561114 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderDetailServiceImpl.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import com.lframework.xingyun.sc.mappers.PurchaseOrderDetailMapper; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderDetailService; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PurchaseOrderDetailServiceImpl extends + BaseMpServiceImpl + implements PurchaseOrderDetailService { + + @Autowired + private ProductService productService; + + @Override + public List getByOrderId(String orderId) { + + return getBaseMapper().getByOrderId(orderId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addReceiveNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + PurchaseOrderDetail orderDetail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(orderDetail.getOrderNum(), orderDetail.getReceiveNum()) + .intValue(); + if (NumberUtil.lt(remainNum, num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余收货数量为" + remainNum + + "个,本次收货数量不允许大于" + + remainNum + "个!"); + } + + if (getBaseMapper().addReceiveNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余收货数量不足,不允许继续收货!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subReceiveNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + PurchaseOrderDetail orderDetail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(orderDetail.getReceiveNum(), num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已收货数量为" + orderDetail.getReceiveNum() + + "个,本次取消收货数量不允许大于" + orderDetail.getReceiveNum() + "个!"); + } + + if (getBaseMapper().subReceiveNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已收货数量不足,不允许取消收货!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderServiceImpl.java new file mode 100644 index 0000000..db66c33 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseOrderServiceImpl.java @@ -0,0 +1,841 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import cn.hutool.core.lang.Dict; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.order.impl.ApprovePassPurchaseOrderEvent; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import com.lframework.xingyun.sc.bo.purchase.GetPurchaseOrderBo; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderWithReceiveDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.PurchaseOrderMapper; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderDetailService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.utils.WebUtils; +import com.lframework.xingyun.sc.vo.purchase.*; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import net.minidev.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class PurchaseOrderServiceImpl extends BaseMpServiceImpl + implements PurchaseOrderService { + + @Autowired + private PurchaseOrderDetailService purchaseOrderDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private SupplierService supplierService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private PurchaseConfigService purchaseConfigService; + + @Autowired + private OrderPayTypeService orderPayTypeService; + + @Autowired + private UserDetailsService userDetailsService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryPurchaseOrderVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryPurchaseOrderVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + PurchaseOrderSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PurchaseOrderFullDto getDetail(String id) { + + PurchaseOrderFullDto order = getBaseMapper().getDetail(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + return order; + } + + @Override + public PurchaseOrderWithReceiveDto getWithReceive(String id) { + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + PurchaseOrderWithReceiveDto order = getBaseMapper().getWithReceive(id, + purchaseConfig.getReceiveRequirePurchase()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + return order; + } + + @Override + public PageResult queryWithReceive(Integer pageIndex, Integer pageSize, + QueryPurchaseOrderWithReceiveVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryWithReceive(vo, + purchaseConfig.getReceiveMultipleRelatePurchase()); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "创建订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建订单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreatePurchaseOrderVo vo) { + + PurchaseOrder order = new PurchaseOrder(); + order.setId(IdUtil.getId()); + order.setCode(generateCodeService.generate(GenerateCodeTypePool.PURCHASE_ORDER)); + + this.create(order, vo); + + order.setStatus(PurchaseOrderStatus.CREATED); + + getBaseMapper().insert(order); + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + + return order.getId(); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "修改订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改订单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdatePurchaseOrderVo vo) { + + PurchaseOrder order = getBaseMapper().selectById(vo.getId()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != PurchaseOrderStatus.CREATED + && order.getStatus() != PurchaseOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,无法修改!"); + } + + throw new DefaultClientException("订单无法修改!"); + } + + // 删除订单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + PurchaseOrderDetail.class) + .eq(PurchaseOrderDetail::getOrderId, order.getId()); + purchaseOrderDetailService.remove(deleteDetailWrapper); + + this.create(order, vo); + + order.setStatus(PurchaseOrderStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(PurchaseOrderStatus.CREATED); + statusList.add(PurchaseOrderStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(PurchaseOrder.class) + .set(PurchaseOrder::getApproveBy, null).set(PurchaseOrder::getApproveTime, null) + .set(PurchaseOrder::getRefuseReason, StringPool.EMPTY_STR) + .eq(PurchaseOrder::getId, order.getId()) + .in(PurchaseOrder::getStatus, statusList); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "审核通过订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassPurchaseOrderVo vo) { + + PurchaseOrder order = getBaseMapper().selectById(vo.getId()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != PurchaseOrderStatus.CREATED + && order.getStatus() != PurchaseOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核通过!"); + } + + order.setStatus(PurchaseOrderStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(PurchaseOrderStatus.CREATED); + statusList.add(PurchaseOrderStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + PurchaseOrder.class) + .set(PurchaseOrder::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(PurchaseOrder::getApproveTime, LocalDateTime.now()) + .eq(PurchaseOrder::getId, order.getId()) + .in(PurchaseOrder::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(PurchaseOrder::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(order.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(order.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有约定支付,请检查!"); + } + } + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + + this.sendApprovePassEvent(order); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Override + public void batchApprovePass(BatchApprovePassPurchaseOrderVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassPurchaseOrderVo approvePassPurchaseOrderVo = new ApprovePassPurchaseOrderVo(); + approvePassPurchaseOrderVo.setId(id); + + try { + PurchaseOrderService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassPurchaseOrderVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个采购订单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Override + public String directApprovePass(CreatePurchaseOrderVo vo) { + + PurchaseOrderService thisService = getThis(this.getClass()); + + String orderId = thisService.create(vo); + + ApprovePassPurchaseOrderVo approvePassPurchaseOrderVo = new ApprovePassPurchaseOrderVo(); + approvePassPurchaseOrderVo.setId(orderId); + approvePassPurchaseOrderVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassPurchaseOrderVo); + + return orderId; + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "审核拒绝订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefusePurchaseOrderVo vo) { + + PurchaseOrder order = getBaseMapper().selectById(vo.getId()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != PurchaseOrderStatus.CREATED) { + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_REFUSE) { + throw new DefaultClientException("订单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核拒绝!"); + } + + order.setStatus(PurchaseOrderStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + PurchaseOrder.class) + .set(PurchaseOrder::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(PurchaseOrder::getApproveTime, LocalDateTime.now()) + .set(PurchaseOrder::getRefuseReason, vo.getRefuseReason()) + .eq(PurchaseOrder::getId, order.getId()) + .eq(PurchaseOrder::getStatus, PurchaseOrderStatus.CREATED); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Override + public void batchApproveRefuse(BatchApproveRefusePurchaseOrderVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefusePurchaseOrderVo approveRefusePurchaseOrderVo = new ApproveRefusePurchaseOrderVo(); + approveRefusePurchaseOrderVo.setId(id); + approveRefusePurchaseOrderVo.setRefuseReason(vo.getRefuseReason()); + + try { + PurchaseOrderService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefusePurchaseOrderVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个采购订单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "删除订单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + PurchaseOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != PurchaseOrderStatus.CREATED + && order.getStatus() != PurchaseOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的采购单据不允许执行删除操作!"); + } + + throw new DefaultClientException("订单无法删除!"); + } + + // 删除订单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + PurchaseOrderDetail.class) + .eq(PurchaseOrderDetail::getOrderId, order.getId()); + purchaseOrderDetailService.remove(deleteDetailWrapper); + + // 删除订单 + getBaseMapper().deleteById(id); + + orderPayTypeService.deleteByOrderId(id); + + OpLogUtil.setVariable("code", order.getCode()); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + PurchaseOrderService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个采购订单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "取消审核订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CANCEL_APPROVE, orderId = "#id", name = "取消审核") + @Transactional(rollbackFor = Exception.class) + @Override + public void cancelApprovePass(String id) { + + Assert.notBlank(id); + + PurchaseOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != PurchaseOrderStatus.APPROVE_PASS) { + + throw new DefaultClientException("订单尚未审核通过,无需取消审核!"); + } + + order.setStatus(PurchaseOrderStatus.CREATED); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(PurchaseOrder.class) + .set(PurchaseOrder::getApproveBy, null).set(PurchaseOrder::getApproveTime, null) + .set(PurchaseOrder::getRefuseReason, StringPool.EMPTY_STR) + .eq(PurchaseOrder::getId, order.getId()) + .eq(PurchaseOrder::getStatus, PurchaseOrderStatus.APPROVE_PASS); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", order.getCode()); + } + + private void create(PurchaseOrder order, CreatePurchaseOrderVo vo) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + order.setScId(vo.getScId()); + + Supplier supplier = supplierService.findById(vo.getSupplierId()); + if (supplier == null) { + throw new InputErrorException("供应商不存在!"); + } + order.setSupplierId(vo.getSupplierId()); + + if (!StringUtil.isBlank(vo.getPurchaserId())) { + UserDto purchaser = userService.findById(vo.getPurchaserId()); + if (purchaser == null) { + throw new InputErrorException("采购员不存在!"); + } + + order.setPurchaserId(vo.getPurchaserId()); + } + + order.setExpectArriveDate(vo.getExpectArriveDate()); + + int purchaseNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (PurchaseProductVo productVo : vo.getProducts()) { + + boolean isGift = productVo.getPurchasePrice().doubleValue() == 0D; + + if (isGift) { + giftNum += productVo.getPurchaseNum(); + } else { + purchaseNum += productVo.getPurchaseNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getPurchasePrice(), productVo.getPurchaseNum())); + + PurchaseOrderDetail orderDetail = new PurchaseOrderDetail(); + orderDetail.setId(IdUtil.getId()); + orderDetail.setOrderId(order.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getPurchasePrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品采购价最多允许2位小数!"); + } + + orderDetail.setProductId(productVo.getProductId()); + orderDetail.setOrderNum(productVo.getPurchaseNum()); + orderDetail.setTaxPrice(productVo.getPurchasePrice()); + orderDetail.setIsGift(isGift); + orderDetail.setTaxRate(product.getTaxRate()); + orderDetail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + orderDetail.setOrderNo(orderNo); + + purchaseOrderDetailService.save(orderDetail); + orderNo++; + } + order.setTotalNum(purchaseNum); + order.setTotalGiftNum(giftNum); + order.setTotalAmount(totalAmount); + order.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + orderPayTypeService.create(order.getId(), vo.getPayTypes()); + } + + @Override + public PageResult queryPurchaseByCondition(Integer pageIndex, + Integer pageSize, String condition) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryPurchaseByCondition(condition); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryPurchaseList(Integer pageIndex, Integer pageSize, + QueryPurchaseProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryPurchaseList(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PurchaseProductDto getPurchaseById(String id) { + + PurchaseProductDto data = getBaseMapper().getPurchaseById(id); + + return data; + } + + private void sendApprovePassEvent(PurchaseOrder order) { + + ApprovePassPurchaseOrderEvent event = new ApprovePassPurchaseOrderEvent(this); + event.setId(order.getId()); + event.setTotalAmount(order.getTotalAmount()); + event.setApproveTime(order.getApproveTime()); + + ApplicationUtil.publishEvent(event); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void approve(YdoolApproveOrderVo vo) { + String status = vo.getStatus(); + if ("y".equals(status)) { + this.approvePass(vo.getId(), vo.getMsg()); + } else { + this.approveRefuse(vo.getId(), vo.getMsg()); + } + } + + + @OpLog(type = ScOpLogType.PURCHASE, name = "发送采购订单审批流程给ydool系统,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_SEND, orderId = "#id", name = "发送采购订单审批流程给ydool系统") + @Transactional(rollbackFor = Exception.class) + @Override + public InvokeResult sendApprove(String id) { + PurchaseOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new DefaultClientException("采购订单不存在!"); + } + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("采购订单已审核通过,无需再次审核!"); + } + if (order.getStatus() == PurchaseOrderStatus.APPROVE_ING) { + throw new DefaultClientException("采购订单正在审核中,请勿重复推送"); + } + //获取订单详情 + PurchaseOrderFullDto data = this.getDetail(id); + GetPurchaseOrderBo bo = new GetPurchaseOrderBo(data); + //获取发起人编号 + String purchaserCode = bo.getPurchaserCode(); + if (StringUtil.isBlank(purchaserCode)) { + throw new DefaultClientException("采购员不存在,无法发起审核!"); + } + //封装参数 + List details = bo.getDetails(); + //将商品编号、商品名称、库存数量、采购数量、采购含税金额从details中提取出来 + List list = details.stream().map(detail -> { + //将商品编号、商品名称、库存数量、采购数量、采购含税金额从detail中提取并返回 + return Dict.create() + .set("goods_number", detail.getProductCode()) + .set("goods_name", detail.getProductName()) + .set("inventory", detail.getStockNum()) + .set("number", detail.getPurchaseNum()) + .set("money", new BigDecimal(detail.getPurchaseNum()).multiply(detail.getPurchasePrice())); + }).collect(Collectors.toList()); + Dict dict = Dict.create(); + dict.set("user_id", purchaserCode) + .set("order_id", id) + .set("all_money", bo.getTotalAmount()) + .set("supplyer", bo.getSupplierName()) + .set("audit_person_ids", "120,262") + .set("push_person_ids", "120,262") + .set("remark", bo.getDescription()) + .set("ghd_goodlist_info", list); + + String jsonString = JSONObject.toJSONString(dict); + String json = HttpUtil.post("https://nb.ydool.com/api/ydoolerp/erp_ajax.ashx/send_gwd", jsonString); + // 修改订单状态 + order.setStatus(PurchaseOrderStatus.APPROVE_ING); + int update = getBaseMapper().updateById(order); + InvokeResult success = InvokeResultBuilder.success(); + success.setMsg(jsonString); + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setVariable("id", id); + OpLogUtil.setExtra(dict); + return update > 0 ? success : InvokeResultBuilder.fail(jsonString); + } + + @Override + public PurchaseProductDto queryPurchaseBySku(String sku) { + return getBaseMapper().queryPurchaseBySku(sku); + } + + @Transactional(rollbackFor = Exception.class) + public void approvePass(String id, String description) { + PurchaseOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != PurchaseOrderStatus.APPROVE_ING) { + throw new DefaultClientException("订单无法审核通过!"); + } + + if (order.getStatus() != PurchaseOrderStatus.CREATED + && order.getStatus() != PurchaseOrderStatus.APPROVE_ING + && order.getStatus() != PurchaseOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核通过!"); + } + + order.setStatus(PurchaseOrderStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(PurchaseOrderStatus.APPROVE_ING); + + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + PurchaseOrder.class) + .set(PurchaseOrder::getApproveBy, user.getId()) + .set(PurchaseOrder::getApproveTime, LocalDateTime.now()) + .eq(PurchaseOrder::getId, order.getId()) + .in(PurchaseOrder::getStatus, statusList); + if (!StringUtil.isBlank(description)) { + updateOrderWrapper.set(PurchaseOrder::getDescription, description); + } + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(order.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(order.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有约定支付,请检查!"); + } + } + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApprovePassPurchaseOrderVo vo = new ApprovePassPurchaseOrderVo(); + vo.setId(id); + vo.setDescription(description); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核通过采购订单,单号:%s", order.getCode())); + opLogs.setLogType(ScOpLogType.PURCHASE); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(order.getId()); + orderTimeLine.setContent("审核通过"); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_PASS); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + + + this.sendApprovePassEvent(order); + } + + @Transactional(rollbackFor = Exception.class) + public void approveRefuse(String id, String refuseReason) { + if (StringUtil.isBlank(refuseReason)) { + throw new InputErrorException("请输入拒绝理由!"); + } + PurchaseOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + + if (order.getStatus() != PurchaseOrderStatus.APPROVE_ING) { + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + if (order.getStatus() == PurchaseOrderStatus.APPROVE_REFUSE) { + throw new DefaultClientException("订单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核拒绝!"); + } + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + order.setStatus(PurchaseOrderStatus.APPROVE_REFUSE); + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + PurchaseOrder.class) + .set(PurchaseOrder::getApproveBy, user.getId()) + .set(PurchaseOrder::getApproveTime, LocalDateTime.now()) + .set(PurchaseOrder::getRefuseReason, refuseReason) + .eq(PurchaseOrder::getId, order.getId()) + .eq(PurchaseOrder::getStatus, PurchaseOrderStatus.APPROVE_ING); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApproveRefusePurchaseOrderVo vo = new ApproveRefusePurchaseOrderVo(); + vo.setId(id); + vo.setRefuseReason(refuseReason); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核拒绝采购订单,单号:%s", order.getCode())); + opLogs.setLogType(ScOpLogType.PURCHASE); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(order.getId()); + orderTimeLine.setContent(String.format("审核拒绝,拒绝理由:%s", refuseReason)); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_RETURN); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnDetailServiceImpl.java new file mode 100644 index 0000000..76f265d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.PurchaseReturnDetail; +import com.lframework.xingyun.sc.mappers.PurchaseReturnDetailMapper; +import com.lframework.xingyun.sc.service.purchase.PurchaseReturnDetailService; +import org.springframework.stereotype.Service; + +@Service +public class PurchaseReturnDetailServiceImpl extends + BaseMpServiceImpl + implements PurchaseReturnDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnServiceImpl.java new file mode 100644 index 0000000..9b697d0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/PurchaseReturnServiceImpl.java @@ -0,0 +1,669 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.order.impl.ApprovePassPurchaseReturnEvent; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.purchase.returned.PurchaseReturnFullDto; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.entity.PurchaseReturnDetail; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.PurchaseReturnStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.mappers.PurchaseReturnMapper; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.service.purchase.PurchaseReturnDetailService; +import com.lframework.xingyun.sc.service.purchase.PurchaseReturnService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetDetailService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.purchase.returned.ApprovePassPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.ApproveRefusePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.BatchApprovePassPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.BatchApproveRefusePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.CreatePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.QueryPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.ReturnProductVo; +import com.lframework.xingyun.sc.vo.purchase.returned.UpdatePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PurchaseReturnServiceImpl extends + BaseMpServiceImpl + implements PurchaseReturnService { + + @Autowired + private PurchaseReturnDetailService purchaseReturnDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private SupplierService supplierService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private ReceiveSheetService receiveSheetService; + + @Autowired + private PurchaseConfigService purchaseConfigService; + + @Autowired + private ReceiveSheetDetailService receiveSheetDetailService; + + @Autowired + private ProductStockService productStockService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryPurchaseReturnVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryPurchaseReturnVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PurchaseReturnFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "创建采购退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建退单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreatePurchaseReturnVo vo) { + + PurchaseReturn purchaseReturn = new PurchaseReturn(); + purchaseReturn.setId(IdUtil.getId()); + purchaseReturn.setCode(generateCodeService.generate(GenerateCodeTypePool.PURCHASE_RETURN)); + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + this.create(purchaseReturn, vo, purchaseConfig.getPurchaseReturnRequireReceive()); + + purchaseReturn.setStatus(PurchaseReturnStatus.CREATED); + + getBaseMapper().insert(purchaseReturn); + + OpLogUtil.setVariable("code", purchaseReturn.getCode()); + OpLogUtil.setExtra(vo); + + return purchaseReturn.getId(); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "修改采购退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改退单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdatePurchaseReturnVo vo) { + + PurchaseReturn purchaseReturn = getBaseMapper().selectById(vo.getId()); + if (purchaseReturn == null) { + throw new InputErrorException("采购退货单不存在!"); + } + + if (purchaseReturn.getStatus() != PurchaseReturnStatus.CREATED + && purchaseReturn.getStatus() != PurchaseReturnStatus.APPROVE_REFUSE) { + + if (purchaseReturn.getStatus() == PurchaseReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("采购退货单已审核通过,无法修改!"); + } + + throw new DefaultClientException("采购退货单无法修改!"); + } + + boolean requireReceive = !StringUtil.isBlank(purchaseReturn.getReceiveSheetId()); + + if (requireReceive) { + //查询采购退货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + PurchaseReturnDetail.class) + .eq(PurchaseReturnDetail::getReturnId, purchaseReturn.getId()); + List details = purchaseReturnDetailService.list(queryDetailWrapper); + for (PurchaseReturnDetail detail : details) { + if (!StringUtil.isBlank(detail.getReceiveSheetDetailId())) { + //先恢复已退货数量 + receiveSheetDetailService.subReturnNum(detail.getReceiveSheetDetailId(), + detail.getReturnNum()); + } + } + } + + // 删除采购退货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + PurchaseReturnDetail.class) + .eq(PurchaseReturnDetail::getReturnId, purchaseReturn.getId()); + purchaseReturnDetailService.remove(deleteDetailWrapper); + + this.create(purchaseReturn, vo, requireReceive); + + purchaseReturn.setStatus(PurchaseReturnStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(PurchaseReturnStatus.CREATED); + statusList.add(PurchaseReturnStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(PurchaseReturn.class) + .set(PurchaseReturn::getApproveBy, null).set(PurchaseReturn::getApproveTime, null) + .set(PurchaseReturn::getRefuseReason, StringPool.EMPTY_STR) + .eq(PurchaseReturn::getId, purchaseReturn.getId()) + .in(PurchaseReturn::getStatus, statusList); + if (getBaseMapper().updateAllColumn(purchaseReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("采购退货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", purchaseReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "审核通过采购退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassPurchaseReturnVo vo) { + + PurchaseReturn purchaseReturn = getBaseMapper().selectById(vo.getId()); + if (purchaseReturn == null) { + throw new InputErrorException("采购退货单不存在!"); + } + + if (purchaseReturn.getStatus() != PurchaseReturnStatus.CREATED + && purchaseReturn.getStatus() != PurchaseReturnStatus.APPROVE_REFUSE) { + + if (purchaseReturn.getStatus() == PurchaseReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("采购退货单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("采购退货单无法审核通过!"); + } + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + if (!purchaseConfig.getPurchaseReturnMultipleRelateReceive()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(PurchaseReturn.class) + .eq(PurchaseReturn::getReceiveSheetId, purchaseReturn.getReceiveSheetId()) + .ne(PurchaseReturn::getId, purchaseReturn.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + ReceiveSheet receiveSheet = receiveSheetService.getById(purchaseReturn.getReceiveSheetId()); + throw new DefaultClientException( + "采购收货单号:" + receiveSheet.getCode() + ",已关联其他采购退货单,不允许关联多个采购退货单!"); + } + } + + purchaseReturn.setStatus(PurchaseReturnStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(PurchaseReturnStatus.CREATED); + statusList.add(PurchaseReturnStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + PurchaseReturn.class) + .set(PurchaseReturn::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(PurchaseReturn::getApproveTime, LocalDateTime.now()) + .eq(PurchaseReturn::getId, purchaseReturn.getId()) + .in(PurchaseReturn::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(PurchaseReturn::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(purchaseReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("采购退货单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + PurchaseReturnDetail.class) + .eq(PurchaseReturnDetail::getReturnId, purchaseReturn.getId()) + .orderByAsc(PurchaseReturnDetail::getOrderNo); + List details = purchaseReturnDetailService.list(queryDetailWrapper); + for (PurchaseReturnDetail detail : details) { + SubProductStockVo subproductStockVo = new SubProductStockVo(); + + subproductStockVo.setProductId(detail.getProductId()); + subproductStockVo.setScId(purchaseReturn.getScId()); + subproductStockVo.setStockNum(detail.getReturnNum()); + subproductStockVo.setTaxAmount(NumberUtil.mul(detail.getTaxPrice(), detail.getReturnNum())); + subproductStockVo.setBizId(purchaseReturn.getId()); + subproductStockVo.setBizDetailId(detail.getId()); + subproductStockVo.setBizCode(purchaseReturn.getCode()); + subproductStockVo.setBizType(ProductStockBizType.PURCHASE_RETURN.getCode()); + + productStockService.subStock(subproductStockVo); + } + + this.sendApprovePassEvent(purchaseReturn); + + OpLogUtil.setVariable("code", purchaseReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassPurchaseReturnVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassPurchaseReturnVo approvePassVo = new ApprovePassPurchaseReturnVo(); + approvePassVo.setId(id); + + try { + PurchaseReturnService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个采购退货单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreatePurchaseReturnVo vo) { + + PurchaseReturnService thisService = getThis(this.getClass()); + + String returnId = thisService.create(vo); + + ApprovePassPurchaseReturnVo approvePassVo = new ApprovePassPurchaseReturnVo(); + approvePassVo.setId(returnId); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return returnId; + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "审核拒绝采购退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefusePurchaseReturnVo vo) { + + PurchaseReturn purchaseReturn = getBaseMapper().selectById(vo.getId()); + if (purchaseReturn == null) { + throw new InputErrorException("采购退货单不存在!"); + } + + if (purchaseReturn.getStatus() != PurchaseReturnStatus.CREATED) { + + if (purchaseReturn.getStatus() == PurchaseReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("采购退货单已审核通过,不允许继续执行审核!"); + } + + if (purchaseReturn.getStatus() == PurchaseReturnStatus.APPROVE_REFUSE) { + throw new DefaultClientException("采购退货单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("采购退货单无法审核拒绝!"); + } + + purchaseReturn.setStatus(PurchaseReturnStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + PurchaseReturn.class) + .set(PurchaseReturn::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(PurchaseReturn::getApproveTime, LocalDateTime.now()) + .set(PurchaseReturn::getRefuseReason, vo.getRefuseReason()) + .eq(PurchaseReturn::getId, purchaseReturn.getId()) + .eq(PurchaseReturn::getStatus, PurchaseReturnStatus.CREATED); + if (getBaseMapper().updateAllColumn(purchaseReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("采购退货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", purchaseReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefusePurchaseReturnVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefusePurchaseReturnVo approveRefuseVo = new ApproveRefusePurchaseReturnVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + PurchaseReturnService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个采购退货单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "删除采购退货单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + PurchaseReturn purchaseReturn = getBaseMapper().selectById(id); + if (purchaseReturn == null) { + throw new InputErrorException("采购退货单不存在!"); + } + + if (purchaseReturn.getStatus() != PurchaseReturnStatus.CREATED + && purchaseReturn.getStatus() != PurchaseReturnStatus.APPROVE_REFUSE) { + + if (purchaseReturn.getStatus() == PurchaseReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的采购退货单不允许执行删除操作!"); + } + + throw new DefaultClientException("采购退货单无法删除!"); + } + + if (!StringUtil.isBlank(purchaseReturn.getReceiveSheetId())) { + //查询采购退货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + PurchaseReturnDetail.class) + .eq(PurchaseReturnDetail::getReturnId, purchaseReturn.getId()); + List details = purchaseReturnDetailService.list(queryDetailWrapper); + for (PurchaseReturnDetail detail : details) { + if (!StringUtil.isBlank(detail.getReceiveSheetDetailId())) { + //恢复已退货数量 + receiveSheetDetailService.subReturnNum(detail.getReceiveSheetDetailId(), + detail.getReturnNum()); + } + } + } + + // 删除退货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + PurchaseReturnDetail.class) + .eq(PurchaseReturnDetail::getReturnId, purchaseReturn.getId()); + purchaseReturnDetailService.remove(deleteDetailWrapper); + + // 删除退货单 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", purchaseReturn.getCode()); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + PurchaseReturnService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个采购退货单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(PurchaseReturn.class) + .set(PurchaseReturn::getSettleStatus, SettleStatus.UN_SETTLE).eq(PurchaseReturn::getId, id) + .eq(PurchaseReturn::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(PurchaseReturn.class) + .set(PurchaseReturn::getSettleStatus, SettleStatus.PART_SETTLE) + .eq(PurchaseReturn::getId, id) + .in(PurchaseReturn::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(PurchaseReturn.class) + .set(PurchaseReturn::getSettleStatus, SettleStatus.SETTLED).eq(PurchaseReturn::getId, id) + .in(PurchaseReturn::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String supplierId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(supplierId, startTime, endTime, settleStatus); + } + + private void create(PurchaseReturn purchaseReturn, CreatePurchaseReturnVo vo, + boolean requireReceive) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + purchaseReturn.setScId(vo.getScId()); + + Supplier supplier = supplierService.findById(vo.getSupplierId()); + if (supplier == null) { + throw new InputErrorException("供应商不存在!"); + } + purchaseReturn.setSupplierId(vo.getSupplierId()); + + if (!StringUtil.isBlank(vo.getPurchaserId())) { + UserDto purchaser = userService.findById(vo.getPurchaserId()); + if (purchaser == null) { + throw new InputErrorException("采购员不存在!"); + } + + purchaseReturn.setPurchaserId(vo.getPurchaserId()); + } + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + GetPaymentDateDto paymentDate = receiveSheetService.getPaymentDate(supplier.getId()); + + purchaseReturn.setPaymentDate( + paymentDate.getAllowModify() ? vo.getPaymentDate() : paymentDate.getPaymentDate()); + + if (requireReceive) { + + ReceiveSheet receiveSheet = receiveSheetService.getById(vo.getReceiveSheetId()); + if (receiveSheet == null) { + throw new DefaultClientException("采购收货单不存在!"); + } + + purchaseReturn.setScId(receiveSheet.getScId()); + purchaseReturn.setSupplierId(receiveSheet.getSupplierId()); + purchaseReturn.setReceiveSheetId(receiveSheet.getId()); + + if (!purchaseConfig.getPurchaseReturnMultipleRelateReceive()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(PurchaseReturn.class) + .eq(PurchaseReturn::getReceiveSheetId, receiveSheet.getId()) + .ne(PurchaseReturn::getId, purchaseReturn.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException( + "采购收货单号:" + receiveSheet.getCode() + ",已关联其他采购退货单,不允许关联多个采购退货单!"); + } + } + } + + int returnNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (ReturnProductVo productVo : vo.getProducts()) { + if (requireReceive) { + if (!StringUtil.isBlank(productVo.getReceiveSheetDetailId())) { + ReceiveSheetDetail detail = receiveSheetDetailService.getById( + productVo.getReceiveSheetDetailId()); + productVo.setPurchasePrice(detail.getTaxPrice()); + } else { + productVo.setPurchasePrice(BigDecimal.ZERO); + } + } + + boolean isGift = productVo.getPurchasePrice().doubleValue() == 0D; + + if (requireReceive) { + if (StringUtil.isBlank(productVo.getReceiveSheetDetailId())) { + if (!isGift) { + throw new InputErrorException("第" + orderNo + "行商品必须为“赠品”!"); + } + } + } + + if (isGift) { + giftNum += productVo.getReturnNum(); + } else { + returnNum += productVo.getReturnNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getPurchasePrice(), productVo.getReturnNum())); + + PurchaseReturnDetail detail = new PurchaseReturnDetail(); + detail.setId(IdUtil.getId()); + detail.setReturnId(purchaseReturn.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getPurchasePrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品采购价最多允许2位小数!"); + } + + detail.setProductId(productVo.getProductId()); + detail.setReturnNum(productVo.getReturnNum()); + detail.setTaxPrice(productVo.getPurchasePrice()); + detail.setIsGift(isGift); + detail.setTaxRate(product.getTaxRate()); + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + detail.setOrderNo(orderNo); + if (requireReceive && !StringUtil.isBlank(productVo.getReceiveSheetDetailId())) { + detail.setReceiveSheetDetailId(productVo.getReceiveSheetDetailId()); + receiveSheetDetailService.addReturnNum(productVo.getReceiveSheetDetailId(), + detail.getReturnNum()); + } + + purchaseReturnDetailService.save(detail); + orderNo++; + } + purchaseReturn.setTotalNum(returnNum); + purchaseReturn.setTotalGiftNum(giftNum); + purchaseReturn.setTotalAmount(totalAmount); + purchaseReturn.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + purchaseReturn.setSettleStatus(this.getInitSettleStatus(supplier)); + } + + /** + * 根据供应商获取初始结算状态 + * + * @param supplier + * @return + */ + private SettleStatus getInitSettleStatus(Supplier supplier) { + + if (supplier.getManageType() == ManageType.DISTRIBUTION) { + return SettleStatus.UN_SETTLE; + } else { + return SettleStatus.UN_REQUIRE; + } + } + + private void sendApprovePassEvent(PurchaseReturn r) { + + ApprovePassPurchaseReturnEvent event = new ApprovePassPurchaseReturnEvent(this); + event.setId(r.getId()); + event.setTotalAmount(r.getTotalAmount()); + event.setApproveTime(r.getApproveTime()); + + ApplicationUtil.publishEvent(event); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetDetailServiceImpl.java new file mode 100644 index 0000000..2f934bb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetDetailServiceImpl.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import com.lframework.xingyun.sc.mappers.ReceiveSheetDetailMapper; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetDetailService; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ReceiveSheetDetailServiceImpl extends + BaseMpServiceImpl + implements ReceiveSheetDetailService { + + @Autowired + private ProductService productService; + + @Override + public List getBySheetId(String sheetId) { + + return getBaseMapper().getBySheetId(sheetId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + ReceiveSheetDetail detail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(detail.getOrderNum(), detail.getReturnNum()).intValue(); + if (NumberUtil.lt(remainNum, num)) { + Product product = productService.findById(detail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量为" + remainNum + + "个,本次退货数量不允许大于" + + remainNum + "个!"); + } + + if (getBaseMapper().addReturnNum(detail.getId(), num) != 1) { + Product product = productService.findById(detail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量不足,不允许继续退货!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + ReceiveSheetDetail orderDetail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(orderDetail.getReturnNum(), num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量为" + orderDetail.getReturnNum() + + "个,本次取消退货数量不允许大于" + orderDetail.getReturnNum() + "个!"); + } + + if (getBaseMapper().subReturnNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量不足,不允许取消退货!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetServiceImpl.java new file mode 100644 index 0000000..0aa2e72 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/purchase/ReceiveSheetServiceImpl.java @@ -0,0 +1,725 @@ +package com.lframework.xingyun.sc.impl.purchase; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.enums.ManageType; +import com.lframework.xingyun.basedata.enums.SettleType; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetFullDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.mappers.ReceiveSheetMapper; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderDetailService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetDetailService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.purchase.receive.ApprovePassReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ApproveRefuseReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.BatchApprovePassReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.BatchApproveRefuseReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.CreateReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ReceiveProductVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ReceiveSheetSelectorVo; +import com.lframework.xingyun.sc.vo.purchase.receive.UpdateReceiveSheetVo; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ReceiveSheetServiceImpl extends BaseMpServiceImpl + implements ReceiveSheetService { + + @Autowired + private ReceiveSheetDetailService receiveSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private SupplierService supplierService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private PurchaseOrderService purchaseOrderService; + + @Autowired + private PurchaseConfigService purchaseConfigService; + + @Autowired + private PurchaseOrderDetailService purchaseOrderDetailService; + + @Autowired + private ProductStockService productStockService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryReceiveSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryReceiveSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + ReceiveSheetSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public GetPaymentDateDto getPaymentDate(String supplierId) { + + // 付款日期默认为当前日期的30天后,如当天为2021-10-01,则付款日期默认为2021-11-01 + //(1)供应商的经营方式为“经销”,且结账方式为“任意指定”,则付款日期按照以上规则展示默认值,允许用户更改,但仅能选择当天及当天之后的日期。 + //(2)供应商的经营方式为“经销”,且结账方式为“货到付款”,则付款日期默认为此刻,即收货单的创建时间,可能会遇到跨日的问题,但付款日期,均赋值为收货单的创建日期。 + //(3)供应商的经营方式为非经销模式时,收货单、退货单不涉及付款,则付款日期字段置灰,为空,且不可点击。 + + Supplier supplier = supplierService.findById(supplierId); + + GetPaymentDateDto result = new GetPaymentDateDto(); + + result.setAllowModify(supplier.getManageType() == ManageType.DISTRIBUTION + && supplier.getSettleType() == SettleType.ARBITRARILY); + if (supplier.getManageType() == ManageType.DISTRIBUTION + && supplier.getSettleType() == SettleType.ARBITRARILY) { + result.setPaymentDate(LocalDate.now().plusMonths(1)); + } else if (supplier.getManageType() == ManageType.DISTRIBUTION + && supplier.getSettleType() == SettleType.CASH_ON_DELIVERY) { + result.setPaymentDate(LocalDate.now()); + } + + return result; + } + + @Override + public ReceiveSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @Override + public ReceiveSheetWithReturnDto getWithReturn(String id) { + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + ReceiveSheetWithReturnDto sheet = getBaseMapper().getWithReturn(id, + purchaseConfig.getPurchaseReturnRequireReceive()); + if (sheet == null) { + throw new InputErrorException("收货单不存在!"); + } + return sheet; + } + + @Override + public PageResult queryWithReturn(Integer pageIndex, Integer pageSize, + QueryReceiveSheetWithReturnVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryWithReturn(vo, + purchaseConfig.getPurchaseReturnMultipleRelateReceive()); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "创建采购收货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建收货单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateReceiveSheetVo vo) { + + ReceiveSheet sheet = new ReceiveSheet(); + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.RECEIVE_SHEET)); + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + this.create(sheet, vo, purchaseConfig.getReceiveRequirePurchase()); + + sheet.setStatus(ReceiveSheetStatus.CREATED); + + getBaseMapper().insert(sheet); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + return sheet.getId(); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "修改采购收货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改收货单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateReceiveSheetVo vo) { + + ReceiveSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("采购收货单不存在!"); + } + + if (sheet.getStatus() != ReceiveSheetStatus.CREATED + && sheet.getStatus() != ReceiveSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == ReceiveSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("采购收货单已审核通过,无法修改!"); + } + + throw new DefaultClientException("采购收货单无法修改!"); + } + + boolean requirePurchase = !StringUtil.isBlank(sheet.getPurchaseOrderId()); + + if (requirePurchase) { + //查询采购收货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + ReceiveSheetDetail.class) + .eq(ReceiveSheetDetail::getSheetId, sheet.getId()); + List details = receiveSheetDetailService.list(queryDetailWrapper); + for (ReceiveSheetDetail detail : details) { + if (!StringUtil.isBlank(detail.getPurchaseOrderDetailId())) { + //先恢复已收货数量 + purchaseOrderDetailService.subReceiveNum(detail.getPurchaseOrderDetailId(), + detail.getOrderNum()); + } + } + } + + // 删除采购收货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(ReceiveSheetDetail.class) + .eq(ReceiveSheetDetail::getSheetId, sheet.getId()); + receiveSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo, requirePurchase); + + sheet.setStatus(ReceiveSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(ReceiveSheetStatus.CREATED); + statusList.add(ReceiveSheetStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(ReceiveSheet.class) + .set(ReceiveSheet::getApproveBy, null).set(ReceiveSheet::getApproveTime, null) + .set(ReceiveSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(ReceiveSheet::getId, sheet.getId()) + .in(ReceiveSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("采购收货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "审核通过采购收货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassReceiveSheetVo vo) { + + ReceiveSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("采购收货单不存在!"); + } + + if (sheet.getStatus() != ReceiveSheetStatus.CREATED + && sheet.getStatus() != ReceiveSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == ReceiveSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("采购收货单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("采购收货单无法审核通过!"); + } + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + if (!purchaseConfig.getReceiveMultipleRelatePurchase()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(ReceiveSheet.class) + .eq(ReceiveSheet::getPurchaseOrderId, sheet.getPurchaseOrderId()) + .ne(ReceiveSheet::getId, sheet.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + PurchaseOrder purchaseOrder = purchaseOrderService.getById(sheet.getPurchaseOrderId()); + throw new DefaultClientException( + "采购订单号:" + purchaseOrder.getCode() + + ",已关联其他采购收货单,不允许关联多个采购收货单!"); + } + } + + sheet.setStatus(ReceiveSheetStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(ReceiveSheetStatus.CREATED); + statusList.add(ReceiveSheetStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(ReceiveSheet.class) + .set(ReceiveSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(ReceiveSheet::getApproveTime, LocalDateTime.now()) + .eq(ReceiveSheet::getId, sheet.getId()) + .in(ReceiveSheet::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(ReceiveSheet::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("采购收货单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(ReceiveSheetDetail.class) + .eq(ReceiveSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(ReceiveSheetDetail::getOrderNo); + List details = receiveSheetDetailService.list(queryDetailWrapper); + for (ReceiveSheetDetail detail : details) { + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(detail.getProductId()); + addProductStockVo.setScId(sheet.getScId()); + addProductStockVo.setStockNum(detail.getOrderNum()); + addProductStockVo.setTaxPrice(detail.getTaxPrice()); + addProductStockVo.setBizId(sheet.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(sheet.getCode()); + addProductStockVo.setBizType(ProductStockBizType.PURCHASE.getCode()); + + productStockService.addStock(addProductStockVo); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Override + public void batchApprovePass(BatchApprovePassReceiveSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassReceiveSheetVo approvePassVo = new ApprovePassReceiveSheetVo(); + approvePassVo.setId(id); + + try { + ReceiveSheetService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个采购收货单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Override + public String directApprovePass(CreateReceiveSheetVo vo) { + + ReceiveSheetService thisService = getThis(this.getClass()); + + String sheetId = thisService.create(vo); + + ApprovePassReceiveSheetVo approvePassVo = new ApprovePassReceiveSheetVo(); + approvePassVo.setId(sheetId); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return sheetId; + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "审核拒绝采购收货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseReceiveSheetVo vo) { + + ReceiveSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("采购收货单不存在!"); + } + + if (sheet.getStatus() != ReceiveSheetStatus.CREATED) { + + if (sheet.getStatus() == ReceiveSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("采购收货单已审核通过,不允许继续执行审核!"); + } + + if (sheet.getStatus() == ReceiveSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("采购收货单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("采购收货单无法审核拒绝!"); + } + + sheet.setStatus(ReceiveSheetStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(ReceiveSheet.class) + .set(ReceiveSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(ReceiveSheet::getApproveTime, LocalDateTime.now()) + .set(ReceiveSheet::getRefuseReason, vo.getRefuseReason()) + .eq(ReceiveSheet::getId, sheet.getId()) + .eq(ReceiveSheet::getStatus, ReceiveSheetStatus.CREATED); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("采购收货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Override + public void batchApproveRefuse(BatchApproveRefuseReceiveSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseReceiveSheetVo approveRefuseVo = new ApproveRefuseReceiveSheetVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + ReceiveSheetService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个采购收货单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.PURCHASE, name = "删除采购收货单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + ReceiveSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("采购收货单不存在!"); + } + + if (sheet.getStatus() != ReceiveSheetStatus.CREATED + && sheet.getStatus() != ReceiveSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == ReceiveSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的采购收货单不允许执行删除操作!"); + } + + throw new DefaultClientException("采购收货单无法删除!"); + } + + if (!StringUtil.isBlank(sheet.getPurchaseOrderId())) { + //查询采购收货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + ReceiveSheetDetail.class) + .eq(ReceiveSheetDetail::getSheetId, sheet.getId()); + List details = receiveSheetDetailService.list(queryDetailWrapper); + for (ReceiveSheetDetail detail : details) { + if (!StringUtil.isBlank(detail.getPurchaseOrderDetailId())) { + //恢复已收货数量 + purchaseOrderDetailService.subReceiveNum(detail.getPurchaseOrderDetailId(), + detail.getOrderNum()); + } + } + } + + // 删除订单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(ReceiveSheetDetail.class) + .eq(ReceiveSheetDetail::getSheetId, sheet.getId()); + receiveSheetDetailService.remove(deleteDetailWrapper); + + // 删除订单 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @Transactional(rollbackFor = Exception.class) + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + ReceiveSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个采购收货单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ReceiveSheet.class) + .set(ReceiveSheet::getSettleStatus, SettleStatus.UN_SETTLE).eq(ReceiveSheet::getId, id) + .eq(ReceiveSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ReceiveSheet.class) + .set(ReceiveSheet::getSettleStatus, SettleStatus.PART_SETTLE).eq(ReceiveSheet::getId, id) + .in(ReceiveSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ReceiveSheet.class) + .set(ReceiveSheet::getSettleStatus, SettleStatus.SETTLED).eq(ReceiveSheet::getId, id) + .in(ReceiveSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String supplierId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(supplierId, startTime, endTime, settleStatus); + } + + private void create(ReceiveSheet sheet, CreateReceiveSheetVo vo, boolean receiveRequirePurchase) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + sheet.setScId(vo.getScId()); + + Supplier supplier = supplierService.findById(vo.getSupplierId()); + if (supplier == null) { + throw new InputErrorException("供应商不存在!"); + } + sheet.setSupplierId(vo.getSupplierId()); + + if (!StringUtil.isBlank(vo.getPurchaserId())) { + UserDto purchaser = userService.findById(vo.getPurchaserId()); + if (purchaser == null) { + throw new InputErrorException("采购员不存在!"); + } + + sheet.setPurchaserId(vo.getPurchaserId()); + } + + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + GetPaymentDateDto paymentDate = this.getPaymentDate(supplier.getId()); + + sheet.setPaymentDate( + vo.getAllowModifyPaymentDate() || paymentDate.getAllowModify() ? vo.getPaymentDate() + : paymentDate.getPaymentDate()); + sheet.setReceiveDate(vo.getReceiveDate()); + + if (receiveRequirePurchase) { + + PurchaseOrder purchaseOrder = purchaseOrderService.getById(vo.getPurchaseOrderId()); + if (purchaseOrder == null) { + throw new DefaultClientException("采购订单不存在!"); + } + + sheet.setScId(purchaseOrder.getScId()); + sheet.setSupplierId(purchaseOrder.getSupplierId()); + sheet.setPurchaseOrderId(purchaseOrder.getId()); + + if (!purchaseConfig.getReceiveMultipleRelatePurchase()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(ReceiveSheet.class) + .eq(ReceiveSheet::getPurchaseOrderId, purchaseOrder.getId()) + .ne(ReceiveSheet::getId, sheet.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException( + "采购订单号:" + purchaseOrder.getCode() + + ",已关联其他采购收货单,不允许关联多个采购收货单!"); + } + } + } + + int purchaseNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (ReceiveProductVo productVo : vo.getProducts()) { + if (receiveRequirePurchase) { + if (!StringUtil.isBlank(productVo.getPurchaseOrderDetailId())) { + PurchaseOrderDetail orderDetail = purchaseOrderDetailService.getById( + productVo.getPurchaseOrderDetailId()); + productVo.setPurchasePrice(orderDetail.getTaxPrice()); + } else { + productVo.setPurchasePrice(BigDecimal.ZERO); + } + } + + boolean isGift = productVo.getPurchasePrice().doubleValue() == 0D; + + if (receiveRequirePurchase) { + if (StringUtil.isBlank(productVo.getPurchaseOrderDetailId())) { + if (!isGift) { + throw new InputErrorException("第" + orderNo + "行商品必须为“赠品”!"); + } + } + } + + if (isGift) { + giftNum += productVo.getReceiveNum(); + } else { + purchaseNum += productVo.getReceiveNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getPurchasePrice(), productVo.getReceiveNum())); + + ReceiveSheetDetail detail = new ReceiveSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getPurchasePrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品采购价最多允许2位小数!"); + } + + detail.setProductId(productVo.getProductId()); + detail.setOrderNum(productVo.getReceiveNum()); + detail.setTaxPrice(productVo.getPurchasePrice()); + detail.setIsGift(isGift); + detail.setTaxRate(product.getTaxRate()); + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + detail.setOrderNo(orderNo); + if (receiveRequirePurchase && !StringUtil.isBlank(productVo.getPurchaseOrderDetailId())) { + detail.setPurchaseOrderDetailId(productVo.getPurchaseOrderDetailId()); + purchaseOrderDetailService.addReceiveNum(productVo.getPurchaseOrderDetailId(), + detail.getOrderNum()); + } + + receiveSheetDetailService.save(detail); + orderNo++; + } + sheet.setTotalNum(purchaseNum); + sheet.setTotalGiftNum(giftNum); + sheet.setTotalAmount(totalAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setSettleStatus(this.getInitSettleStatus(supplier)); + } + + /** + * 根据供应商获取初始结算状态 + * + * @param supplier + * @return + */ + private SettleStatus getInitSettleStatus(Supplier supplier) { + + if (supplier.getManageType() == ManageType.DISTRIBUTION) { + return SettleStatus.UN_SETTLE; + } else { + return SettleStatus.UN_REQUIRE; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailConfigServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailConfigServiceImpl.java new file mode 100644 index 0000000..c53c269 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailConfigServiceImpl.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.sc.impl.retail; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.RetailConfig; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.RetailConfigMapper; +import com.lframework.xingyun.sc.service.retail.RetailConfigService; +import com.lframework.xingyun.sc.vo.retail.config.UpdateRetailConfigVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class RetailConfigServiceImpl extends BaseMpServiceImpl + implements RetailConfigService { + + @Cacheable(value = RetailConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'", unless = "#result == null") + @Override + public RetailConfig get() { + + RetailConfig config = getBaseMapper().selectOne(Wrappers.query()); + + return config; + } + + @OpLog(type = ScOpLogType.RETAIL, name = "修改零售参数设置") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateRetailConfigVo vo) { + + RetailConfig config = getBaseMapper().selectOne(Wrappers.query()); + config.setRetailReturnRequireOutStock(vo.getRetailReturnRequireOutStock()); + config.setRetailReturnMultipleRelateOutStock(vo.getRetailReturnMultipleRelateOutStock()); + config.setRetailOutSheetRequireMember(vo.getRetailOutSheetRequireMember()); + config.setRetailReturnRequireMember(vo.getRetailReturnRequireMember()); + config.setRetailOutSheetRequireLogistics(vo.getRetailOutSheetRequireLogistics()); + + getBaseMapper().updateById(config); + + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = RetailConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailBundleServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailBundleServiceImpl.java new file mode 100644 index 0000000..1604fa6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailBundleServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.retail; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailBundle; +import com.lframework.xingyun.sc.mappers.RetailOutSheetDetailBundleMapper; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailBundleService; +import org.springframework.stereotype.Service; + +@Service +public class RetailOutSheetDetailBundleServiceImpl extends + BaseMpServiceImpl + implements RetailOutSheetDetailBundleService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailLotServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailLotServiceImpl.java new file mode 100644 index 0000000..602b799 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailLotServiceImpl.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.sc.impl.retail; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetail; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailLot; +import com.lframework.xingyun.sc.mappers.RetailOutSheetDetailLotMapper; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class RetailOutSheetDetailLotServiceImpl + extends BaseMpServiceImpl + implements RetailOutSheetDetailLotService { + + @Autowired + private ProductService productService; + + @Autowired + private RetailOutSheetDetailService retailOutSheetDetailService; + + @Override + public RetailOutSheetDetailLotDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + RetailOutSheetDetailLot detail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(detail.getOrderNum(), detail.getReturnNum()).intValue(); + if (NumberUtil.lt(remainNum, num)) { + RetailOutSheetDetail sheetDetail = retailOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量为" + remainNum + + "个,本次退货数量不允许大于" + + remainNum + "个!"); + } + + if (getBaseMapper().addReturnNum(detail.getId(), num) != 1) { + RetailOutSheetDetail sheetDetail = retailOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量不足,不允许继续退货!"); + } + + retailOutSheetDetailService.addReturnNum(detail.getDetailId(), num); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + RetailOutSheetDetailLot detail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(detail.getReturnNum(), num)) { + RetailOutSheetDetail sheetDetail = retailOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量为" + detail.getReturnNum() + + "个,本次取消退货数量不允许大于" + detail.getReturnNum() + "个!"); + } + + if (getBaseMapper().subReturnNum(detail.getId(), num) != 1) { + RetailOutSheetDetail sheetDetail = retailOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量不足,不允许取消退货!"); + } + + retailOutSheetDetailService.subReturnNum(detail.getDetailId(), num); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailServiceImpl.java new file mode 100644 index 0000000..ec4754f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetDetailServiceImpl.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.sc.impl.retail; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetail; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailBundle; +import com.lframework.xingyun.sc.mappers.RetailOutSheetDetailMapper; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailBundleService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailService; +import java.math.BigDecimal; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class RetailOutSheetDetailServiceImpl extends + BaseMpServiceImpl implements + RetailOutSheetDetailService { + + @Autowired + private ProductService productService; + + @Autowired + private RetailOutSheetDetailBundleService retailOutSheetDetailBundleService; + + @Override + public List getBySheetId(String sheetId) { + + return getBaseMapper().getBySheetId(sheetId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + RetailOutSheetDetail detail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(detail.getOrderNum(), detail.getReturnNum()).intValue(); + if (NumberUtil.lt(remainNum, num)) { + Product product = productService.findById(detail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量为" + remainNum + + "个,本次退货数量不允许大于" + remainNum + "个!"); + } + + if (getBaseMapper().addReturnNum(detail.getId(), num) != 1) { + Product product = productService.findById(detail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量不足,不允许继续退货!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + RetailOutSheetDetail orderDetail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(orderDetail.getReturnNum(), num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException("(" + product.getCode() + ")" + product.getName() + "已退货数量为" + + orderDetail.getReturnNum() + "个,本次取消退货数量不允许大于" + + orderDetail.getReturnNum() + "个!"); + } + + if (getBaseMapper().subReturnNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量不足,不允许取消退货!"); + } + } + + @Override + public BigDecimal getTotalWeightBySheetIds(List sheetIds) { + if (CollectionUtil.isEmpty(sheetIds)) { + return BigDecimal.ZERO; + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(RetailOutSheetDetail.class) + .in(RetailOutSheetDetail::getSheetId, sheetIds); + List details = this.list(queryWrapper); + BigDecimal sumWeight = details.stream().map(t -> { + Product product = productService.findById(t.getProductId()); + if (product.getProductType() == ProductType.BUNDLE) { + Wrapper detailBundleWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailBundle.class) + .eq(RetailOutSheetDetailBundle::getDetailId, t.getId()); + List detailBundles = retailOutSheetDetailBundleService.list( + detailBundleWrapper); + return detailBundles.stream().map(b -> { + Product targetProduct = productService.findById(b.getProductId()); + if (targetProduct.getWeight() == null) { + throw new DefaultClientException( + "商品(" + targetProduct.getCode() + ")" + targetProduct.getName() + + "尚未设置重量,请检查!"); + } + + return NumberUtil.mul(targetProduct.getWeight(), b.getProductOrderNum()); + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + } else { + if (product.getWeight() == null) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "尚未设置重量,请检查!"); + } + return NumberUtil.mul(t.getOrderNum(), product.getWeight()); + } + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + + return sumWeight; + } + + @Override + public BigDecimal getTotalVolumeBySheetIds(List sheetIds) { + if (CollectionUtil.isEmpty(sheetIds)) { + return BigDecimal.ZERO; + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(RetailOutSheetDetail.class) + .in(RetailOutSheetDetail::getSheetId, sheetIds); + List details = this.list(queryWrapper); + BigDecimal sumVolume = details.stream().map(t -> { + Product product = productService.findById(t.getProductId()); + if (product.getProductType() == ProductType.BUNDLE) { + Wrapper detailBundleWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailBundle.class) + .eq(RetailOutSheetDetailBundle::getDetailId, t.getId()); + List detailBundles = retailOutSheetDetailBundleService.list( + detailBundleWrapper); + return detailBundles.stream().map(b -> { + Product targetProduct = productService.findById(b.getProductId()); + if (targetProduct.getVolume() == null) { + throw new DefaultClientException( + "商品(" + targetProduct.getCode() + ")" + targetProduct.getName() + + "尚未设置体积,请检查!"); + } + + return NumberUtil.mul(targetProduct.getVolume(), b.getProductOrderNum()); + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + } else { + if (product.getVolume() == null) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "尚未设置体积,请检查!"); + } + return NumberUtil.mul(t.getOrderNum(), product.getVolume()); + } + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + + return sumVolume; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetServiceImpl.java new file mode 100644 index 0000000..2f31725 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailOutSheetServiceImpl.java @@ -0,0 +1,1178 @@ +package com.lframework.xingyun.sc.impl.retail; + +import cn.hutool.core.lang.Dict; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.order.impl.ApprovePassRetailOutSheetEvent; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import com.lframework.xingyun.core.utils.SplitNumberUtil; +import com.lframework.xingyun.sc.bo.purchase.GetPurchaseOrderBo; +import com.lframework.xingyun.sc.bo.retail.out.GetRetailOutSheetBo; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetFullDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.*; +import com.lframework.xingyun.sc.enums.*; +import com.lframework.xingyun.sc.mappers.RetailOutSheetMapper; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetDetailService; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.retail.RetailConfigService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailBundleService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.utils.WebUtils; +import com.lframework.xingyun.sc.vo.purchase.ApproveRefusePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.retail.out.ApprovePassRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.ApproveRefuseRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.BatchApprovePassRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.BatchApproveRefuseRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.CreateRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailProductVo; +import com.lframework.xingyun.sc.vo.retail.out.RetailOutProductVo; +import com.lframework.xingyun.sc.vo.retail.out.RetailOutSheetSelectorVo; +import com.lframework.xingyun.sc.vo.retail.out.UpdateRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.ApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +import net.minidev.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class RetailOutSheetServiceImpl extends + BaseMpServiceImpl + implements RetailOutSheetService { + + @Autowired + private RetailOutSheetDetailService retailOutSheetDetailService; + + @Autowired + private RetailOutSheetDetailLotService retailOutSheetDetailLotService; + + @Autowired + private RetailOutSheetDetailBundleService retailOutSheetDetailBundleService; + + @Autowired + private ProductBundleService productBundleService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private MemberService memberService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private RetailConfigService retailConfigService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private OrderPayTypeService orderPayTypeService; + + @Autowired + private LogisticsSheetDetailService logisticsSheetDetailService; + + @Autowired + private UserDetailsService userDetailsService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryRetailOutSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryRetailOutSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + RetailOutSheetSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public GetPaymentDateDto getPaymentDate(String memberId) { + + GetPaymentDateDto result = new GetPaymentDateDto(); + result.setAllowModify(Boolean.TRUE); + result.setPaymentDate(LocalDate.now()); + + return result; + } + + @Override + public RetailOutSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @Override + public RetailOutSheetWithReturnDto getWithReturn(String id) { + + RetailConfig retailConfig = retailConfigService.get(); + + RetailOutSheetWithReturnDto sheet = getBaseMapper().getWithReturn(id, + retailConfig.getRetailReturnRequireOutStock()); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + return sheet; + } + + @Override + public PageResult queryWithReturn(Integer pageIndex, Integer pageSize, + QueryRetailOutSheetWithReturnVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + RetailConfig retailConfig = retailConfigService.get(); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryWithReturn(vo, + retailConfig.getRetailReturnMultipleRelateOutStock()); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = ScOpLogType.RETAIL, name = "创建零售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建出库单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateRetailOutSheetVo vo) { + + RetailOutSheet sheet = new RetailOutSheet(); + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.RETAIL_OUT_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(RetailOutSheetStatus.CREATED); + + getBaseMapper().insert(sheet); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + return sheet.getId(); + } + + @OpLog(type = ScOpLogType.RETAIL, name = "修改零售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改出库单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateRetailOutSheetVo vo) { + + RetailOutSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + if (sheet.getStatus() != RetailOutSheetStatus.CREATED + && sheet.getStatus() != RetailOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("零售出库单已审核通过,无法修改!"); + } + + throw new DefaultClientException("零售出库单无法修改!"); + } + + // 删除出库单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetail.class) + .eq(RetailOutSheetDetail::getSheetId, sheet.getId()); + retailOutSheetDetailService.remove(deleteDetailWrapper); + + // 删除组合商品信息 + Wrapper deleteDetailBundleWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailBundle.class).eq(RetailOutSheetDetailBundle::getSheetId, sheet.getId()); + retailOutSheetDetailBundleService.remove(deleteDetailBundleWrapper); + + this.create(sheet, vo); + + sheet.setStatus(RetailOutSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(RetailOutSheetStatus.CREATED); + statusList.add(RetailOutSheetStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(RetailOutSheet.class) + .set(RetailOutSheet::getApproveBy, null).set(RetailOutSheet::getApproveTime, null) + .set(RetailOutSheet::getRefuseReason, StringPool.EMPTY_STR) + .set(RetailOutSheet::getMemberId, sheet.getMemberId()) + .eq(RetailOutSheet::getId, sheet.getId()) + .in(RetailOutSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售出库单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.RETAIL, name = "审核通过零售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassRetailOutSheetVo vo) { + + RetailOutSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + if (sheet.getStatus() != RetailOutSheetStatus.CREATED + && sheet.getStatus() != RetailOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("零售出库单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("零售出库单无法审核通过!"); + } + + RetailConfig retailConfig = retailConfigService.get(); + if (retailConfig.getRetailOutSheetRequireLogistics()) { + // 关联物流单 + LogisticsSheetDetail logisticsSheetDetail = logisticsSheetDetailService.getByBizId( + sheet.getId(), LogisticsSheetDetailBizType.RETAIL_OUT_SHEET); + if (logisticsSheetDetail == null) { + throw new DefaultClientException("零售出库单尚未发货,无法审核通过!"); + } + } + + sheet.setStatus(RetailOutSheetStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(RetailOutSheetStatus.CREATED); + statusList.add(RetailOutSheetStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + RetailOutSheet.class) + .set(RetailOutSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(RetailOutSheet::getApproveTime, LocalDateTime.now()) + .eq(RetailOutSheet::getId, sheet.getId()) + .in(RetailOutSheet::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(RetailOutSheet::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售出库单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(sheet.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(sheet.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有支付方式,请检查!"); + } + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetail.class) + .eq(RetailOutSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(RetailOutSheetDetail::getOrderNo); + List details = retailOutSheetDetailService.list(queryDetailWrapper); + + int totalNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (RetailOutSheetDetail detail : details) { + boolean isGift = detail.getIsGift(); + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(detail.getTaxPrice(), detail.getOrderNum())); + + Product product = productService.findById(detail.getProductId()); + if (product.getProductType() == ProductType.NORMAL) { + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(detail.getProductId()); + subProductStockVo.setScId(sheet.getScId()); + subProductStockVo.setStockNum(detail.getOrderNum()); + subProductStockVo.setBizId(sheet.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(sheet.getCode()); + subProductStockVo.setBizType(ProductStockBizType.RETAIL.getCode()); + + ProductStockChangeDto stockChange = productStockService.subStock(subProductStockVo); + + RetailOutSheetDetailLot detailLot = new RetailOutSheetDetailLot(); + + detailLot.setId(IdUtil.getId()); + detailLot.setDetailId(detail.getId()); + detailLot.setOrderNum(detail.getOrderNum()); + detailLot.setCostTaxAmount(stockChange.getTaxAmount()); + detailLot.setSettleStatus(detail.getSettleStatus()); + detailLot.setOrderNo(orderNo); + retailOutSheetDetailLotService.save(detailLot); + + if (isGift) { + giftNum += detail.getOrderNum(); + } else { + totalNum += detail.getOrderNum(); + } + } else { + Wrapper queryBundleWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailBundle.class) + .eq(RetailOutSheetDetailBundle::getSheetId, sheet.getId()) + .eq(RetailOutSheetDetailBundle::getDetailId, detail.getId()); + List retailOutSheetDetailBundles = retailOutSheetDetailBundleService.list( + queryBundleWrapper); + Assert.notEmpty(retailOutSheetDetailBundles); + + for (RetailOutSheetDetailBundle retailOutSheetDetailBundle : retailOutSheetDetailBundles) { + RetailOutSheetDetail newDetail = new RetailOutSheetDetail(); + newDetail.setId(IdUtil.getId()); + newDetail.setSheetId(sheet.getId()); + newDetail.setProductId(retailOutSheetDetailBundle.getProductId()); + newDetail.setOrderNum(retailOutSheetDetailBundle.getProductOrderNum()); + newDetail.setOriPrice(retailOutSheetDetailBundle.getProductOriPrice()); + newDetail.setTaxPrice(retailOutSheetDetailBundle.getProductTaxPrice()); + newDetail.setDiscountRate(detail.getDiscountRate()); + newDetail.setIsGift(detail.getIsGift()); + newDetail.setTaxRate(retailOutSheetDetailBundle.getProductTaxRate()); + newDetail.setDescription(detail.getDescription()); + newDetail.setOrderNo(orderNo++); + newDetail.setSettleStatus(detail.getSettleStatus()); + newDetail.setOriBundleDetailId(detail.getId()); + + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(newDetail.getProductId()); + subProductStockVo.setScId(sheet.getScId()); + subProductStockVo.setStockNum(newDetail.getOrderNum()); + subProductStockVo.setBizId(sheet.getId()); + subProductStockVo.setBizDetailId(newDetail.getId()); + subProductStockVo.setBizCode(sheet.getCode()); + subProductStockVo.setBizType(ProductStockBizType.RETAIL.getCode()); + + ProductStockChangeDto stockChange = productStockService.subStock(subProductStockVo); + + RetailOutSheetDetailLot detailLot = new RetailOutSheetDetailLot(); + + detailLot.setId(IdUtil.getId()); + detailLot.setDetailId(newDetail.getId()); + detailLot.setOrderNum(newDetail.getOrderNum()); + detailLot.setCostTaxAmount(stockChange.getTaxAmount()); + detailLot.setSettleStatus(newDetail.getSettleStatus()); + detailLot.setOrderNo(orderNo); + retailOutSheetDetailLotService.save(detailLot); + + retailOutSheetDetailService.save(newDetail); + retailOutSheetDetailService.removeById(detail.getId()); + + retailOutSheetDetailBundle.setProductDetailId(newDetail.getId()); + retailOutSheetDetailBundleService.updateById(retailOutSheetDetailBundle); + + if (isGift) { + giftNum += newDetail.getOrderNum(); + } else { + totalNum += newDetail.getOrderNum(); + } + } + } + orderNo++; + } + + // 这里需要重新统计明细信息,因为明细发生变动了 + Wrapper updateWrapper = Wrappers.lambdaUpdate(RetailOutSheet.class) + .set(RetailOutSheet::getTotalNum, totalNum).set(RetailOutSheet::getTotalGiftNum, giftNum) + .set(RetailOutSheet::getTotalAmount, totalAmount).eq(RetailOutSheet::getId, sheet.getId()); + this.update(updateWrapper); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassRetailOutSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassRetailOutSheetVo approvePassVo = new ApprovePassRetailOutSheetVo(); + approvePassVo.setId(id); + + try { + RetailOutSheetService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个零售出库单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateRetailOutSheetVo vo) { + + RetailOutSheetService thisService = getThis(this.getClass()); + + String sheetId = thisService.create(vo); + + ApprovePassRetailOutSheetVo approvePassVo = new ApprovePassRetailOutSheetVo(); + approvePassVo.setId(sheetId); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return sheetId; + } + + @OpLog(type = ScOpLogType.RETAIL, name = "审核拒绝零售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseRetailOutSheetVo vo) { + + RetailOutSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + if (sheet.getStatus() != RetailOutSheetStatus.CREATED) { + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("零售出库单已审核通过,不允许继续执行审核!"); + } + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("零售出库单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("零售出库单无法审核拒绝!"); + } + + sheet.setStatus(RetailOutSheetStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + RetailOutSheet.class) + .set(RetailOutSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(RetailOutSheet::getApproveTime, LocalDateTime.now()) + .set(RetailOutSheet::getRefuseReason, vo.getRefuseReason()) + .eq(RetailOutSheet::getId, sheet.getId()) + .eq(RetailOutSheet::getStatus, RetailOutSheetStatus.CREATED); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售出库单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseRetailOutSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseRetailOutSheetVo approveRefuseVo = new ApproveRefuseRetailOutSheetVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + RetailOutSheetService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个零售出库单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.RETAIL, name = "删除零售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + RetailOutSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + if (sheet.getStatus() != RetailOutSheetStatus.CREATED + && sheet.getStatus() != RetailOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的零售出库单不允许执行删除操作!"); + } + + throw new DefaultClientException("零售出库单无法删除!"); + } + + if (logisticsSheetDetailService.getByBizId(sheet.getId(), + LogisticsSheetDetailBizType.RETAIL_OUT_SHEET) != null) { + throw new DefaultClientException("零售出库单已关联物流单,请先删除物流单!"); + } + + // 删除订单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetail.class) + .eq(RetailOutSheetDetail::getSheetId, sheet.getId()); + List details = retailOutSheetDetailService.list(queryDetailWrapper); + retailOutSheetDetailService.remove(queryDetailWrapper); + + // 删除组合商品信息 + Wrapper deleteDetailBundleWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailBundle.class).eq(RetailOutSheetDetailBundle::getSheetId, sheet.getId()); + retailOutSheetDetailBundleService.remove(deleteDetailBundleWrapper); + + Wrapper deleteDetailLotWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailLot.class).in(RetailOutSheetDetailLot::getDetailId, + details.stream().map(RetailOutSheetDetail::getId).collect( + Collectors.toList())); + retailOutSheetDetailLotService.remove(deleteDetailLotWrapper); + + // 删除订单 + getBaseMapper().deleteById(id); + + orderPayTypeService.deleteByOrderId(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + RetailOutSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个零售出库单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Override + public PageResult queryRetailByCondition(Integer pageIndex, Integer pageSize, + String condition, Boolean isReturn) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryRetailByCondition(condition, isReturn); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryRetailList(Integer pageIndex, Integer pageSize, + QueryRetailProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryRetailList(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public RetailProductDto getRetailById(String id) { + + RetailProductDto data = getBaseMapper().getRetailById(id); + return data; + } + + @OpLog(type = ScOpLogType.RETAIL, name = "发送零售出库单审批流程给ydool系统,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_SEND, orderId = "#id", name = "发送零售出库单审批流程给ydool系统") + @Transactional(rollbackFor = Exception.class) + @Override + public InvokeResult sendApprove(String id) { + RetailOutSheet order = getBaseMapper().selectById(id); + if (order == null) { + throw new DefaultClientException("零售出库单不存在!"); + } + if (order.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("零售出库单已审核通过,无需再次审核!"); + } + if (order.getStatus() == RetailOutSheetStatus.APPROVE_ING) { + throw new DefaultClientException("零售出库单正在审核中,请勿重复推送"); + } + //获取订单详情 + RetailOutSheetFullDto data = this.getDetail(id); + + GetRetailOutSheetBo bo = new GetRetailOutSheetBo(data); + //获取发起人编号 + String salerCode = bo.getSalerCode(); + if (StringUtil.isBlank(salerCode)) { + throw new DefaultClientException("销售员不存在,无法发起审核!"); + } + //封装参数 + List details = bo.getDetails(); + //将商品编号、商品名称、库存数量、采购数量、采购含税金额从details中提取出来 + List list = details.stream().map(detail -> { + //将商品编号、商品名称、库存数量、采购数量、采购含税金额从detail中提取并返回 + return Dict.create() + .set("goods_number", detail.getProductCode()) + .set("goods_name", detail.getProductName()) + .set("number", detail.getOutNum()) + .set("money", new BigDecimal(detail.getOutNum()).multiply(detail.getTaxPrice())); + }).collect(Collectors.toList()); + Dict dict = Dict.create(); + dict.set("user_id", salerCode) + .set("order_id", id) + .set("all_money", bo.getTotalAmount()) + .set("audit_person_ids", "120,262") + .set("push_person_ids", "120,262") + .set("remark", bo.getDescription()) + .set("ghd_goodlist_info", list); + + String jsonString = JSONObject.toJSONString(dict); + String json = HttpUtil.post("https://nb.ydool.com/api/ydoolerp/erp_ajax.ashx/send_ls", jsonString); + // 修改订单状态 + order.setStatus(RetailOutSheetStatus.APPROVE_ING); + int update = getBaseMapper().updateById(order); + InvokeResult success = InvokeResultBuilder.success(); + success.setMsg(jsonString); + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setVariable("id", id); + OpLogUtil.setExtra(dict); + return update > 0 ? success : InvokeResultBuilder.fail(jsonString); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void approve(YdoolApproveOrderVo vo) { + String status = vo.getStatus(); + if ("y".equals(status)) { + this.approvePass(vo.getId(), vo.getMsg()); + } else { + this.approveRefuse(vo.getId(), vo.getMsg()); + } + } + + + + @Transactional(rollbackFor = Exception.class) + public void approvePass(String id, String description) { + RetailOutSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + if (sheet.getStatus() != RetailOutSheetStatus.APPROVE_ING) { + throw new DefaultClientException("零售出库单无法审核通过!"); + } + + if (sheet.getStatus() != RetailOutSheetStatus.CREATED + && sheet.getStatus() != RetailOutSheetStatus.APPROVE_ING + && sheet.getStatus() != RetailOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("零售出库单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("零售出库单无法审核通过!"); + } + + RetailConfig retailConfig = retailConfigService.get(); + if (retailConfig.getRetailOutSheetRequireLogistics()) { + // 关联物流单 + LogisticsSheetDetail logisticsSheetDetail = logisticsSheetDetailService.getByBizId( + sheet.getId(), LogisticsSheetDetailBizType.RETAIL_OUT_SHEET); + if (logisticsSheetDetail == null) { + throw new DefaultClientException("零售出库单尚未发货,无法审核通过!"); + } + } + + sheet.setStatus(RetailOutSheetStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(RetailOutSheetStatus.APPROVE_ING); + + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + RetailOutSheet.class) + .set(RetailOutSheet::getApproveBy, user.getId()) + .set(RetailOutSheet::getApproveTime, LocalDateTime.now()) + .eq(RetailOutSheet::getId, sheet.getId()) + .in(RetailOutSheet::getStatus, statusList); + if (!StringUtil.isBlank(description)) { + updateOrderWrapper.set(RetailOutSheet::getDescription, description); + } + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售出库单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(sheet.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(sheet.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有支付方式,请检查!"); + } + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetail.class) + .eq(RetailOutSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(RetailOutSheetDetail::getOrderNo); + List details = retailOutSheetDetailService.list(queryDetailWrapper); + + int totalNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (RetailOutSheetDetail detail : details) { + boolean isGift = detail.getIsGift(); + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(detail.getTaxPrice(), detail.getOrderNum())); + + Product product = productService.findById(detail.getProductId()); + if (product.getProductType() == ProductType.NORMAL) { + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(detail.getProductId()); + subProductStockVo.setScId(sheet.getScId()); + subProductStockVo.setStockNum(detail.getOrderNum()); + subProductStockVo.setBizId(sheet.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(sheet.getCode()); + subProductStockVo.setBizType(ProductStockBizType.RETAIL.getCode()); + + ProductStockChangeDto stockChange = productStockService.subStock(subProductStockVo); + + RetailOutSheetDetailLot detailLot = new RetailOutSheetDetailLot(); + + detailLot.setId(IdUtil.getId()); + detailLot.setDetailId(detail.getId()); + detailLot.setOrderNum(detail.getOrderNum()); + detailLot.setCostTaxAmount(stockChange.getTaxAmount()); + detailLot.setSettleStatus(detail.getSettleStatus()); + detailLot.setOrderNo(orderNo); + retailOutSheetDetailLotService.save(detailLot); + + if (isGift) { + giftNum += detail.getOrderNum(); + } else { + totalNum += detail.getOrderNum(); + } + } else { + Wrapper queryBundleWrapper = Wrappers.lambdaQuery( + RetailOutSheetDetailBundle.class) + .eq(RetailOutSheetDetailBundle::getSheetId, sheet.getId()) + .eq(RetailOutSheetDetailBundle::getDetailId, detail.getId()); + List retailOutSheetDetailBundles = retailOutSheetDetailBundleService.list( + queryBundleWrapper); + Assert.notEmpty(retailOutSheetDetailBundles); + + for (RetailOutSheetDetailBundle retailOutSheetDetailBundle : retailOutSheetDetailBundles) { + RetailOutSheetDetail newDetail = new RetailOutSheetDetail(); + newDetail.setId(IdUtil.getId()); + newDetail.setSheetId(sheet.getId()); + newDetail.setProductId(retailOutSheetDetailBundle.getProductId()); + newDetail.setOrderNum(retailOutSheetDetailBundle.getProductOrderNum()); + newDetail.setOriPrice(retailOutSheetDetailBundle.getProductOriPrice()); + newDetail.setTaxPrice(retailOutSheetDetailBundle.getProductTaxPrice()); + newDetail.setDiscountRate(detail.getDiscountRate()); + newDetail.setIsGift(detail.getIsGift()); + newDetail.setTaxRate(retailOutSheetDetailBundle.getProductTaxRate()); + newDetail.setDescription(detail.getDescription()); + newDetail.setOrderNo(orderNo++); + newDetail.setSettleStatus(detail.getSettleStatus()); + newDetail.setOriBundleDetailId(detail.getId()); + + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(newDetail.getProductId()); + subProductStockVo.setScId(sheet.getScId()); + subProductStockVo.setStockNum(newDetail.getOrderNum()); + subProductStockVo.setBizId(sheet.getId()); + subProductStockVo.setBizDetailId(newDetail.getId()); + subProductStockVo.setBizCode(sheet.getCode()); + subProductStockVo.setBizType(ProductStockBizType.RETAIL.getCode()); + + ProductStockChangeDto stockChange = productStockService.subStock(subProductStockVo); + + RetailOutSheetDetailLot detailLot = new RetailOutSheetDetailLot(); + + detailLot.setId(IdUtil.getId()); + detailLot.setDetailId(newDetail.getId()); + detailLot.setOrderNum(newDetail.getOrderNum()); + detailLot.setCostTaxAmount(stockChange.getTaxAmount()); + detailLot.setSettleStatus(newDetail.getSettleStatus()); + detailLot.setOrderNo(orderNo); + retailOutSheetDetailLotService.save(detailLot); + + retailOutSheetDetailService.save(newDetail); + retailOutSheetDetailService.removeById(detail.getId()); + + retailOutSheetDetailBundle.setProductDetailId(newDetail.getId()); + retailOutSheetDetailBundleService.updateById(retailOutSheetDetailBundle); + + if (isGift) { + giftNum += newDetail.getOrderNum(); + } else { + totalNum += newDetail.getOrderNum(); + } + } + } + orderNo++; + } + + // 这里需要重新统计明细信息,因为明细发生变动了 + Wrapper updateWrapper = Wrappers.lambdaUpdate(RetailOutSheet.class) + .set(RetailOutSheet::getTotalNum, totalNum).set(RetailOutSheet::getTotalGiftNum, giftNum) + .set(RetailOutSheet::getTotalAmount, totalAmount).eq(RetailOutSheet::getId, sheet.getId()); + this.update(updateWrapper); + + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApprovePassRetailOutSheetVo vo = new ApprovePassRetailOutSheetVo(); + vo.setId(id); + vo.setDescription(description); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核通过零售出库单,单号:%s", sheet.getCode())); + opLogs.setLogType(ScOpLogType.RETAIL); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(sheet.getId()); + orderTimeLine.setContent("审核通过"); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_PASS); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + + this.sendApprovePassEvent(sheet); + } + + @Transactional(rollbackFor = Exception.class) + public void approveRefuse(String id, String refuseReason) { + if (StringUtil.isBlank(refuseReason)) { + throw new InputErrorException("请输入拒绝理由!"); + } + + RetailOutSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("零售出库单不存在!"); + } + + + if (sheet.getStatus() != RetailOutSheetStatus.APPROVE_ING) { + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("零售出库单已审核通过,不允许继续执行审核!"); + } + + if (sheet.getStatus() == RetailOutSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("零售出库单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("零售出库单无法审核拒绝!"); + } + + sheet.setStatus(RetailOutSheetStatus.APPROVE_REFUSE); + + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate( + RetailOutSheet.class) + .set(RetailOutSheet::getApproveBy, user.getId()) + .set(RetailOutSheet::getApproveTime, LocalDateTime.now()) + .set(RetailOutSheet::getRefuseReason, refuseReason) + .eq(RetailOutSheet::getId, sheet.getId()) + .eq(RetailOutSheet::getStatus, RetailOutSheetStatus.APPROVE_ING); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售出库单信息已过期,请刷新重试!"); + } + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApproveRefuseRetailOutSheetVo vo = new ApproveRefuseRetailOutSheetVo(); + vo.setId(id); + vo.setRefuseReason(refuseReason); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核拒绝零售出库单,单号:%s", sheet.getCode())); + opLogs.setLogType(ScOpLogType.RETAIL); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(sheet.getId()); + orderTimeLine.setContent(String.format("审核拒绝,拒绝理由:%s", refuseReason)); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_RETURN); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + + } + + private void create(RetailOutSheet sheet, CreateRetailOutSheetVo vo) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + sheet.setScId(vo.getScId()); + + Member member = null; + if (!StringUtil.isBlank(vo.getMemberId())) { + member = memberService.findById(vo.getMemberId()); + if (member == null) { + throw new InputErrorException("会员不存在!"); + } + sheet.setMemberId(vo.getMemberId()); + } else { + sheet.setMemberId(null); + } + + if (!StringUtil.isBlank(vo.getSalerId())) { + UserDto saler = userService.findById(vo.getSalerId()); + if (saler == null) { + throw new InputErrorException("销售员不存在!"); + } + + sheet.setSalerId(vo.getSalerId()); + } + + GetPaymentDateDto paymentDate = this.getPaymentDate(member == null ? null : member.getId()); + + sheet.setPaymentDate( + vo.getAllowModifyPaymentDate() || paymentDate.getAllowModify() ? vo.getPaymentDate() + : paymentDate.getPaymentDate()); + + int purchaseNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (RetailOutProductVo productVo : vo.getProducts()) { + boolean isGift = productVo.getTaxPrice().doubleValue() == 0D; + + if (isGift) { + giftNum += productVo.getOrderNum(); + } else { + purchaseNum += productVo.getOrderNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getTaxPrice(), productVo.getOrderNum())); + + RetailOutSheetDetail detail = new RetailOutSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getTaxPrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品价格最多允许2位小数!"); + } + + detail.setProductId(productVo.getProductId()); + detail.setOrderNum(productVo.getOrderNum()); + detail.setOriPrice(productVo.getOriPrice()); + detail.setTaxPrice(productVo.getTaxPrice()); + detail.setDiscountRate(productVo.getDiscountRate()); + detail.setIsGift(isGift); + detail.setTaxRate(product.getSaleTaxRate()); + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + detail.setOrderNo(orderNo); + detail.setSettleStatus(this.getInitSettleStatus(member)); + + retailOutSheetDetailService.save(detail); + + // 这里处理组合商品 + if (product.getProductType() == ProductType.BUNDLE) { + List productBundles = productBundleService.getByMainProductId( + product.getId()); + // 构建指标项 + Map bundleWeight = new HashMap<>(productBundles.size()); + for (ProductBundle productBundle : productBundles) { + bundleWeight.put(productBundle.getProductId(), + NumberUtil.mul(productBundle.getRetailPrice(), productBundle.getBundleNum())); + } + Map splitPriceMap = SplitNumberUtil.split(detail.getTaxPrice(), + bundleWeight, 2); + List retailOutSheetDetailBundles = productBundles.stream() + .map(productBundle -> { + Product bundle = productService.findById(productBundle.getProductId()); + RetailOutSheetDetailBundle retailOutSheetDetailBundle = new RetailOutSheetDetailBundle(); + retailOutSheetDetailBundle.setId(IdUtil.getId()); + retailOutSheetDetailBundle.setSheetId(sheet.getId()); + retailOutSheetDetailBundle.setDetailId(detail.getId()); + retailOutSheetDetailBundle.setMainProductId(product.getId()); + retailOutSheetDetailBundle.setOrderNum(detail.getOrderNum()); + retailOutSheetDetailBundle.setProductId(productBundle.getProductId()); + retailOutSheetDetailBundle.setProductOrderNum( + NumberUtil.mul(detail.getOrderNum(), productBundle.getBundleNum()).intValue()); + retailOutSheetDetailBundle.setProductOriPrice(productBundle.getRetailPrice()); + // 这里会有尾差 + retailOutSheetDetailBundle.setProductTaxPrice( + NumberUtil.getNumber(NumberUtil.div(BigDecimal.valueOf( + splitPriceMap.get(productBundle.getProductId()).doubleValue()), + productBundle.getBundleNum()), 2)); + retailOutSheetDetailBundle.setProductTaxRate(bundle.getSaleTaxRate()); + + return retailOutSheetDetailBundle; + }).collect(Collectors.toList()); + + retailOutSheetDetailBundleService.saveBatch(retailOutSheetDetailBundles); + } + orderNo++; + } + sheet.setTotalNum(purchaseNum); + sheet.setTotalGiftNum(giftNum); + sheet.setTotalAmount(totalAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setSettleStatus(this.getInitSettleStatus(member)); + + orderPayTypeService.create(sheet.getId(), vo.getPayTypes()); + } + + /** + * 根据会员获取初始结算状态 + * + * @param member + * @return + */ + private SettleStatus getInitSettleStatus(Member member) { + + return SettleStatus.UN_SETTLE; + } + + private void sendApprovePassEvent(RetailOutSheet sheet) { + + ApprovePassRetailOutSheetEvent event = new ApprovePassRetailOutSheetEvent(this); + event.setId(sheet.getId()); + event.setTotalAmount(sheet.getTotalAmount()); + event.setApproveTime(sheet.getApproveTime()); + + ApplicationUtil.publishEvent(event); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnDetailServiceImpl.java new file mode 100644 index 0000000..8e5ec0b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.retail; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.RetailReturnDetail; +import com.lframework.xingyun.sc.mappers.RetailReturnDetailMapper; +import com.lframework.xingyun.sc.service.retail.RetailReturnDetailService; +import org.springframework.stereotype.Service; + +@Service +public class RetailReturnDetailServiceImpl extends + BaseMpServiceImpl + implements RetailReturnDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnServiceImpl.java new file mode 100644 index 0000000..cd6b80e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/retail/RetailReturnServiceImpl.java @@ -0,0 +1,654 @@ +package com.lframework.xingyun.sc.impl.retail; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Member; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.member.MemberService; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.order.impl.ApprovePassRetailReturnEvent; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetDetailLotDto; +import com.lframework.xingyun.sc.dto.retail.returned.RetailReturnFullDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.RetailConfig; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetail; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.entity.RetailReturnDetail; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.RetailReturnStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.mappers.RetailReturnMapper; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.retail.RetailConfigService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.service.retail.RetailReturnDetailService; +import com.lframework.xingyun.sc.service.retail.RetailReturnService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.retail.returned.ApprovePassRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.ApproveRefuseRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.BatchApprovePassRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.BatchApproveRefuseRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.CreateRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.QueryRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.RetailReturnProductVo; +import com.lframework.xingyun.sc.vo.retail.returned.UpdateRetailReturnVo; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class RetailReturnServiceImpl extends BaseMpServiceImpl + implements RetailReturnService { + + @Autowired + private RetailReturnDetailService retailReturnDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private MemberService memberService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private RetailOutSheetService retailOutSheetService; + + @Autowired + private RetailConfigService retailConfigService; + + @Autowired + private RetailOutSheetDetailService retailOutSheetDetailService; + + @Autowired + private RetailOutSheetDetailLotService retailOutSheetDetailLotService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private ProductPurchaseService productPurchaseService; + + @Autowired + private OrderPayTypeService orderPayTypeService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryRetailReturnVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryRetailReturnVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public RetailReturnFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.RETAIL, name = "创建零售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建退单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateRetailReturnVo vo) { + + RetailReturn retailReturn = new RetailReturn(); + retailReturn.setId(IdUtil.getId()); + retailReturn.setCode(generateCodeService.generate(GenerateCodeTypePool.RETAIL_RETURN)); + + RetailConfig retailConfig = retailConfigService.get(); + + this.create(retailReturn, vo, retailConfig.getRetailReturnRequireOutStock()); + + retailReturn.setStatus(RetailReturnStatus.CREATED); + + getBaseMapper().insert(retailReturn); + + OpLogUtil.setVariable("code", retailReturn.getCode()); + OpLogUtil.setExtra(vo); + + return retailReturn.getId(); + } + + @OpLog(type = ScOpLogType.RETAIL, name = "修改零售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改退单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateRetailReturnVo vo) { + + RetailReturn retailReturn = getBaseMapper().selectById(vo.getId()); + if (retailReturn == null) { + throw new InputErrorException("零售退货单不存在!"); + } + + if (retailReturn.getStatus() != RetailReturnStatus.CREATED + && retailReturn.getStatus() != RetailReturnStatus.APPROVE_REFUSE) { + + if (retailReturn.getStatus() == RetailReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("零售退货单已审核通过,无法修改!"); + } + + throw new DefaultClientException("零售退货单无法修改!"); + } + + boolean requireOut = !StringUtil.isBlank(retailReturn.getOutSheetId()); + + if (requireOut) { + //查询零售退货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + RetailReturnDetail.class) + .eq(RetailReturnDetail::getReturnId, retailReturn.getId()); + List details = retailReturnDetailService.list(queryDetailWrapper); + for (RetailReturnDetail detail : details) { + if (!StringUtil.isBlank(detail.getOutSheetDetailId())) { + //先恢复已退货数量 + retailOutSheetDetailLotService.subReturnNum(detail.getOutSheetDetailId(), + detail.getReturnNum()); + } + } + } + + // 删除零售退货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(RetailReturnDetail.class) + .eq(RetailReturnDetail::getReturnId, retailReturn.getId()); + retailReturnDetailService.remove(deleteDetailWrapper); + + this.create(retailReturn, vo, requireOut); + + retailReturn.setStatus(RetailReturnStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(RetailReturnStatus.CREATED); + statusList.add(RetailReturnStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(RetailReturn.class) + .set(RetailReturn::getApproveBy, null).set(RetailReturn::getApproveTime, null) + .set(RetailReturn::getRefuseReason, StringPool.EMPTY_STR) + .set(RetailReturn::getMemberId, retailReturn.getMemberId()) + .eq(RetailReturn::getId, retailReturn.getId()) + .in(RetailReturn::getStatus, statusList); + if (getBaseMapper().updateAllColumn(retailReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售退货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", retailReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.RETAIL, name = "审核通过零售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassRetailReturnVo vo) { + + RetailReturn retailReturn = getBaseMapper().selectById(vo.getId()); + if (retailReturn == null) { + throw new InputErrorException("零售退货单不存在!"); + } + + if (retailReturn.getStatus() != RetailReturnStatus.CREATED + && retailReturn.getStatus() != RetailReturnStatus.APPROVE_REFUSE) { + + if (retailReturn.getStatus() == RetailReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("零售退货单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("零售退货单无法审核通过!"); + } + + RetailConfig retailConfig = retailConfigService.get(); + + if (!retailConfig.getRetailReturnMultipleRelateOutStock()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(RetailReturn.class) + .eq(RetailReturn::getOutSheetId, retailReturn.getOutSheetId()) + .ne(RetailReturn::getId, retailReturn.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + RetailOutSheet retailOutSheet = retailOutSheetService.getById(retailReturn.getOutSheetId()); + throw new DefaultClientException( + "零售出库单号:" + retailOutSheet.getCode() + ",已关联其他零售退货单,不允许关联多个零售退货单!"); + } + } + + retailReturn.setStatus(RetailReturnStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(RetailReturnStatus.CREATED); + statusList.add(RetailReturnStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(RetailReturn.class) + .set(RetailReturn::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(RetailReturn::getApproveTime, LocalDateTime.now()) + .eq(RetailReturn::getId, retailReturn.getId()) + .in(RetailReturn::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(RetailReturn::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(retailReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售退货单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(retailReturn.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(retailReturn.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有支付方式,请检查!"); + } + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(RetailReturnDetail.class) + .eq(RetailReturnDetail::getReturnId, retailReturn.getId()) + .orderByAsc(RetailReturnDetail::getOrderNo); + List details = retailReturnDetailService.list(queryDetailWrapper); + for (RetailReturnDetail detail : details) { + ProductPurchase productPurchase = productPurchaseService.getById(detail.getProductId()); + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(detail.getProductId()); + addProductStockVo.setScId(retailReturn.getScId()); + addProductStockVo.setStockNum(detail.getReturnNum()); + addProductStockVo.setDefaultTaxPrice(productPurchase.getPrice()); + addProductStockVo.setBizId(retailReturn.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(retailReturn.getCode()); + addProductStockVo.setBizType(ProductStockBizType.RETAIL_RETURN.getCode()); + + productStockService.addStock(addProductStockVo); + } + + this.sendApprovePassEvent(retailReturn); + + OpLogUtil.setVariable("code", retailReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassRetailReturnVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassRetailReturnVo approvePassVo = new ApprovePassRetailReturnVo(); + approvePassVo.setId(id); + + try { + RetailReturnService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个零售退货单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateRetailReturnVo vo) { + + RetailReturnService thisService = getThis(this.getClass()); + + String returnId = thisService.create(vo); + + ApprovePassRetailReturnVo approvePassVo = new ApprovePassRetailReturnVo(); + approvePassVo.setId(returnId); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return returnId; + } + + @OpLog(type = ScOpLogType.RETAIL, name = "审核拒绝零售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseRetailReturnVo vo) { + + RetailReturn retailReturn = getBaseMapper().selectById(vo.getId()); + if (retailReturn == null) { + throw new InputErrorException("零售退货单不存在!"); + } + + if (retailReturn.getStatus() != RetailReturnStatus.CREATED) { + + if (retailReturn.getStatus() == RetailReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("零售退货单已审核通过,不允许继续执行审核!"); + } + + if (retailReturn.getStatus() == RetailReturnStatus.APPROVE_REFUSE) { + throw new DefaultClientException("零售退货单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("零售退货单无法审核拒绝!"); + } + + retailReturn.setStatus(RetailReturnStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(RetailReturn.class) + .set(RetailReturn::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(RetailReturn::getApproveTime, LocalDateTime.now()) + .set(RetailReturn::getRefuseReason, vo.getRefuseReason()) + .eq(RetailReturn::getId, retailReturn.getId()) + .eq(RetailReturn::getStatus, RetailReturnStatus.CREATED); + if (getBaseMapper().updateAllColumn(retailReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("零售退货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", retailReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseRetailReturnVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseRetailReturnVo approveRefuseVo = new ApproveRefuseRetailReturnVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + RetailReturnService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个零售退货单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.RETAIL, name = "删除零售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + RetailReturn retailReturn = getBaseMapper().selectById(id); + if (retailReturn == null) { + throw new InputErrorException("零售退货单不存在!"); + } + + if (retailReturn.getStatus() != RetailReturnStatus.CREATED + && retailReturn.getStatus() != RetailReturnStatus.APPROVE_REFUSE) { + + if (retailReturn.getStatus() == RetailReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的零售退货单不允许执行删除操作!"); + } + + throw new DefaultClientException("零售退货单无法删除!"); + } + + if (!StringUtil.isBlank(retailReturn.getOutSheetId())) { + //查询零售退货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + RetailReturnDetail.class) + .eq(RetailReturnDetail::getReturnId, retailReturn.getId()); + List details = retailReturnDetailService.list(queryDetailWrapper); + for (RetailReturnDetail detail : details) { + if (!StringUtil.isBlank(detail.getOutSheetDetailId())) { + //恢复已退货数量 + retailOutSheetDetailLotService.subReturnNum(detail.getOutSheetDetailId(), + detail.getReturnNum()); + } + } + } + + // 删除退货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(RetailReturnDetail.class) + .eq(RetailReturnDetail::getReturnId, retailReturn.getId()); + retailReturnDetailService.remove(deleteDetailWrapper); + + // 删除退货单 + getBaseMapper().deleteById(id); + + orderPayTypeService.deleteByOrderId(id); + + OpLogUtil.setVariable("code", retailReturn.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + RetailReturnService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个零售退货单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + private void create(RetailReturn retailReturn, CreateRetailReturnVo vo, boolean requireOut) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + retailReturn.setScId(vo.getScId()); + + Member member = null; + if (!StringUtil.isBlank(vo.getMemberId())) { + member = memberService.findById(vo.getMemberId()); + if (member == null) { + throw new InputErrorException("客户不存在!"); + } + retailReturn.setMemberId(vo.getMemberId()); + } else { + retailReturn.setMemberId(null); + } + + if (!StringUtil.isBlank(vo.getSalerId())) { + UserDto saler = userService.findById(vo.getSalerId()); + if (saler == null) { + throw new InputErrorException("零售员不存在!"); + } + + retailReturn.setSalerId(vo.getSalerId()); + } + + RetailConfig retailConfig = retailConfigService.get(); + + GetPaymentDateDto paymentDate = retailOutSheetService.getPaymentDate( + member == null ? null : member.getId()); + + retailReturn.setPaymentDate( + vo.getAllowModifyPaymentDate() || paymentDate.getAllowModify() ? vo.getPaymentDate() + : paymentDate.getPaymentDate()); + + if (requireOut) { + + RetailOutSheet retailOutSheet = retailOutSheetService.getById(vo.getOutSheetId()); + if (retailOutSheet == null) { + throw new DefaultClientException("零售出库单不存在!"); + } + + retailReturn.setScId(retailOutSheet.getScId()); + retailReturn.setMemberId(retailOutSheet.getMemberId()); + retailReturn.setOutSheetId(retailOutSheet.getId()); + + if (!retailConfig.getRetailReturnMultipleRelateOutStock()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(RetailReturn.class) + .eq(RetailReturn::getOutSheetId, retailOutSheet.getId()) + .ne(RetailReturn::getId, retailReturn.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException( + "零售出库单号:" + retailOutSheet.getCode() + ",已关联其他零售退货单,不允许关联多个零售退货单!"); + } + } + } + + int returnNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (RetailReturnProductVo productVo : vo.getProducts()) { + if (requireOut) { + if (!StringUtil.isBlank(productVo.getOutSheetDetailId())) { + RetailOutSheetDetailLotDto detailLot = retailOutSheetDetailLotService.findById( + productVo.getOutSheetDetailId()); + RetailOutSheetDetail detail = retailOutSheetDetailService.getById( + detailLot.getDetailId()); + productVo.setOriPrice(detail.getOriPrice()); + productVo.setTaxPrice(detail.getTaxPrice()); + productVo.setDiscountRate(detail.getDiscountRate()); + } else { + productVo.setTaxPrice(BigDecimal.ZERO); + productVo.setDiscountRate(BigDecimal.valueOf(100)); + } + } + + boolean isGift = productVo.getTaxPrice().doubleValue() == 0D; + + if (requireOut) { + if (StringUtil.isBlank(productVo.getOutSheetDetailId())) { + if (!isGift) { + throw new InputErrorException("第" + orderNo + "行商品必须为“赠品”!"); + } + } + } + + if (isGift) { + giftNum += productVo.getReturnNum(); + } else { + returnNum += productVo.getReturnNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getTaxPrice(), productVo.getReturnNum())); + + RetailReturnDetail detail = new RetailReturnDetail(); + detail.setId(IdUtil.getId()); + detail.setReturnId(retailReturn.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getTaxPrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品价格最多允许2位小数!"); + } + + detail.setProductId(productVo.getProductId()); + detail.setReturnNum(productVo.getReturnNum()); + detail.setOriPrice(productVo.getOriPrice()); + detail.setTaxPrice(productVo.getTaxPrice()); + detail.setDiscountRate(productVo.getDiscountRate()); + detail.setIsGift(isGift); + detail.setTaxRate(product.getSaleTaxRate()); + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + detail.setOrderNo(orderNo); + detail.setSettleStatus(this.getInitSettleStatus(member)); + if (requireOut && !StringUtil.isBlank(productVo.getOutSheetDetailId())) { + detail.setOutSheetDetailId(productVo.getOutSheetDetailId()); + retailOutSheetDetailLotService.addReturnNum(productVo.getOutSheetDetailId(), + detail.getReturnNum()); + } + + retailReturnDetailService.save(detail); + orderNo++; + } + retailReturn.setTotalNum(returnNum); + retailReturn.setTotalGiftNum(giftNum); + retailReturn.setTotalAmount(totalAmount); + retailReturn.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + retailReturn.setSettleStatus(this.getInitSettleStatus(member)); + + orderPayTypeService.create(retailReturn.getId(), vo.getPayTypes()); + } + + /** + * 根据客户获取初始结算状态 + * + * @param member + * @return + */ + private SettleStatus getInitSettleStatus(Member member) { + + return SettleStatus.UN_SETTLE; + } + + private void sendApprovePassEvent(RetailReturn r) { + + ApprovePassRetailReturnEvent event = new ApprovePassRetailReturnEvent(this); + event.setId(r.getId()); + event.setTotalAmount(r.getTotalAmount()); + event.setApproveTime(r.getApproveTime()); + + ApplicationUtil.publishEvent(event); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleConfigServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleConfigServiceImpl.java new file mode 100644 index 0000000..8b2b730 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleConfigServiceImpl.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.SaleConfigMapper; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.vo.sale.config.UpdateSaleConfigVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleConfigServiceImpl extends BaseMpServiceImpl + implements SaleConfigService { + + @Cacheable(value = SaleConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'", unless = "#result == null") + @Override + public SaleConfig get() { + + SaleConfig config = getBaseMapper().selectOne(Wrappers.query()); + + return config; + } + + @OpLog(type = ScOpLogType.SALE, name = "修改销售参数设置") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSaleConfigVo vo) { + + SaleConfig config = getBaseMapper().selectOne(Wrappers.query()); + config.setOutStockRequireSale(vo.getOutStockRequireSale()); + config.setOutStockMultipleRelateSale(vo.getOutStockMultipleRelateSale()); + config.setSaleReturnRequireOutStock(vo.getSaleReturnRequireOutStock()); + config.setSaleReturnMultipleRelateOutStock(vo.getSaleReturnMultipleRelateOutStock()); + config.setOutStockRequireLogistics(vo.getOutStockRequireLogistics()); + + getBaseMapper().updateById(config); + + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = SaleConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailBundleServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailBundleServiceImpl.java new file mode 100644 index 0000000..d07fac9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailBundleServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.SaleOrderDetailBundle; +import com.lframework.xingyun.sc.mappers.SaleOrderDetailBundleMapper; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailBundleService; +import org.springframework.stereotype.Service; + +@Service +public class SaleOrderDetailBundleServiceImpl extends + BaseMpServiceImpl + implements SaleOrderDetailBundleService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailServiceImpl.java new file mode 100644 index 0000000..2d1b25a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderDetailServiceImpl.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import com.lframework.xingyun.sc.mappers.SaleOrderDetailMapper; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailService; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleOrderDetailServiceImpl extends + BaseMpServiceImpl + implements SaleOrderDetailService { + + @Autowired + private ProductService productService; + + @Override + public List getByOrderId(String orderId) { + + return getBaseMapper().getByOrderId(orderId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addOutNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + SaleOrderDetail orderDetail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(orderDetail.getOrderNum(), orderDetail.getOutNum()) + .intValue(); + if (NumberUtil.lt(remainNum, num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余出库数量为" + remainNum + + "个,本次出库数量不允许大于" + + remainNum + "个!"); + } + + if (getBaseMapper().addOutNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余出库数量不足,不允许继续出库!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subOutNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + SaleOrderDetail orderDetail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(orderDetail.getOutNum(), num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已出库数量为" + orderDetail.getOutNum() + + "个,本次取消出库数量不允许大于" + orderDetail.getOutNum() + "个!"); + } + + if (getBaseMapper().subOutNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已出库数量不足,不允许取消出库!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderServiceImpl.java new file mode 100644 index 0000000..4c29c6b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOrderServiceImpl.java @@ -0,0 +1,997 @@ +package com.lframework.xingyun.sc.impl.sale; + +import cn.hutool.core.lang.Dict; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.order.impl.ApprovePassSaleOrderEvent; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import com.lframework.xingyun.core.utils.SplitNumberUtil; +import com.lframework.xingyun.sc.bo.sale.GetSaleOrderBo; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto; +import com.lframework.xingyun.sc.dto.sale.SaleOrderWithOutDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import com.lframework.xingyun.sc.entity.SaleOrderDetailBundle; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import com.lframework.xingyun.sc.enums.RetailOutSheetStatus; +import com.lframework.xingyun.sc.enums.SaleOrderStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.SaleOrderMapper; +import com.lframework.xingyun.sc.service.paytype.OrderPayTypeService; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailBundleService; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.utils.WebUtils; +import com.lframework.xingyun.sc.vo.purchase.ApprovePassPurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.ApproveRefusePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.sale.ApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.ApproveRefuseSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.BatchApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.BatchApproveRefuseSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.CreateSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderWithOutVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleProductVo; +import com.lframework.xingyun.sc.vo.sale.SaleOrderSelectorVo; +import com.lframework.xingyun.sc.vo.sale.SaleProductVo; +import com.lframework.xingyun.sc.vo.sale.UpdateSaleOrderVo; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import net.minidev.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleOrderServiceImpl extends BaseMpServiceImpl implements + SaleOrderService { + + @Autowired + private SaleOrderDetailService saleOrderDetailService; + + @Autowired + private SaleOrderDetailBundleService saleOrderDetailBundleService; + + @Autowired + private ProductBundleService productBundleService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private CustomerService customerService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private SaleConfigService saleConfigService; + + @Autowired + private OrderPayTypeService orderPayTypeService; + + @Autowired + private UserDetailsService userDetailsService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySaleOrderVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySaleOrderVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SaleOrderSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public SaleOrderFullDto getDetail(String id) { + + SaleOrderFullDto order = getBaseMapper().getDetail(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + return order; + } + + @Override + public SaleOrderWithOutDto getWithOut(String id) { + + SaleConfig saleConfig = saleConfigService.get(); + + SaleOrderWithOutDto order = getBaseMapper().getWithOut(id, saleConfig.getOutStockRequireSale()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + return order; + } + + @Override + public PageResult queryWithOut(Integer pageIndex, Integer pageSize, + QuerySaleOrderWithOutVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + SaleConfig saleConfig = saleConfigService.get(); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryWithOut(vo, + saleConfig.getOutStockMultipleRelateSale()); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = ScOpLogType.SALE, name = "创建销售订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建订单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSaleOrderVo vo) { + + SaleOrder order = new SaleOrder(); + order.setId(IdUtil.getId()); + order.setCode(generateCodeService.generate(GenerateCodeTypePool.SALE_ORDER)); + + this.create(order, vo); + + order.setStatus(SaleOrderStatus.CREATED); + + getBaseMapper().insert(order); + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + + return order.getId(); + } + + @OpLog(type = ScOpLogType.SALE, name = "修改销售订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改订单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSaleOrderVo vo) { + + SaleOrder order = getBaseMapper().selectById(vo.getId()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != SaleOrderStatus.CREATED + && order.getStatus() != SaleOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,无法修改!"); + } + + throw new DefaultClientException("订单无法修改!"); + } + + // 删除订单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SaleOrderDetail.class) + .eq(SaleOrderDetail::getOrderId, order.getId()); + saleOrderDetailService.remove(deleteDetailWrapper); + + // 删除组合商品信息 + Wrapper deleteDetailBundleWrapper = Wrappers.lambdaQuery( + SaleOrderDetailBundle.class).eq(SaleOrderDetailBundle::getOrderId, order.getId()); + saleOrderDetailBundleService.remove(deleteDetailBundleWrapper); + + this.create(order, vo); + + order.setStatus(SaleOrderStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SaleOrderStatus.CREATED); + statusList.add(SaleOrderStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getApproveBy, null).set(SaleOrder::getApproveTime, null) + .set(SaleOrder::getRefuseReason, StringPool.EMPTY_STR).eq(SaleOrder::getId, order.getId()) + .in(SaleOrder::getStatus, statusList); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.SALE, name = "审核通过销售订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSaleOrderVo vo) { + + SaleOrder order = getBaseMapper().selectById(vo.getId()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != SaleOrderStatus.CREATED + && order.getStatus() != SaleOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核通过!"); + } + + order.setStatus(SaleOrderStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(SaleOrderStatus.CREATED); + statusList.add(SaleOrderStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(SaleOrder::getApproveTime, LocalDateTime.now()).eq(SaleOrder::getId, order.getId()) + .in(SaleOrder::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(SaleOrder::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(order.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(order.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有约定支付,请检查!"); + } + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SaleOrderDetail.class) + .eq(SaleOrderDetail::getOrderId, order.getId()) + .orderByAsc(SaleOrderDetail::getOrderNo); + List details = saleOrderDetailService.list(queryDetailWrapper); + + int totalNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + + for (SaleOrderDetail detail : details) { + boolean isGift = detail.getIsGift(); + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(detail.getTaxPrice(), detail.getOrderNum())); + + Product product = productService.findById(detail.getProductId()); + if (product.getProductType() == ProductType.NORMAL) { + if (isGift) { + giftNum += detail.getOrderNum(); + } else { + totalNum += detail.getOrderNum(); + } + } else { + Wrapper queryBundleWrapper = Wrappers.lambdaQuery( + SaleOrderDetailBundle.class).eq(SaleOrderDetailBundle::getOrderId, order.getId()) + .eq(SaleOrderDetailBundle::getDetailId, detail.getId()); + List saleOrderDetailBundles = saleOrderDetailBundleService.list( + queryBundleWrapper); + Assert.notEmpty(saleOrderDetailBundles); + + for (SaleOrderDetailBundle saleOrderDetailBundle : saleOrderDetailBundles) { + SaleOrderDetail newDetail = new SaleOrderDetail(); + newDetail.setId(IdUtil.getId()); + newDetail.setOrderId(order.getId()); + newDetail.setProductId(saleOrderDetailBundle.getProductId()); + newDetail.setOrderNum(saleOrderDetailBundle.getProductOrderNum()); + newDetail.setOriPrice(saleOrderDetailBundle.getProductOriPrice()); + newDetail.setTaxPrice(saleOrderDetailBundle.getProductTaxPrice()); + newDetail.setDiscountRate(detail.getDiscountRate()); + newDetail.setIsGift(detail.getIsGift()); + newDetail.setTaxRate(saleOrderDetailBundle.getProductTaxRate()); + newDetail.setDescription(detail.getDescription()); + newDetail.setOrderNo(detail.getOrderNo()); + newDetail.setOriBundleDetailId(detail.getId()); + + saleOrderDetailService.save(newDetail); + saleOrderDetailService.removeById(detail.getId()); + + saleOrderDetailBundle.setProductDetailId(newDetail.getId()); + saleOrderDetailBundleService.updateById(saleOrderDetailBundle); + + if (isGift) { + giftNum += newDetail.getOrderNum(); + } else { + totalNum += newDetail.getOrderNum(); + } + } + } + } + + // 这里需要重新统计明细信息,因为明细发生变动了 + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getTotalNum, totalNum).set(SaleOrder::getTotalGiftNum, giftNum) + .set(SaleOrder::getTotalAmount, totalAmount).eq(SaleOrder::getId, order.getId()); + this.update(updateWrapper); + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + + this.sendApprovePassEvent(order); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSaleOrderVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSaleOrderVo approvePassSaleOrderVo = new ApprovePassSaleOrderVo(); + approvePassSaleOrderVo.setId(id); + + try { + SaleOrderService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassSaleOrderVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售订单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSaleOrderVo vo) { + + SaleOrderService thisService = getThis(this.getClass()); + + String orderId = thisService.create(vo); + + ApprovePassSaleOrderVo approvePassSaleOrderVo = new ApprovePassSaleOrderVo(); + approvePassSaleOrderVo.setId(orderId); + approvePassSaleOrderVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassSaleOrderVo); + + return orderId; + } + + @OpLog(type = ScOpLogType.SALE, name = "审核拒绝销售订单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSaleOrderVo vo) { + + SaleOrder order = getBaseMapper().selectById(vo.getId()); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != SaleOrderStatus.CREATED) { + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + if (order.getStatus() == SaleOrderStatus.APPROVE_REFUSE) { + throw new DefaultClientException("订单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核拒绝!"); + } + + order.setStatus(SaleOrderStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(SaleOrder::getApproveTime, LocalDateTime.now()) + .set(SaleOrder::getRefuseReason, vo.getRefuseReason()).eq(SaleOrder::getId, order.getId()) + .eq(SaleOrder::getStatus, SaleOrderStatus.CREATED); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSaleOrderVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSaleOrderVo approveRefuseSaleOrderVo = new ApproveRefuseSaleOrderVo(); + approveRefuseSaleOrderVo.setId(id); + approveRefuseSaleOrderVo.setRefuseReason(vo.getRefuseReason()); + + try { + SaleOrderService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseSaleOrderVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售订单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.SALE, name = "删除销售订单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SaleOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != SaleOrderStatus.CREATED + && order.getStatus() != SaleOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的销售单据不允许执行删除操作!"); + } + + throw new DefaultClientException("订单无法删除!"); + } + + // 删除订单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SaleOrderDetail.class) + .eq(SaleOrderDetail::getOrderId, order.getId()); + saleOrderDetailService.remove(deleteDetailWrapper); + + // 删除组合商品信息 + Wrapper deleteDetailBundleWrapper = Wrappers.lambdaQuery( + SaleOrderDetailBundle.class).eq(SaleOrderDetailBundle::getOrderId, order.getId()); + saleOrderDetailBundleService.remove(deleteDetailBundleWrapper); + + // 删除订单 + getBaseMapper().deleteById(id); + + orderPayTypeService.deleteByOrderId(id); + + OpLogUtil.setVariable("code", order.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SaleOrderService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售订单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Override + public PageResult querySaleByCondition(Integer pageIndex, Integer pageSize, + String condition, Boolean isReturn) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().querySaleByCondition(condition, + isReturn); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult querySaleList(Integer pageIndex, Integer pageSize, + QuerySaleProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().querySaleList(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public SaleProductDto getSaleById(String id) { + + SaleProductDto data = getBaseMapper().getSaleById(id); + + return data; + } + @OpLog(type = ScOpLogType.SALE, name = "发送销售订单审批流程给ydool系统,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_SEND, orderId = "#id", name = "发送销售订单审批流程给ydool系统") + @Transactional(rollbackFor = Exception.class) + @Override + public InvokeResult sendApprove(String id) { + SaleOrderFullDto order = getBaseMapper().getDetail(id); + if (order == null) { + throw new InputErrorException("销售订单不存在!"); + } + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("销售订单已审核通过,无需再次审核!"); + } + if (order.getStatus() == SaleOrderStatus.APPROVE_ING) { + throw new DefaultClientException("销售订单正在审核中,请勿重复推送"); + } + + GetSaleOrderBo result = new GetSaleOrderBo(order); + + String salerCode = result.getSalerCode(); + + if (StringUtil.isBlank(salerCode)) { + throw new DefaultClientException("销售员不存在,无法发起审核!"); + } + + List details = result.getDetails(); + + List list = details.stream().map(detail -> { + return Dict.create() + .set("goods_number", detail.getProductCode()) + .set("goods_name", detail.getProductName()) + .set("number", detail.getOrderNum()) + .set("money", new BigDecimal(detail.getOrderNum()).multiply(detail.getTaxPrice())); + }).collect(Collectors.toList()); + Dict dict = Dict.create(); + dict.set("user_id", salerCode) + .set("order_id", id) + .set("all_money", result.getTotalAmount()) + .set("customer", result.getCustomerName()) + .set("audit_person_ids", "120,262") + .set("push_person_ids", "120,262") + .set("remark", result.getDescription()) + .set("ghd_goodlist_info", list); + String jsonString = JSONObject.toJSONString(dict); + String json = HttpUtil.post("https://nb.ydool.com/api/ydoolerp/erp_ajax.ashx/send_xs", jsonString); + // 修改订单状态 + SaleOrder saleOrder = getById(id); + saleOrder.setStatus(SaleOrderStatus.APPROVE_ING); + int update = getBaseMapper().updateById(saleOrder); + InvokeResult success = InvokeResultBuilder.success(); + success.setMsg(jsonString); + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setVariable("id", id); + OpLogUtil.setExtra(dict); + return update > 0 ? success : InvokeResultBuilder.fail(jsonString); + } + @Transactional(rollbackFor = Exception.class) + @Override + public void approve(YdoolApproveOrderVo vo) { + String status = vo.getStatus(); + if ("y".equals(status)) { + this.approvePass(vo.getId(), vo.getMsg()); + } else { + this.approveRefuse(vo.getId(), vo.getMsg()); + } + } + + private void create(SaleOrder order, CreateSaleOrderVo vo) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + order.setScId(vo.getScId()); + + Customer customer = customerService.findById(vo.getCustomerId()); + if (customer == null) { + throw new InputErrorException("客户不存在!"); + } + order.setCustomerId(vo.getCustomerId()); + + if (!StringUtil.isBlank(vo.getSalerId())) { + UserDto saler = userService.findById(vo.getSalerId()); + if (saler == null) { + throw new InputErrorException("销售员不存在!"); + } + + order.setSalerId(vo.getSalerId()); + } + + int totalNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (SaleProductVo productVo : vo.getProducts()) { + + boolean isGift = productVo.getTaxPrice().doubleValue() == 0D; + + if (isGift) { + giftNum += productVo.getOrderNum(); + } else { + totalNum += productVo.getOrderNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getTaxPrice(), productVo.getOrderNum())); + + SaleOrderDetail orderDetail = new SaleOrderDetail(); + orderDetail.setId(IdUtil.getId()); + orderDetail.setOrderId(order.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getTaxPrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品价格最多允许2位小数!"); + } + + orderDetail.setProductId(productVo.getProductId()); + orderDetail.setOrderNum(productVo.getOrderNum()); + orderDetail.setOriPrice(productVo.getOriPrice()); + orderDetail.setDiscountRate(productVo.getDiscountRate()); + orderDetail.setTaxPrice(productVo.getTaxPrice()); + orderDetail.setIsGift(isGift); + orderDetail.setTaxRate(product.getSaleTaxRate()); + orderDetail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + orderDetail.setOrderNo(orderNo); + + saleOrderDetailService.save(orderDetail); + + // 这里处理组合商品 + if (product.getProductType() == ProductType.BUNDLE) { + List productBundles = productBundleService.getByMainProductId( + product.getId()); + // 构建指标项 + Map bundleWeight = new HashMap<>(productBundles.size()); + for (ProductBundle productBundle : productBundles) { + bundleWeight.put(productBundle.getProductId(), + NumberUtil.mul(productBundle.getSalePrice(), productBundle.getBundleNum())); + } + Map splitPriceMap = SplitNumberUtil.split(orderDetail.getTaxPrice(), + bundleWeight, 2); + List saleOrderDetailBundles = productBundles.stream() + .map(productBundle -> { + Product bundle = productService.findById(productBundle.getProductId()); + SaleOrderDetailBundle saleOrderDetailBundle = new SaleOrderDetailBundle(); + saleOrderDetailBundle.setId(IdUtil.getId()); + saleOrderDetailBundle.setOrderId(order.getId()); + saleOrderDetailBundle.setDetailId(orderDetail.getId()); + saleOrderDetailBundle.setMainProductId(product.getId()); + saleOrderDetailBundle.setOrderNum(orderDetail.getOrderNum()); + saleOrderDetailBundle.setProductId(productBundle.getProductId()); + saleOrderDetailBundle.setProductOrderNum( + NumberUtil.mul(orderDetail.getOrderNum(), productBundle.getBundleNum()) + .intValue()); + saleOrderDetailBundle.setProductOriPrice(productBundle.getSalePrice()); + // 这里会有尾差 + saleOrderDetailBundle.setProductTaxPrice(NumberUtil.getNumber(NumberUtil.div( + BigDecimal.valueOf( + splitPriceMap.get(productBundle.getProductId()).doubleValue()), productBundle.getBundleNum()), 2)); + saleOrderDetailBundle.setProductTaxRate(bundle.getSaleTaxRate()); + + return saleOrderDetailBundle; + }).collect(Collectors.toList()); + + saleOrderDetailBundleService.saveBatch(saleOrderDetailBundles); + } + orderNo++; + } + order.setTotalNum(totalNum); + order.setTotalGiftNum(giftNum); + order.setTotalAmount(totalAmount); + order.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + orderPayTypeService.create(order.getId(), vo.getPayTypes()); + } + + private void sendApprovePassEvent(SaleOrder order) { + + ApprovePassSaleOrderEvent event = new ApprovePassSaleOrderEvent(this); + event.setId(order.getId()); + event.setTotalAmount(order.getTotalAmount()); + event.setApproveTime(order.getApproveTime()); + + ApplicationUtil.publishEvent(event); + } + + + @Transactional(rollbackFor = Exception.class) + public void approvePass(String id, String description) { + + SaleOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + if (order.getStatus() != SaleOrderStatus.APPROVE_ING) { + throw new DefaultClientException("订单无法审核通过!"); + } + + if (order.getStatus() != SaleOrderStatus.CREATED + && order.getStatus() != SaleOrderStatus.APPROVE_ING + && order.getStatus() != SaleOrderStatus.APPROVE_REFUSE) { + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核通过!"); + } + + order.setStatus(SaleOrderStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(SaleOrderStatus.APPROVE_ING); + + + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getApproveBy, user.getId()) + .set(SaleOrder::getApproveTime, LocalDateTime.now()).eq(SaleOrder::getId, order.getId()) + .in(SaleOrder::getStatus, statusList); + if (!StringUtil.isBlank(description)) { + updateOrderWrapper.set(SaleOrder::getDescription, description); + } + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + if (NumberUtil.gt(order.getTotalAmount(), BigDecimal.ZERO)) { + List orderPayTypes = orderPayTypeService.findByOrderId(order.getId()); + if (CollectionUtil.isEmpty(orderPayTypes)) { + throw new DefaultClientException("单据没有约定支付,请检查!"); + } + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SaleOrderDetail.class) + .eq(SaleOrderDetail::getOrderId, order.getId()) + .orderByAsc(SaleOrderDetail::getOrderNo); + List details = saleOrderDetailService.list(queryDetailWrapper); + + int totalNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + + for (SaleOrderDetail detail : details) { + boolean isGift = detail.getIsGift(); + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(detail.getTaxPrice(), detail.getOrderNum())); + + Product product = productService.findById(detail.getProductId()); + if (product.getProductType() == ProductType.NORMAL) { + if (isGift) { + giftNum += detail.getOrderNum(); + } else { + totalNum += detail.getOrderNum(); + } + } else { + Wrapper queryBundleWrapper = Wrappers.lambdaQuery( + SaleOrderDetailBundle.class).eq(SaleOrderDetailBundle::getOrderId, order.getId()) + .eq(SaleOrderDetailBundle::getDetailId, detail.getId()); + List saleOrderDetailBundles = saleOrderDetailBundleService.list( + queryBundleWrapper); + Assert.notEmpty(saleOrderDetailBundles); + + for (SaleOrderDetailBundle saleOrderDetailBundle : saleOrderDetailBundles) { + SaleOrderDetail newDetail = new SaleOrderDetail(); + newDetail.setId(IdUtil.getId()); + newDetail.setOrderId(order.getId()); + newDetail.setProductId(saleOrderDetailBundle.getProductId()); + newDetail.setOrderNum(saleOrderDetailBundle.getProductOrderNum()); + newDetail.setOriPrice(saleOrderDetailBundle.getProductOriPrice()); + newDetail.setTaxPrice(saleOrderDetailBundle.getProductTaxPrice()); + newDetail.setDiscountRate(detail.getDiscountRate()); + newDetail.setIsGift(detail.getIsGift()); + newDetail.setTaxRate(saleOrderDetailBundle.getProductTaxRate()); + newDetail.setDescription(detail.getDescription()); + newDetail.setOrderNo(detail.getOrderNo()); + newDetail.setOriBundleDetailId(detail.getId()); + + saleOrderDetailService.save(newDetail); + saleOrderDetailService.removeById(detail.getId()); + + saleOrderDetailBundle.setProductDetailId(newDetail.getId()); + saleOrderDetailBundleService.updateById(saleOrderDetailBundle); + + if (isGift) { + giftNum += newDetail.getOrderNum(); + } else { + totalNum += newDetail.getOrderNum(); + } + } + } + } + + // 这里需要重新统计明细信息,因为明细发生变动了 + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getTotalNum, totalNum).set(SaleOrder::getTotalGiftNum, giftNum) + .set(SaleOrder::getTotalAmount, totalAmount).eq(SaleOrder::getId, order.getId()); + this.update(updateWrapper); + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApprovePassSaleOrderVo vo = new ApprovePassSaleOrderVo(); + vo.setId(id); + vo.setDescription(description); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核通过销售订单,单号:%s", order.getCode())); + opLogs.setLogType(ScOpLogType.SALE); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(order.getId()); + orderTimeLine.setContent("审核通过"); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_PASS); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + + this.sendApprovePassEvent(order); + } + + + @Transactional(rollbackFor = Exception.class) + public void approveRefuse(String id, String refuseReason) { + + if (StringUtil.isBlank(refuseReason)) { + throw new InputErrorException("请输入拒绝理由!"); + } + + SaleOrder order = getBaseMapper().selectById(id); + if (order == null) { + throw new InputErrorException("订单不存在!"); + } + + if (order.getStatus() != SaleOrderStatus.APPROVE_ING) { + + if (order.getStatus() == SaleOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("订单已审核通过,不允许继续执行审核!"); + } + + if (order.getStatus() == SaleOrderStatus.APPROVE_REFUSE) { + throw new DefaultClientException("订单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("订单无法审核拒绝!"); + } + + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + order.setStatus(SaleOrderStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOrder.class) + .set(SaleOrder::getApproveBy, user.getId()) + .set(SaleOrder::getApproveTime, LocalDateTime.now()) + .set(SaleOrder::getRefuseReason, refuseReason).eq(SaleOrder::getId, order.getId()) + .eq(SaleOrder::getStatus, SaleOrderStatus.APPROVE_ING); + if (getBaseMapper().updateAllColumn(order, updateOrderWrapper) != 1) { + throw new DefaultClientException("订单信息已过期,请刷新重试!"); + } + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApproveRefusePurchaseOrderVo vo = new ApproveRefusePurchaseOrderVo(); + vo.setId(id); + vo.setRefuseReason(refuseReason); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核拒绝销售订单,单号:%s", order.getCode())); + opLogs.setLogType(ScOpLogType.SALE); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(order.getId()); + orderTimeLine.setContent(String.format("审核拒绝,拒绝理由:%s", refuseReason)); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_RETURN); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailBundleServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailBundleServiceImpl.java new file mode 100644 index 0000000..a0f74d2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailBundleServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailBundle; +import com.lframework.xingyun.sc.mappers.SaleOutSheetDetailBundleMapper; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailBundleService; +import org.springframework.stereotype.Service; + +@Service +public class SaleOutSheetDetailBundleServiceImpl extends + BaseMpServiceImpl + implements SaleOutSheetDetailBundleService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailLotServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailLotServiceImpl.java new file mode 100644 index 0000000..5789e95 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailLotServiceImpl.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailLot; +import com.lframework.xingyun.sc.mappers.SaleOutSheetDetailLotMapper; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleOutSheetDetailLotServiceImpl + extends BaseMpServiceImpl + implements SaleOutSheetDetailLotService { + + @Autowired + private ProductService productService; + + @Autowired + private SaleOutSheetDetailService saleOutSheetDetailService; + + @Override + public SaleOutSheetDetailLotDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + SaleOutSheetDetailLot detail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(detail.getOrderNum(), detail.getReturnNum()).intValue(); + if (NumberUtil.lt(remainNum, num)) { + SaleOutSheetDetail sheetDetail = saleOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量为" + remainNum + + "个,本次退货数量不允许大于" + + remainNum + "个!"); + } + + if (getBaseMapper().addReturnNum(detail.getId(), num) != 1) { + SaleOutSheetDetail sheetDetail = saleOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量不足,不允许继续退货!"); + } + + saleOutSheetDetailService.addReturnNum(detail.getDetailId(), num); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + SaleOutSheetDetailLot detail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(detail.getReturnNum(), num)) { + SaleOutSheetDetail sheetDetail = saleOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量为" + detail.getReturnNum() + + "个,本次取消退货数量不允许大于" + detail.getReturnNum() + "个!"); + } + + if (getBaseMapper().subReturnNum(detail.getId(), num) != 1) { + SaleOutSheetDetail sheetDetail = saleOutSheetDetailService.getById(detail.getDetailId()); + + Product product = productService.findById(sheetDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量不足,不允许取消退货!"); + } + + saleOutSheetDetailService.subReturnNum(detail.getDetailId(), num); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailServiceImpl.java new file mode 100644 index 0000000..8a257f0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetDetailServiceImpl.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailBundle; +import com.lframework.xingyun.sc.mappers.SaleOutSheetDetailMapper; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailBundleService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailService; +import java.math.BigDecimal; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleOutSheetDetailServiceImpl extends + BaseMpServiceImpl + implements SaleOutSheetDetailService { + + @Autowired + private ProductService productService; + + @Autowired + private SaleOutSheetDetailBundleService saleOutSheetDetailBundleService; + + @Override + public List getBySheetId(String sheetId) { + + return getBaseMapper().getBySheetId(sheetId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + SaleOutSheetDetail detail = getBaseMapper().selectById(id); + + Integer remainNum = NumberUtil.sub(detail.getOrderNum(), detail.getReturnNum()).intValue(); + if (NumberUtil.lt(remainNum, num)) { + Product product = productService.findById(detail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量为" + remainNum + + "个,本次退货数量不允许大于" + + remainNum + "个!"); + } + + if (getBaseMapper().addReturnNum(detail.getId(), num) != 1) { + Product product = productService.findById(detail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "剩余退货数量不足,不允许继续退货!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void subReturnNum(String id, Integer num) { + + Assert.notBlank(id); + Assert.greaterThanZero(num); + + SaleOutSheetDetail orderDetail = getBaseMapper().selectById(id); + + if (NumberUtil.lt(orderDetail.getReturnNum(), num)) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量为" + + orderDetail.getReturnNum() + + "个,本次取消退货数量不允许大于" + orderDetail.getReturnNum() + "个!"); + } + + if (getBaseMapper().subReturnNum(orderDetail.getId(), num) != 1) { + Product product = productService.findById(orderDetail.getProductId()); + + throw new DefaultClientException( + "(" + product.getCode() + ")" + product.getName() + "已退货数量不足,不允许取消退货!"); + } + } + + @Override + public BigDecimal getTotalWeightBySheetIds(List sheetIds) { + if (CollectionUtil.isEmpty(sheetIds)) { + return BigDecimal.ZERO; + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(SaleOutSheetDetail.class) + .in(SaleOutSheetDetail::getSheetId, sheetIds); + List details = this.list(queryWrapper); + BigDecimal sumWeight = details.stream().map(t -> { + Product product = productService.findById(t.getProductId()); + if (product.getProductType() == ProductType.BUNDLE) { + Wrapper detailBundleWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetailBundle.class).eq(SaleOutSheetDetailBundle::getDetailId, t.getId()); + List detailBundles = saleOutSheetDetailBundleService.list( + detailBundleWrapper); + return detailBundles.stream().map(b -> { + Product targetProduct = productService.findById(b.getProductId()); + if (targetProduct.getWeight() == null) { + throw new DefaultClientException( + "商品(" + targetProduct.getCode() + ")" + targetProduct.getName() + + "尚未设置重量,请检查!"); + } + + return NumberUtil.mul(targetProduct.getWeight(), b.getProductOrderNum()); + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + } else { + if (product.getWeight() == null) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "尚未设置重量,请检查!"); + } + return NumberUtil.mul(t.getOrderNum(), product.getWeight()); + } + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + + return sumWeight; + } + + @Override + public BigDecimal getTotalVolumeBySheetIds(List sheetIds) { + if (CollectionUtil.isEmpty(sheetIds)) { + return BigDecimal.ZERO; + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(SaleOutSheetDetail.class) + .in(SaleOutSheetDetail::getSheetId, sheetIds); + List details = this.list(queryWrapper); + BigDecimal sumVolume = details.stream().map(t -> { + Product product = productService.findById(t.getProductId()); + if (product.getProductType() == ProductType.BUNDLE) { + Wrapper detailBundleWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetailBundle.class).eq(SaleOutSheetDetailBundle::getDetailId, t.getId()); + List detailBundles = saleOutSheetDetailBundleService.list( + detailBundleWrapper); + return detailBundles.stream().map(b -> { + Product targetProduct = productService.findById(b.getProductId()); + if (targetProduct.getVolume() == null) { + throw new DefaultClientException( + "商品(" + targetProduct.getCode() + ")" + targetProduct.getName() + + "尚未设置体积,请检查!"); + } + + return NumberUtil.mul(targetProduct.getVolume(), b.getProductOrderNum()); + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + } else { + if (product.getVolume() == null) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "尚未设置体积,请检查!"); + } + return NumberUtil.mul(t.getOrderNum(), product.getVolume()); + } + }).reduce(NumberUtil::add).orElse(BigDecimal.ZERO); + + return sumVolume; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetServiceImpl.java new file mode 100644 index 0000000..3b2b1c3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleOutSheetServiceImpl.java @@ -0,0 +1,939 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.enums.SettleType; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.utils.SplitNumberUtil; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetFullDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.LogisticsSheetDetail; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import com.lframework.xingyun.sc.entity.SaleOrderDetailBundle; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailBundle; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailLot; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.SaleOutSheetStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.mappers.SaleOutSheetMapper; +import com.lframework.xingyun.sc.service.logistics.LogisticsSheetDetailService; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailBundleService; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOrderService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailBundleService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.sale.out.ApprovePassSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.ApproveRefuseSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.BatchApprovePassSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.BatchApproveRefuseSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.CreateSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.sale.out.SaleOutProductVo; +import com.lframework.xingyun.sc.vo.sale.out.SaleOutSheetSelectorVo; +import com.lframework.xingyun.sc.vo.sale.out.UpdateSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleOutSheetServiceImpl extends BaseMpServiceImpl + implements SaleOutSheetService { + + @Autowired + private SaleOutSheetDetailService saleOutSheetDetailService; + + @Autowired + private SaleOutSheetDetailLotService saleOutSheetDetailLotService; + + @Autowired + private SaleOutSheetDetailBundleService saleOutSheetDetailBundleService; + + @Autowired + private SaleOrderDetailBundleService saleOrderDetailBundleService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private CustomerService customerService; + + @Autowired + private UserService userService; + + @Autowired + private SaleOrderService saleOrderService; + + @Autowired + private ProductService productService; + + @Autowired + private ProductBundleService productBundleService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private SaleConfigService saleConfigService; + + @Autowired + private SaleOrderDetailService saleOrderDetailService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private LogisticsSheetDetailService logisticsSheetDetailService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySaleOutSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySaleOutSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SaleOutSheetSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public GetPaymentDateDto getPaymentDate(String customerId) { + + //默认为当前日期的30天后,如当天为2021-10-01,则付款日期默认为2021-11-01 + //(1)客户的结账方式为“任意指定”,则付款日期按照以上规则展示默认值,允许用户更改,但仅能选择当天及当天之后的日期。 + //(2)客户的结账方式为“货到付款”(这个参数的名字后期会改,如“货销付款”),则付款日期默认为此刻,且不允许修改,即出库单的创建时间,可能会遇到跨日的问题,但付款日期,均赋值为出库单的创建日期。 + + Customer customer = customerService.findById(customerId); + + GetPaymentDateDto result = new GetPaymentDateDto(); + result.setAllowModify(customer.getSettleType() == SettleType.ARBITRARILY); + + if (customer.getSettleType() == SettleType.ARBITRARILY) { + result.setPaymentDate(LocalDate.now().plusMonths(1)); + } else if (customer.getSettleType() == SettleType.CASH_ON_DELIVERY) { + result.setPaymentDate(LocalDate.now()); + } + + return result; + } + + @Override + public SaleOutSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @Override + public SaleOutSheetWithReturnDto getWithReturn(String id) { + + SaleConfig saleConfig = saleConfigService.get(); + + SaleOutSheetWithReturnDto sheet = getBaseMapper().getWithReturn(id, + saleConfig.getSaleReturnRequireOutStock()); + if (sheet == null) { + throw new InputErrorException("销售出库单不存在!"); + } + + return sheet; + } + + @Override + public PageResult queryWithReturn(Integer pageIndex, Integer pageSize, + QuerySaleOutSheetWithReturnVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + SaleConfig saleConfig = saleConfigService.get(); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryWithReturn(vo, + saleConfig.getSaleReturnMultipleRelateOutStock()); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = ScOpLogType.SALE, name = "创建销售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建出库单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSaleOutSheetVo vo) { + + SaleOutSheet sheet = new SaleOutSheet(); + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.SALE_OUT_SHEET)); + + SaleConfig saleConfig = saleConfigService.get(); + + this.create(sheet, vo, saleConfig.getOutStockRequireSale()); + + sheet.setStatus(SaleOutSheetStatus.CREATED); + + getBaseMapper().insert(sheet); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + return sheet.getId(); + } + + @OpLog(type = ScOpLogType.SALE, name = "修改销售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改出库单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSaleOutSheetVo vo) { + + SaleOutSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("销售出库单不存在!"); + } + + if (sheet.getStatus() != SaleOutSheetStatus.CREATED + && sheet.getStatus() != SaleOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SaleOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("销售出库单已审核通过,无法修改!"); + } + + throw new DefaultClientException("销售出库单无法修改!"); + } + + boolean requireSale = !StringUtil.isBlank(sheet.getSaleOrderId()); + + if (requireSale) { + //查询出库单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetail.class) + .eq(SaleOutSheetDetail::getSheetId, sheet.getId()); + List details = saleOutSheetDetailService.list(queryDetailWrapper); + for (SaleOutSheetDetail detail : details) { + if (!StringUtil.isBlank(detail.getSaleOrderDetailId())) { + //先恢复已出库数量 + saleOrderDetailService.subOutNum(detail.getSaleOrderDetailId(), detail.getOrderNum()); + } + } + } + + // 删除出库单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SaleOutSheetDetail.class) + .eq(SaleOutSheetDetail::getSheetId, sheet.getId()); + saleOutSheetDetailService.remove(deleteDetailWrapper); + + // 删除组合商品信息 + Wrapper deleteDetailBundleWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetailBundle.class).eq(SaleOutSheetDetailBundle::getSheetId, sheet.getId()); + saleOutSheetDetailBundleService.remove(deleteDetailBundleWrapper); + + this.create(sheet, vo, requireSale); + + sheet.setStatus(SaleOutSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SaleOutSheetStatus.CREATED); + statusList.add(SaleOutSheetStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getApproveBy, null).set(SaleOutSheet::getApproveTime, null) + .set(SaleOutSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(SaleOutSheet::getId, sheet.getId()) + .in(SaleOutSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("销售出库单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.SALE, name = "审核通过销售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSaleOutSheetVo vo) { + + SaleOutSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("销售出库单不存在!"); + } + + if (sheet.getStatus() != SaleOutSheetStatus.CREATED + && sheet.getStatus() != SaleOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SaleOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("销售出库单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("销售出库单无法审核通过!"); + } + + SaleConfig saleConfig = saleConfigService.get(); + + if (!saleConfig.getOutStockMultipleRelateSale()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SaleOutSheet.class) + .eq(SaleOutSheet::getSaleOrderId, sheet.getSaleOrderId()) + .ne(SaleOutSheet::getId, sheet.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + SaleOrder purchaseOrder = saleOrderService.getById(sheet.getSaleOrderId()); + throw new DefaultClientException( + "销售订单号:" + purchaseOrder.getCode() + + ",已关联其他销售出库单,不允许关联多个销售出库单!"); + } + } + + if (saleConfig.getOutStockRequireLogistics()) { + // 关联物流单 + LogisticsSheetDetail logisticsSheetDetail = logisticsSheetDetailService.getByBizId( + sheet.getId(), LogisticsSheetDetailBizType.SALE_OUT_SHEET); + if (logisticsSheetDetail == null) { + throw new DefaultClientException("销售出库单尚未发货,无法审核通过!"); + } + } + + sheet.setStatus(SaleOutSheetStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(SaleOutSheetStatus.CREATED); + statusList.add(SaleOutSheetStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(SaleOutSheet::getApproveTime, LocalDateTime.now()) + .eq(SaleOutSheet::getId, sheet.getId()) + .in(SaleOutSheet::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(SaleOutSheet::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("销售出库单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SaleOutSheetDetail.class) + .eq(SaleOutSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(SaleOutSheetDetail::getOrderNo); + List details = saleOutSheetDetailService.list(queryDetailWrapper); + + int totalNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (SaleOutSheetDetail detail : details) { + boolean isGift = detail.getIsGift(); + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(detail.getTaxPrice(), detail.getOrderNum())); + + Product product = productService.findById(detail.getProductId()); + if (product.getProductType() == ProductType.NORMAL) { + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(detail.getProductId()); + subProductStockVo.setScId(sheet.getScId()); + subProductStockVo.setStockNum(detail.getOrderNum()); + subProductStockVo.setBizId(sheet.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(sheet.getCode()); + subProductStockVo.setBizType(ProductStockBizType.SALE.getCode()); + + ProductStockChangeDto stockChange = productStockService.subStock(subProductStockVo); + + SaleOutSheetDetailLot detailLot = new SaleOutSheetDetailLot(); + + detailLot.setId(IdUtil.getId()); + detailLot.setDetailId(detail.getId()); + detailLot.setOrderNum(detail.getOrderNum()); + detailLot.setCostTaxAmount(stockChange.getTaxAmount()); + detailLot.setSettleStatus(detail.getSettleStatus()); + detailLot.setOrderNo(orderNo); + saleOutSheetDetailLotService.save(detailLot); + + if (isGift) { + giftNum += detail.getOrderNum(); + } else { + totalNum += detail.getOrderNum(); + } + } else { + Wrapper queryBundleWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetailBundle.class).eq(SaleOutSheetDetailBundle::getSheetId, sheet.getId()) + .eq(SaleOutSheetDetailBundle::getDetailId, detail.getId()); + List saleOutSheetDetailBundles = saleOutSheetDetailBundleService.list( + queryBundleWrapper); + Assert.notEmpty(saleOutSheetDetailBundles); + + for (SaleOutSheetDetailBundle saleOutSheetDetailBundle : saleOutSheetDetailBundles) { + SaleOutSheetDetail newDetail = new SaleOutSheetDetail(); + newDetail.setId(IdUtil.getId()); + newDetail.setSheetId(sheet.getId()); + newDetail.setProductId(saleOutSheetDetailBundle.getProductId()); + newDetail.setOrderNum(saleOutSheetDetailBundle.getProductOrderNum()); + newDetail.setOriPrice(saleOutSheetDetailBundle.getProductOriPrice()); + newDetail.setTaxPrice(saleOutSheetDetailBundle.getProductTaxPrice()); + newDetail.setDiscountRate(detail.getDiscountRate()); + newDetail.setIsGift(detail.getIsGift()); + newDetail.setTaxRate(saleOutSheetDetailBundle.getProductTaxRate()); + newDetail.setDescription(detail.getDescription()); + newDetail.setOrderNo(orderNo++); + newDetail.setSettleStatus(detail.getSettleStatus()); + newDetail.setSaleOrderDetailId(detail.getSaleOrderDetailId()); + newDetail.setOriBundleDetailId(detail.getId()); + + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(newDetail.getProductId()); + subProductStockVo.setScId(sheet.getScId()); + subProductStockVo.setStockNum(newDetail.getOrderNum()); + subProductStockVo.setBizId(sheet.getId()); + subProductStockVo.setBizDetailId(newDetail.getId()); + subProductStockVo.setBizCode(sheet.getCode()); + subProductStockVo.setBizType(ProductStockBizType.SALE.getCode()); + + ProductStockChangeDto stockChange = productStockService.subStock(subProductStockVo); + + SaleOutSheetDetailLot detailLot = new SaleOutSheetDetailLot(); + + detailLot.setId(IdUtil.getId()); + detailLot.setDetailId(newDetail.getId()); + detailLot.setOrderNum(newDetail.getOrderNum()); + detailLot.setCostTaxAmount(stockChange.getTaxAmount()); + detailLot.setSettleStatus(newDetail.getSettleStatus()); + detailLot.setOrderNo(orderNo); + saleOutSheetDetailLotService.save(detailLot); + + saleOutSheetDetailService.save(newDetail); + saleOutSheetDetailService.removeById(detail.getId()); + + saleOutSheetDetailBundle.setProductDetailId(newDetail.getId()); + saleOutSheetDetailBundleService.updateById(saleOutSheetDetailBundle); + + if (isGift) { + giftNum += newDetail.getOrderNum(); + } else { + totalNum += newDetail.getOrderNum(); + } + } + } + orderNo++; + } + + // 这里需要重新统计明细信息,因为明细发生变动了 + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getTotalNum, totalNum).set(SaleOutSheet::getTotalGiftNum, giftNum) + .set(SaleOutSheet::getTotalAmount, totalAmount).eq(SaleOutSheet::getId, sheet.getId()); + this.update(updateWrapper); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSaleOutSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSaleOutSheetVo approvePassVo = new ApprovePassSaleOutSheetVo(); + approvePassVo.setId(id); + + try { + SaleOutSheetService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售出库单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSaleOutSheetVo vo) { + + SaleOutSheetService thisService = getThis(this.getClass()); + + String sheetId = thisService.create(vo); + + ApprovePassSaleOutSheetVo approvePassVo = new ApprovePassSaleOutSheetVo(); + approvePassVo.setId(sheetId); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return sheetId; + } + + @OpLog(type = ScOpLogType.SALE, name = "审核拒绝销售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSaleOutSheetVo vo) { + + SaleOutSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new InputErrorException("销售出库单不存在!"); + } + + if (sheet.getStatus() != SaleOutSheetStatus.CREATED) { + + if (sheet.getStatus() == SaleOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("销售出库单已审核通过,不允许继续执行审核!"); + } + + if (sheet.getStatus() == SaleOutSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("销售出库单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("销售出库单无法审核拒绝!"); + } + + sheet.setStatus(SaleOutSheetStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(SaleOutSheet::getApproveTime, LocalDateTime.now()) + .set(SaleOutSheet::getRefuseReason, vo.getRefuseReason()) + .eq(SaleOutSheet::getId, sheet.getId()) + .eq(SaleOutSheet::getStatus, SaleOutSheetStatus.CREATED); + if (getBaseMapper().updateAllColumn(sheet, updateOrderWrapper) != 1) { + throw new DefaultClientException("销售出库单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSaleOutSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSaleOutSheetVo approveRefuseVo = new ApproveRefuseSaleOutSheetVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + SaleOutSheetService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售出库单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.SALE, name = "删除销售出库单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SaleOutSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("销售出库单不存在!"); + } + + if (sheet.getStatus() != SaleOutSheetStatus.CREATED + && sheet.getStatus() != SaleOutSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SaleOutSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的销售出库单不允许执行删除操作!"); + } + + throw new DefaultClientException("销售出库单无法删除!"); + } + + if (logisticsSheetDetailService.getByBizId(sheet.getId(), + LogisticsSheetDetailBizType.SALE_OUT_SHEET) != null) { + throw new DefaultClientException("销售出库单已关联物流单,请先删除物流单!"); + } + + //查询销售出库单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetail.class) + .eq(SaleOutSheetDetail::getSheetId, sheet.getId()); + List details = saleOutSheetDetailService.list(queryDetailWrapper); + + if (!StringUtil.isBlank(sheet.getSaleOrderId())) { + for (SaleOutSheetDetail detail : details) { + if (!StringUtil.isBlank(detail.getSaleOrderDetailId())) { + //恢复已出库数量 + saleOrderDetailService.subOutNum(detail.getSaleOrderDetailId(), detail.getOrderNum()); + } + } + } + + // 删除订单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SaleOutSheetDetail.class) + .eq(SaleOutSheetDetail::getSheetId, sheet.getId()); + saleOutSheetDetailService.remove(deleteDetailWrapper); + + // 删除组合商品信息 + Wrapper deleteDetailBundleWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetailBundle.class).eq(SaleOutSheetDetailBundle::getSheetId, sheet.getId()); + saleOutSheetDetailBundleService.remove(deleteDetailBundleWrapper); + + Wrapper deleteDetailLotWrapper = Wrappers.lambdaQuery( + SaleOutSheetDetailLot.class) + .in(SaleOutSheetDetailLot::getDetailId, + details.stream().map(SaleOutSheetDetail::getId).collect( + Collectors.toList())); + saleOutSheetDetailLotService.remove(deleteDetailLotWrapper); + + // 删除订单 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SaleOutSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售出库单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getSettleStatus, SettleStatus.UN_SETTLE).eq(SaleOutSheet::getId, id) + .eq(SaleOutSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getSettleStatus, SettleStatus.PART_SETTLE).eq(SaleOutSheet::getId, id) + .in(SaleOutSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleOutSheet.class) + .set(SaleOutSheet::getSettleStatus, SettleStatus.SETTLED).eq(SaleOutSheet::getId, id) + .in(SaleOutSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(customerId, startTime, endTime, settleStatus); + } + + private void create(SaleOutSheet sheet, CreateSaleOutSheetVo vo, boolean requireSale) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + sheet.setScId(vo.getScId()); + + Customer customer = customerService.findById(vo.getCustomerId()); + if (customer == null) { + throw new InputErrorException("客户不存在!"); + } + sheet.setCustomerId(vo.getCustomerId()); + + if (!StringUtil.isBlank(vo.getSalerId())) { + UserDto saler = userService.findById(vo.getSalerId()); + if (saler == null) { + throw new InputErrorException("销售员不存在!"); + } + + sheet.setSalerId(vo.getSalerId()); + } + + SaleConfig saleConfig = saleConfigService.get(); + + GetPaymentDateDto paymentDate = this.getPaymentDate(customer.getId()); + + sheet.setPaymentDate( + vo.getAllowModifyPaymentDate() || paymentDate.getAllowModify() ? vo.getPaymentDate() + : paymentDate.getPaymentDate()); + + if (requireSale) { + + SaleOrder saleOrder = saleOrderService.getById(vo.getSaleOrderId()); + if (saleOrder == null) { + throw new DefaultClientException("销售订单不存在!"); + } + + sheet.setScId(saleOrder.getScId()); + sheet.setCustomerId(saleOrder.getCustomerId()); + sheet.setSaleOrderId(saleOrder.getId()); + + if (!saleConfig.getOutStockMultipleRelateSale()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SaleOutSheet.class) + .eq(SaleOutSheet::getSaleOrderId, saleOrder.getId()) + .ne(SaleOutSheet::getId, sheet.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException( + "销售订单号:" + saleOrder.getCode() + + ",已关联其他销售出库单,不允许关联多个销售出库单!"); + } + } + } + + int purchaseNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (SaleOutProductVo productVo : vo.getProducts()) { + if (requireSale) { + if (!StringUtil.isBlank(productVo.getSaleOrderDetailId())) { + SaleOrderDetail orderDetail = saleOrderDetailService.getById( + productVo.getSaleOrderDetailId()); + productVo.setOriPrice(orderDetail.getOriPrice()); + productVo.setTaxPrice(orderDetail.getTaxPrice()); + productVo.setDiscountRate(orderDetail.getDiscountRate()); + } else { + productVo.setTaxPrice(BigDecimal.ZERO); + productVo.setDiscountRate(BigDecimal.valueOf(100)); + } + } + + boolean isGift = productVo.getTaxPrice().doubleValue() == 0D; + + if (requireSale) { + if (StringUtil.isBlank(productVo.getSaleOrderDetailId())) { + if (!isGift) { + throw new InputErrorException("第" + orderNo + "行商品必须为“赠品”!"); + } + } + } + + if (isGift) { + giftNum += productVo.getOrderNum(); + } else { + purchaseNum += productVo.getOrderNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getTaxPrice(), productVo.getOrderNum())); + + SaleOutSheetDetail detail = new SaleOutSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getTaxPrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品价格最多允许2位小数!"); + } + + detail.setProductId(productVo.getProductId()); + detail.setOrderNum(productVo.getOrderNum()); + detail.setOriPrice(productVo.getOriPrice()); + detail.setTaxPrice(productVo.getTaxPrice()); + detail.setDiscountRate(productVo.getDiscountRate()); + detail.setIsGift(isGift); + detail.setTaxRate(product.getSaleTaxRate()); + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + detail.setOrderNo(orderNo); + detail.setSettleStatus(this.getInitSettleStatus(customer)); + if (requireSale && !StringUtil.isBlank(productVo.getSaleOrderDetailId())) { + detail.setSaleOrderDetailId(productVo.getSaleOrderDetailId()); + saleOrderDetailService.addOutNum(productVo.getSaleOrderDetailId(), detail.getOrderNum()); + } + + saleOutSheetDetailService.save(detail); + + // 这里处理组合商品 + if (product.getProductType() == ProductType.BUNDLE) { + List productBundles = productBundleService.getByMainProductId( + product.getId()); + // 构建指标项 + Map bundleWeight = new HashMap<>(productBundles.size()); + for (ProductBundle productBundle : productBundles) { + bundleWeight.put(productBundle.getProductId(), + NumberUtil.mul(productBundle.getSalePrice(), productBundle.getBundleNum())); + } + Map splitPriceMap = SplitNumberUtil.split(detail.getTaxPrice(), + bundleWeight, 2); + List saleOutSheetDetailBundles = productBundles.stream() + .map(productBundle -> { + Product bundle = productService.findById(productBundle.getProductId()); + SaleOutSheetDetailBundle saleOutSheetDetailBundle = new SaleOutSheetDetailBundle(); + saleOutSheetDetailBundle.setId(IdUtil.getId()); + saleOutSheetDetailBundle.setSheetId(sheet.getId()); + saleOutSheetDetailBundle.setDetailId(detail.getId()); + saleOutSheetDetailBundle.setMainProductId(product.getId()); + saleOutSheetDetailBundle.setOrderNum(detail.getOrderNum()); + saleOutSheetDetailBundle.setProductId(productBundle.getProductId()); + saleOutSheetDetailBundle.setProductOrderNum( + NumberUtil.mul(detail.getOrderNum(), productBundle.getBundleNum()).intValue()); + saleOutSheetDetailBundle.setProductOriPrice(productBundle.getSalePrice()); + // 这里会有尾差 + saleOutSheetDetailBundle.setProductTaxPrice( + NumberUtil.getNumber(NumberUtil.div(BigDecimal.valueOf( + splitPriceMap.get(productBundle.getProductId()).doubleValue()), + productBundle.getBundleNum()), 2)); + saleOutSheetDetailBundle.setProductTaxRate(bundle.getSaleTaxRate()); + + return saleOutSheetDetailBundle; + }).collect(Collectors.toList()); + + saleOutSheetDetailBundleService.saveBatch(saleOutSheetDetailBundles); + } else { + if (requireSale && !StringUtil.isBlank(detail.getSaleOrderDetailId())) { + // 这里如果是关联销售单的话,需要把组合商品信息拿过来,价格不用重新算,因为关联销售单的话,价格不允许修改 + Wrapper querySaleOrderDetailBundleWrapper = Wrappers.lambdaQuery( + SaleOrderDetailBundle.class) + .eq(SaleOrderDetailBundle::getOrderId, sheet.getSaleOrderId()) + .eq(SaleOrderDetailBundle::getProductDetailId, detail.getSaleOrderDetailId()); + SaleOrderDetailBundle saleOrderDetailBundle = saleOrderDetailBundleService.getOne( + querySaleOrderDetailBundleWrapper); + if (saleOrderDetailBundle != null) { + SaleOutSheetDetailBundle saleOutSheetDetailBundle = new SaleOutSheetDetailBundle(); + saleOutSheetDetailBundle.setId(IdUtil.getId()); + saleOutSheetDetailBundle.setSheetId(sheet.getId()); + saleOutSheetDetailBundle.setDetailId(detail.getId()); + saleOutSheetDetailBundle.setMainProductId(saleOrderDetailBundle.getMainProductId()); + saleOutSheetDetailBundle.setOrderNum(detail.getOrderNum()); + saleOutSheetDetailBundle.setProductId(saleOrderDetailBundle.getProductId()); + saleOutSheetDetailBundle.setProductOrderNum(saleOrderDetailBundle.getProductOrderNum()); + saleOutSheetDetailBundle.setProductOriPrice(saleOrderDetailBundle.getProductOriPrice()); + saleOutSheetDetailBundle.setProductTaxPrice(saleOrderDetailBundle.getProductTaxPrice()); + saleOutSheetDetailBundle.setProductTaxRate(saleOrderDetailBundle.getProductTaxRate()); + saleOutSheetDetailBundle.setProductDetailId(detail.getId()); + saleOutSheetDetailBundleService.save(saleOutSheetDetailBundle); + } + } + } + orderNo++; + } + sheet.setTotalNum(purchaseNum); + sheet.setTotalGiftNum(giftNum); + sheet.setTotalAmount(totalAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setSettleStatus(this.getInitSettleStatus(customer)); + } + + /** + * 根据客户获取初始结算状态 + * + * @param customer + * @return + */ + private SettleStatus getInitSettleStatus(Customer customer) { + + return SettleStatus.UN_SETTLE; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnDetailServiceImpl.java new file mode 100644 index 0000000..a07fee8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.SaleReturnDetail; +import com.lframework.xingyun.sc.mappers.SaleReturnDetailMapper; +import com.lframework.xingyun.sc.service.sale.SaleReturnDetailService; +import org.springframework.stereotype.Service; + +@Service +public class SaleReturnDetailServiceImpl extends + BaseMpServiceImpl + implements SaleReturnDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnServiceImpl.java new file mode 100644 index 0000000..eb5cbee --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/sale/SaleReturnServiceImpl.java @@ -0,0 +1,675 @@ +package com.lframework.xingyun.sc.impl.sale; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.entity.StoreCenter; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.order.impl.ApprovePassSaleReturnEvent; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetDetailLotDto; +import com.lframework.xingyun.sc.dto.sale.returned.SaleReturnFullDto; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.entity.SaleReturnDetail; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.SaleReturnStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.mappers.SaleReturnMapper; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.sc.service.sale.SaleReturnDetailService; +import com.lframework.xingyun.sc.service.sale.SaleReturnService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.sale.returned.ApprovePassSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.ApproveRefuseSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.BatchApprovePassSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.BatchApproveRefuseSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.CreateSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.QuerySaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.SaleReturnProductVo; +import com.lframework.xingyun.sc.vo.sale.returned.UpdateSaleReturnVo; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SaleReturnServiceImpl extends BaseMpServiceImpl + implements SaleReturnService { + + @Autowired + private SaleReturnDetailService saleReturnDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private StoreCenterService storeCenterService; + + @Autowired + private CustomerService customerService; + + @Autowired + private UserService userService; + + @Autowired + private ProductService productService; + + @Autowired + private SaleOutSheetService saleOutSheetService; + + @Autowired + private SaleConfigService saleConfigService; + + @Autowired + private SaleOutSheetDetailService saleOutSheetDetailService; + + @Autowired + private SaleOutSheetDetailLotService saleOutSheetDetailLotService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private ProductPurchaseService productPurchaseService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySaleReturnVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySaleReturnVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public SaleReturnFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.SALE, name = "创建销售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建退货单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSaleReturnVo vo) { + + SaleReturn saleReturn = new SaleReturn(); + saleReturn.setId(IdUtil.getId()); + saleReturn.setCode(generateCodeService.generate(GenerateCodeTypePool.SALE_RETURN)); + + SaleConfig saleConfig = saleConfigService.get(); + + this.create(saleReturn, vo, saleConfig.getSaleReturnRequireOutStock()); + + saleReturn.setStatus(SaleReturnStatus.CREATED); + + getBaseMapper().insert(saleReturn); + + OpLogUtil.setVariable("code", saleReturn.getCode()); + OpLogUtil.setExtra(vo); + + return saleReturn.getId(); + } + + @OpLog(type = ScOpLogType.SALE, name = "修改销售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改退货单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSaleReturnVo vo) { + + SaleReturn saleReturn = getBaseMapper().selectById(vo.getId()); + if (saleReturn == null) { + throw new InputErrorException("销售退货单不存在!"); + } + + if (saleReturn.getStatus() != SaleReturnStatus.CREATED + && saleReturn.getStatus() != SaleReturnStatus.APPROVE_REFUSE) { + + if (saleReturn.getStatus() == SaleReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("销售退货单已审核通过,无法修改!"); + } + + throw new DefaultClientException("销售退货单无法修改!"); + } + + boolean requireOut = !StringUtil.isBlank(saleReturn.getOutSheetId()); + + if (requireOut) { + //查询销售退货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SaleReturnDetail.class) + .eq(SaleReturnDetail::getReturnId, saleReturn.getId()); + List details = saleReturnDetailService.list(queryDetailWrapper); + for (SaleReturnDetail detail : details) { + if (!StringUtil.isBlank(detail.getOutSheetDetailId())) { + //先恢复已退货数量 + saleOutSheetDetailLotService.subReturnNum(detail.getOutSheetDetailId(), + detail.getReturnNum()); + } + } + } + + // 删除销售退货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SaleReturnDetail.class) + .eq(SaleReturnDetail::getReturnId, saleReturn.getId()); + saleReturnDetailService.remove(deleteDetailWrapper); + + this.create(saleReturn, vo, requireOut); + + saleReturn.setStatus(SaleReturnStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SaleReturnStatus.CREATED); + statusList.add(SaleReturnStatus.APPROVE_REFUSE); + + Wrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleReturn.class) + .set(SaleReturn::getApproveBy, null).set(SaleReturn::getApproveTime, null) + .set(SaleReturn::getRefuseReason, StringPool.EMPTY_STR) + .eq(SaleReturn::getId, saleReturn.getId()) + .in(SaleReturn::getStatus, statusList); + if (getBaseMapper().updateAllColumn(saleReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("销售退货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", saleReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.SALE, name = "审核通过销售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSaleReturnVo vo) { + + SaleReturn saleReturn = getBaseMapper().selectById(vo.getId()); + if (saleReturn == null) { + throw new InputErrorException("销售退货单不存在!"); + } + + if (saleReturn.getStatus() != SaleReturnStatus.CREATED + && saleReturn.getStatus() != SaleReturnStatus.APPROVE_REFUSE) { + + if (saleReturn.getStatus() == SaleReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("销售退货单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("销售退货单无法审核通过!"); + } + + SaleConfig saleConfig = saleConfigService.get(); + + if (!saleConfig.getSaleReturnMultipleRelateOutStock()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SaleReturn.class) + .eq(SaleReturn::getOutSheetId, saleReturn.getOutSheetId()) + .ne(SaleReturn::getId, saleReturn.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + SaleOutSheet saleOutSheet = saleOutSheetService.getById(saleReturn.getOutSheetId()); + throw new DefaultClientException( + "销售出库单号:" + saleOutSheet.getCode() + + ",已关联其他销售退货单,不允许关联多个销售退货单!"); + } + } + + saleReturn.setStatus(SaleReturnStatus.APPROVE_PASS); + + List statusList = new ArrayList<>(); + statusList.add(SaleReturnStatus.CREATED); + statusList.add(SaleReturnStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleReturn.class) + .set(SaleReturn::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(SaleReturn::getApproveTime, LocalDateTime.now()) + .eq(SaleReturn::getId, saleReturn.getId()) + .in(SaleReturn::getStatus, statusList); + if (!StringUtil.isBlank(vo.getDescription())) { + updateOrderWrapper.set(SaleReturn::getDescription, vo.getDescription()); + } + if (getBaseMapper().updateAllColumn(saleReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("销售退货单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SaleReturnDetail.class) + .eq(SaleReturnDetail::getReturnId, saleReturn.getId()) + .orderByAsc(SaleReturnDetail::getOrderNo); + List details = saleReturnDetailService.list(queryDetailWrapper); + for (SaleReturnDetail detail : details) { + ProductPurchase productPurchase = productPurchaseService.getById(detail.getProductId()); + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(detail.getProductId()); + addProductStockVo.setScId(saleReturn.getScId()); + addProductStockVo.setStockNum(detail.getReturnNum()); + addProductStockVo.setDefaultTaxPrice(productPurchase.getPrice()); + addProductStockVo.setBizId(saleReturn.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(saleReturn.getCode()); + addProductStockVo.setBizType(ProductStockBizType.SALE_RETURN.getCode()); + + productStockService.addStock(addProductStockVo); + } + + this.sendApprovePassEvent(saleReturn); + + OpLogUtil.setVariable("code", saleReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSaleReturnVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSaleReturnVo approvePassVo = new ApprovePassSaleReturnVo(); + approvePassVo.setId(id); + + try { + SaleReturnService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售退货单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSaleReturnVo vo) { + + SaleReturnService thisService = getThis(this.getClass()); + + String returnId = thisService.create(vo); + + ApprovePassSaleReturnVo approvePassVo = new ApprovePassSaleReturnVo(); + approvePassVo.setId(returnId); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return returnId; + } + + @OpLog(type = ScOpLogType.SALE, name = "审核拒绝销售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSaleReturnVo vo) { + + SaleReturn saleReturn = getBaseMapper().selectById(vo.getId()); + if (saleReturn == null) { + throw new InputErrorException("销售退货单不存在!"); + } + + if (saleReturn.getStatus() != SaleReturnStatus.CREATED) { + + if (saleReturn.getStatus() == SaleReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("销售退货单已审核通过,不允许继续执行审核!"); + } + + if (saleReturn.getStatus() == SaleReturnStatus.APPROVE_REFUSE) { + throw new DefaultClientException("销售退货单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("销售退货单无法审核拒绝!"); + } + + saleReturn.setStatus(SaleReturnStatus.APPROVE_REFUSE); + + LambdaUpdateWrapper updateOrderWrapper = Wrappers.lambdaUpdate(SaleReturn.class) + .set(SaleReturn::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(SaleReturn::getApproveTime, LocalDateTime.now()) + .set(SaleReturn::getRefuseReason, vo.getRefuseReason()) + .eq(SaleReturn::getId, saleReturn.getId()) + .eq(SaleReturn::getStatus, SaleReturnStatus.CREATED); + if (getBaseMapper().updateAllColumn(saleReturn, updateOrderWrapper) != 1) { + throw new DefaultClientException("销售退货单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", saleReturn.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSaleReturnVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSaleReturnVo approveRefuseVo = new ApproveRefuseSaleReturnVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + SaleReturnService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售退货单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OpLog(type = ScOpLogType.SALE, name = "删除销售退货单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SaleReturn saleReturn = getBaseMapper().selectById(id); + if (saleReturn == null) { + throw new InputErrorException("销售退货单不存在!"); + } + + if (saleReturn.getStatus() != SaleReturnStatus.CREATED + && saleReturn.getStatus() != SaleReturnStatus.APPROVE_REFUSE) { + + if (saleReturn.getStatus() == SaleReturnStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的销售退货单不允许执行删除操作!"); + } + + throw new DefaultClientException("销售退货单无法删除!"); + } + + if (!StringUtil.isBlank(saleReturn.getOutSheetId())) { + //查询销售退货单明细 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SaleReturnDetail.class) + .eq(SaleReturnDetail::getReturnId, saleReturn.getId()); + List details = saleReturnDetailService.list(queryDetailWrapper); + for (SaleReturnDetail detail : details) { + if (!StringUtil.isBlank(detail.getOutSheetDetailId())) { + //恢复已退货数量 + saleOutSheetDetailLotService.subReturnNum(detail.getOutSheetDetailId(), + detail.getReturnNum()); + } + } + } + + // 删除退货单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SaleReturnDetail.class) + .eq(SaleReturnDetail::getReturnId, saleReturn.getId()); + saleReturnDetailService.remove(deleteDetailWrapper); + + // 删除退货单 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", saleReturn.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SaleReturnService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个销售退货单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleReturn.class) + .set(SaleReturn::getSettleStatus, SettleStatus.UN_SETTLE).eq(SaleReturn::getId, id) + .eq(SaleReturn::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleReturn.class) + .set(SaleReturn::getSettleStatus, SettleStatus.PART_SETTLE).eq(SaleReturn::getId, id) + .in(SaleReturn::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SaleReturn.class) + .set(SaleReturn::getSettleStatus, SettleStatus.SETTLED).eq(SaleReturn::getId, id) + .in(SaleReturn::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(customerId, startTime, endTime, settleStatus); + } + + private void create(SaleReturn saleReturn, CreateSaleReturnVo vo, boolean requireOut) { + + StoreCenter sc = storeCenterService.findById(vo.getScId()); + if (sc == null) { + throw new InputErrorException("仓库不存在!"); + } + + saleReturn.setScId(vo.getScId()); + + Customer customer = customerService.findById(vo.getCustomerId()); + if (customer == null) { + throw new InputErrorException("客户不存在!"); + } + saleReturn.setCustomerId(vo.getCustomerId()); + + if (!StringUtil.isBlank(vo.getSalerId())) { + UserDto saler = userService.findById(vo.getSalerId()); + if (saler == null) { + throw new InputErrorException("销售员不存在!"); + } + + saleReturn.setSalerId(vo.getSalerId()); + } + + SaleConfig saleConfig = saleConfigService.get(); + + GetPaymentDateDto paymentDate = saleOutSheetService.getPaymentDate(customer.getId()); + + saleReturn.setPaymentDate( + paymentDate.getAllowModify() ? vo.getPaymentDate() : paymentDate.getPaymentDate()); + + if (requireOut) { + + SaleOutSheet saleOutSheet = saleOutSheetService.getById(vo.getOutSheetId()); + if (saleOutSheet == null) { + throw new DefaultClientException("销售出库单不存在!"); + } + + saleReturn.setScId(saleOutSheet.getScId()); + saleReturn.setCustomerId(saleOutSheet.getCustomerId()); + saleReturn.setOutSheetId(saleOutSheet.getId()); + + if (!saleConfig.getSaleReturnMultipleRelateOutStock()) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SaleReturn.class) + .eq(SaleReturn::getOutSheetId, saleOutSheet.getId()) + .ne(SaleReturn::getId, saleReturn.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException( + "销售出库单号:" + saleOutSheet.getCode() + + ",已关联其他销售退货单,不允许关联多个销售退货单!"); + } + } + } + + int returnNum = 0; + int giftNum = 0; + BigDecimal totalAmount = BigDecimal.ZERO; + int orderNo = 1; + for (SaleReturnProductVo productVo : vo.getProducts()) { + if (requireOut) { + if (!StringUtil.isBlank(productVo.getOutSheetDetailId())) { + SaleOutSheetDetailLotDto detailLot = saleOutSheetDetailLotService.findById( + productVo.getOutSheetDetailId()); + SaleOutSheetDetail detail = saleOutSheetDetailService.getById(detailLot.getDetailId()); + productVo.setOriPrice(detail.getOriPrice()); + productVo.setTaxPrice(detail.getTaxPrice()); + productVo.setDiscountRate(detail.getDiscountRate()); + } else { + productVo.setTaxPrice(BigDecimal.ZERO); + productVo.setDiscountRate(BigDecimal.valueOf(100)); + } + } + + boolean isGift = productVo.getTaxPrice().doubleValue() == 0D; + + if (requireOut) { + if (StringUtil.isBlank(productVo.getOutSheetDetailId())) { + if (!isGift) { + throw new InputErrorException("第" + orderNo + "行商品必须为“赠品”!"); + } + } + } + + if (isGift) { + giftNum += productVo.getReturnNum(); + } else { + returnNum += productVo.getReturnNum(); + } + + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(productVo.getTaxPrice(), productVo.getReturnNum())); + + SaleReturnDetail detail = new SaleReturnDetail(); + detail.setId(IdUtil.getId()); + detail.setReturnId(saleReturn.getId()); + + Product product = productService.findById(productVo.getProductId()); + if (product == null) { + throw new InputErrorException("第" + orderNo + "行商品不存在!"); + } + + if (!NumberUtil.isNumberPrecision(productVo.getTaxPrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品价格最多允许2位小数!"); + } + + detail.setProductId(productVo.getProductId()); + detail.setReturnNum(productVo.getReturnNum()); + detail.setOriPrice(productVo.getOriPrice()); + detail.setTaxPrice(productVo.getTaxPrice()); + detail.setDiscountRate(productVo.getDiscountRate()); + detail.setIsGift(isGift); + detail.setTaxRate(product.getSaleTaxRate()); + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + detail.setOrderNo(orderNo); + detail.setSettleStatus(this.getInitSettleStatus(customer)); + if (requireOut && !StringUtil.isBlank(productVo.getOutSheetDetailId())) { + detail.setOutSheetDetailId(productVo.getOutSheetDetailId()); + saleOutSheetDetailLotService.addReturnNum(productVo.getOutSheetDetailId(), + detail.getReturnNum()); + } + + saleReturnDetailService.save(detail); + orderNo++; + } + saleReturn.setTotalNum(returnNum); + saleReturn.setTotalGiftNum(giftNum); + saleReturn.setTotalAmount(totalAmount); + saleReturn.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + saleReturn.setSettleStatus(this.getInitSettleStatus(customer)); + } + + /** + * 根据客户获取初始结算状态 + * + * @param customer + * @return + */ + private SettleStatus getInitSettleStatus(Customer customer) { + + return SettleStatus.UN_SETTLE; + } + + private void sendApprovePassEvent(SaleReturn r) { + + ApprovePassSaleReturnEvent event = new ApprovePassSaleReturnEvent(this); + event.setId(r.getId()); + event.setTotalAmount(r.getTotalAmount()); + event.setApproveTime(r.getApproveTime()); + + ApplicationUtil.publishEvent(event); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockLogServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockLogServiceImpl.java new file mode 100644 index 0000000..64314ea --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockLogServiceImpl.java @@ -0,0 +1,152 @@ +package com.lframework.xingyun.sc.impl.stock; + +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.entity.ProductStockLog; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.mappers.ProductStockLogMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockLogService; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithAddStockVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithStockCostAdjustVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithSubStockVo; +import com.lframework.xingyun.sc.vo.stock.log.QueryProductStockLogVo; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductStockLogServiceImpl extends + BaseMpServiceImpl + implements ProductStockLogService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryProductStockLogVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryProductStockLogVo vo) { + + return getBaseMapper().query(vo); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addLogWithAddStock(AddLogWithAddStockVo vo) { + + ProductStockLog record = new ProductStockLog(); + record.setId(IdUtil.getId()); + record.setScId(vo.getScId()); + record.setProductId(vo.getProductId()); + record.setOriStockNum(vo.getOriStockNum()); + record.setCurStockNum(vo.getCurStockNum()); + record.setOriTaxPrice(vo.getOriTaxPrice()); + record.setCurTaxPrice(vo.getCurTaxPrice()); + record.setStockNum(vo.getStockNum()); + record.setTaxAmount(vo.getTaxAmount()); + if (!StringUtil.isBlank(vo.getCreateBy())) { + record.setCreateBy(vo.getCreateBy()); + } + if (!StringUtil.isBlank(vo.getCreateById())) { + record.setCreateById(vo.getCreateById()); + } + record.setCreateTime(vo.getCreateTime()); + if (!StringUtil.isBlank(vo.getBizId())) { + record.setBizId(vo.getBizId()); + } + if (!StringUtil.isBlank(vo.getBizDetailId())) { + record.setBizDetailId(vo.getBizDetailId()); + } + if (!StringUtil.isBlank(vo.getBizCode())) { + record.setBizCode(vo.getBizCode()); + } + record.setBizType(EnumUtil.getByCode(ProductStockBizType.class, vo.getBizType())); + + getBaseMapper().insert(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addLogWithSubStock(AddLogWithSubStockVo vo) { + + ProductStockLog record = new ProductStockLog(); + record.setId(IdUtil.getId()); + record.setScId(vo.getScId()); + record.setProductId(vo.getProductId()); + record.setOriStockNum(vo.getOriStockNum()); + record.setCurStockNum(vo.getCurStockNum()); + record.setOriTaxPrice(vo.getOriTaxPrice()); + record.setCurTaxPrice(vo.getCurTaxPrice()); + record.setStockNum(-Math.abs(vo.getStockNum())); + record.setTaxAmount(vo.getTaxAmount().abs().negate()); + if (!StringUtil.isBlank(vo.getCreateBy())) { + record.setCreateBy(vo.getCreateBy()); + } + if (!StringUtil.isBlank(vo.getCreateById())) { + record.setCreateById(vo.getCreateById()); + } + record.setCreateTime(vo.getCreateTime()); + if (!StringUtil.isBlank(vo.getBizId())) { + record.setBizId(vo.getBizId()); + } + if (!StringUtil.isBlank(vo.getBizDetailId())) { + record.setBizDetailId(vo.getBizDetailId()); + } + if (!StringUtil.isBlank(vo.getBizCode())) { + record.setBizCode(vo.getBizCode()); + } + record.setBizType(EnumUtil.getByCode(ProductStockBizType.class, vo.getBizType())); + + getBaseMapper().insert(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addLogWithStockCostAdjust(AddLogWithStockCostAdjustVo vo) { + + ProductStockLog record = new ProductStockLog(); + record.setId(IdUtil.getId()); + record.setScId(vo.getScId()); + record.setProductId(vo.getProductId()); + record.setOriStockNum(vo.getOriStockNum()); + record.setCurStockNum(vo.getOriStockNum()); + record.setOriTaxPrice(vo.getOriTaxPrice()); + record.setCurTaxPrice(vo.getCurTaxPrice()); + record.setStockNum(0); + record.setTaxAmount(vo.getTaxAmount()); + if (!StringUtil.isBlank(vo.getCreateBy())) { + record.setCreateBy(vo.getCreateBy()); + } + if (!StringUtil.isBlank(vo.getCreateById())) { + record.setCreateById(vo.getCreateById()); + } + record.setCreateTime(vo.getCreateTime()); + if (!StringUtil.isBlank(vo.getBizId())) { + record.setBizId(vo.getBizId()); + } + if (!StringUtil.isBlank(vo.getBizDetailId())) { + record.setBizDetailId(vo.getBizDetailId()); + } + if (!StringUtil.isBlank(vo.getBizCode())) { + record.setBizCode(vo.getBizCode()); + } + record.setBizType(ProductStockBizType.STOCK_COST_ADJUST); + + getBaseMapper().insert(record); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockServiceImpl.java new file mode 100644 index 0000000..fd612e5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/ProductStockServiceImpl.java @@ -0,0 +1,358 @@ +package com.lframework.xingyun.sc.impl.stock; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductBundle; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.product.ProductBundleService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import com.lframework.xingyun.core.events.stock.AddStockEvent; +import com.lframework.xingyun.core.events.stock.SubStockEvent; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustDiffDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.mappers.ProductStockMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockLogService; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.sc.vo.stock.QueryProductStockVo; +import com.lframework.xingyun.sc.vo.stock.StockCostAdjustVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithAddStockVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithStockCostAdjustVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithSubStockVo; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProductStockServiceImpl extends BaseMpServiceImpl + implements ProductStockService { + + @Autowired + private ProductService productService; + + @Autowired + private ProductBundleService productBundleService; + + @Autowired + private ProductStockLogService productStockLogService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryProductStockVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryProductStockVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public ProductStock getByProductIdAndScId(String productId, String scId) { + + Product product = productService.findById(productId); + if (product == null) { + return null; + } + + if (product.getProductType() == ProductType.NORMAL) { + return getBaseMapper().getByProductIdAndScId(productId, scId); + } else { + List productBundles = productBundleService.getByMainProductId(productId); + if (CollectionUtil.isEmpty(productBundles)) { + return null; + } + + List productIds = productBundles.stream().map(ProductBundle::getProductId).collect( + Collectors.toList()); + List productStocks = this.getByProductIdsAndScId(productIds, scId, + ProductType.NORMAL.getCode()); + + int stockNum = Integer.MAX_VALUE; + for (ProductBundle productBundle : productBundles) { + String id = productBundle.getProductId(); + ProductStock productStock = productStocks.stream().filter(t -> t.getProductId().equals(id)) + .findFirst().orElse(null); + if (productStock == null || productStock.getStockNum() <= 0) { + // 此处说明有单品没有库存 + return null; + } + + stockNum = Math.min(productStock.getStockNum() / productBundle.getBundleNum(), stockNum); + } + + ProductStock productStock = new ProductStock(); + productStock.setId(IdUtil.getId()); + productStock.setScId(scId); + productStock.setProductId(productId); + productStock.setStockNum(stockNum); + productStock.setTaxPrice(BigDecimal.ZERO); + productStock.setTaxAmount(BigDecimal.ZERO); + + return productStock; + } + } + + @Override + public List getByProductIdsAndScId(List productIds, String scId, + Integer productType) { + + if (CollectionUtil.isEmpty(productIds)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByProductIdsAndScId(productIds, scId, productType); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ProductStockChangeDto addStock(AddProductStockVo vo) { + + Product product = productService.findById(vo.getProductId()); + if (product.getProductType() != ProductType.NORMAL) { + throw new DefaultClientException( + "只有商品类型为【" + ProductType.NORMAL.getDesc() + "】的商品支持入库!"); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(ProductStock.class) + .eq(ProductStock::getProductId, vo.getProductId()).eq(ProductStock::getScId, vo.getScId()); + + ProductStock productStock = getBaseMapper().selectOne(queryWrapper); + + boolean isStockEmpty = false; + if (productStock == null) { + //首次入库,先新增 + productStock = new ProductStock(); + productStock.setId(IdUtil.getId()); + productStock.setScId(vo.getScId()); + productStock.setProductId(vo.getProductId()); + productStock.setStockNum(0); + productStock.setTaxPrice(BigDecimal.ZERO); + productStock.setTaxAmount(BigDecimal.ZERO); + + getBaseMapper().insert(productStock); + + isStockEmpty = true; + } + + // 如果taxAmount为null,代表不重算均价,即:按当前均价直接入库 + boolean reCalcCostPrice = vo.getTaxPrice() != null; + + if (vo.getTaxPrice() == null) { + vo.setTaxPrice(isStockEmpty ? + vo.getDefaultTaxPrice() : + productStock.getTaxPrice()); + } + if (vo.getTaxPrice() == null) { + // 如果此时taxPrice还是null,则代表taxPrice和defaultTaxPrice均为null + throw new DefaultSysException( + "商品ID:" + vo.getProductId() + ",没有库存,taxPrice和defaultTaxPrice不能同时为null!"); + } + + if (isStockEmpty) { + // 如果之前没有库存,那么均价必须重算 + reCalcCostPrice = true; + } + + vo.setTaxPrice(NumberUtil.getNumber(vo.getTaxPrice(), 2)); + int count = getBaseMapper().addStock(vo.getProductId(), vo.getScId(), vo.getStockNum(), + NumberUtil.mul(vo.getTaxPrice(), vo.getStockNum()), productStock.getStockNum(), + productStock.getTaxAmount(), reCalcCostPrice); + if (count != 1) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "入库失败,请稍后重试!"); + } + + AddLogWithAddStockVo addLogWithAddStockVo = new AddLogWithAddStockVo(); + addLogWithAddStockVo.setProductId(vo.getProductId()); + addLogWithAddStockVo.setScId(vo.getScId()); + addLogWithAddStockVo.setStockNum(vo.getStockNum()); + addLogWithAddStockVo.setTaxAmount(NumberUtil.mul(vo.getTaxPrice(), vo.getStockNum())); + addLogWithAddStockVo.setOriStockNum(productStock.getStockNum()); + addLogWithAddStockVo.setCurStockNum( + NumberUtil.add(productStock.getStockNum(), vo.getStockNum()).intValue()); + addLogWithAddStockVo.setOriTaxPrice(productStock.getTaxPrice()); + addLogWithAddStockVo.setCurTaxPrice(!reCalcCostPrice ? + productStock.getTaxPrice() : + addLogWithAddStockVo.getCurStockNum() == 0 ? + BigDecimal.ZERO : + NumberUtil.getNumber( + NumberUtil.div(NumberUtil.add(productStock.getTaxAmount(), + NumberUtil.mul(vo.getTaxPrice(), vo.getStockNum())), + addLogWithAddStockVo.getCurStockNum()), 6)); + addLogWithAddStockVo.setCreateTime(vo.getCreateTime()); + addLogWithAddStockVo.setBizId(vo.getBizId()); + addLogWithAddStockVo.setBizDetailId(vo.getBizDetailId()); + addLogWithAddStockVo.setBizCode(vo.getBizCode()); + addLogWithAddStockVo.setBizType(vo.getBizType()); + + productStockLogService.addLogWithAddStock(addLogWithAddStockVo); + + ProductStockChangeDto stockChange = new ProductStockChangeDto(); + stockChange.setScId(vo.getScId()); + stockChange.setProductId(vo.getProductId()); + stockChange.setNum(vo.getStockNum()); + stockChange.setTaxAmount(addLogWithAddStockVo.getTaxAmount()); + stockChange.setCurTaxPrice(addLogWithAddStockVo.getCurTaxPrice()); + + AddStockEvent addStockEvent = new AddStockEvent(this, stockChange); + ApplicationUtil.publishEvent(addStockEvent); + + return stockChange; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ProductStockChangeDto subStock(SubProductStockVo vo) { + + Product product = productService.findById(vo.getProductId()); + if (product.getProductType() != ProductType.NORMAL) { + throw new DefaultClientException( + "只有商品类型为【" + ProductType.NORMAL.getDesc() + "】的商品支持出库!"); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(ProductStock.class) + .eq(ProductStock::getProductId, vo.getProductId()).eq(ProductStock::getScId, vo.getScId()); + + ProductStock productStock = getBaseMapper().selectOne(queryWrapper); + if (productStock == null) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "当前库存为0,无法出库!"); + } + + if (NumberUtil.lt(productStock.getStockNum(), vo.getStockNum())) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "当前库存为" + + productStock.getStockNum() + + ",库存不足,无法出库!"); + } + + // 如果taxAmount为null,代表不重算均价,即:按当前均价直接出库 + boolean reCalcCostPrice = vo.getTaxAmount() != null; + if (vo.getTaxAmount() == null) { + vo.setTaxAmount(NumberUtil.mul(productStock.getTaxPrice(), vo.getStockNum())); + } + + vo.setTaxAmount(NumberUtil.getNumber(vo.getTaxAmount(), 2)); + + BigDecimal subTaxAmount = vo.getTaxAmount(); + + int count = getBaseMapper().subStock(vo.getProductId(), vo.getScId(), vo.getStockNum(), + subTaxAmount, + productStock.getStockNum(), productStock.getTaxAmount(), reCalcCostPrice); + if (count != 1) { + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "出库失败,请稍后重试!"); + } + + AddLogWithSubStockVo addLogWithAddStockVo = new AddLogWithSubStockVo(); + addLogWithAddStockVo.setProductId(vo.getProductId()); + addLogWithAddStockVo.setScId(vo.getScId()); + addLogWithAddStockVo.setStockNum(vo.getStockNum()); + addLogWithAddStockVo.setTaxAmount(subTaxAmount); + addLogWithAddStockVo.setOriStockNum(productStock.getStockNum()); + addLogWithAddStockVo.setCurStockNum( + NumberUtil.sub(productStock.getStockNum(), vo.getStockNum()).intValue()); + addLogWithAddStockVo.setOriTaxPrice(productStock.getTaxPrice()); + addLogWithAddStockVo.setCurTaxPrice(!reCalcCostPrice ? + productStock.getTaxPrice() : + addLogWithAddStockVo.getCurStockNum() == 0 ? + BigDecimal.ZERO : + NumberUtil.getNumber( + NumberUtil.div(NumberUtil.sub(productStock.getTaxAmount(), subTaxAmount), + addLogWithAddStockVo.getCurStockNum()), 6)); + addLogWithAddStockVo.setCreateTime(vo.getCreateTime()); + addLogWithAddStockVo.setBizId(vo.getBizId()); + addLogWithAddStockVo.setBizDetailId(vo.getBizDetailId()); + addLogWithAddStockVo.setBizCode(vo.getBizCode()); + addLogWithAddStockVo.setBizType(vo.getBizType()); + + productStockLogService.addLogWithSubStock(addLogWithAddStockVo); + + ProductStockChangeDto stockChange = new ProductStockChangeDto(); + stockChange.setScId(vo.getScId()); + stockChange.setProductId(vo.getProductId()); + stockChange.setNum(vo.getStockNum()); + stockChange.setTaxAmount(subTaxAmount); + stockChange.setCurTaxPrice(addLogWithAddStockVo.getCurTaxPrice()); + + SubStockEvent subStockEvent = new SubStockEvent(this, stockChange); + ApplicationUtil.publishEvent(subStockEvent); + + return stockChange; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public StockCostAdjustDiffDto stockCostAdjust(StockCostAdjustVo vo) { + + Product product = productService.findById(vo.getProductId()); + if (product.getProductType() != ProductType.NORMAL) { + throw new DefaultClientException( + "只有商品类型为【" + ProductType.NORMAL.getDesc() + "】的商品支持库存成本调整!"); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(ProductStock.class) + .eq(ProductStock::getProductId, vo.getProductId()).eq(ProductStock::getScId, vo.getScId()); + + ProductStock productStock = getBaseMapper().selectOne(queryWrapper); + + if (productStock == null) { + // 没有库存,跳过 + return new StockCostAdjustDiffDto(); + } + + BigDecimal taxPrice = NumberUtil.getNumber(vo.getTaxPrice(), 6); + + StockCostAdjustDiffDto result = new StockCostAdjustDiffDto(); + result.setStockNum(productStock.getStockNum()); + result.setOriPrice(NumberUtil.getNumber(productStock.getTaxPrice(), 2)); + result.setDiffAmount(NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.sub(taxPrice, productStock.getTaxPrice()), + productStock.getStockNum()), 2)); + + getBaseMapper().stockCostAdjust(vo.getProductId(), vo.getScId(), taxPrice); + + AddLogWithStockCostAdjustVo logVo = new AddLogWithStockCostAdjustVo(); + logVo.setProductId(vo.getProductId()); + logVo.setScId(vo.getScId()); + logVo.setTaxAmount(result.getDiffAmount()); + logVo.setOriStockNum(productStock.getStockNum()); + logVo.setOriTaxPrice(productStock.getTaxPrice()); + logVo.setCurTaxPrice(taxPrice); + logVo.setCreateTime(vo.getCreateTime()); + logVo.setBizId(vo.getBizId()); + logVo.setBizDetailId(vo.getBizDetailId()); + logVo.setBizCode(vo.getBizCode()); + + productStockLogService.addLogWithStockCostAdjust(logVo); + + return result; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustReasonServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustReasonServiceImpl.java new file mode 100644 index 0000000..a5e81b0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustReasonServiceImpl.java @@ -0,0 +1,174 @@ +package com.lframework.xingyun.sc.impl.stock.adjust; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.StockAdjustReasonMapper; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustReasonService; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.CreateStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.QueryStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.StockAdjustReasonSelectorVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.UpdateStockAdjustReasonVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StockAdjustReasonServiceImpl extends + BaseMpServiceImpl + implements StockAdjustReasonService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryStockAdjustReasonVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryStockAdjustReasonVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + StockAdjustReasonSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = StockAdjustReason.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public StockAdjustReason findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "停用库存调整原因,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockAdjustReason.class) + .set(StockAdjustReason::getAvailable, Boolean.FALSE).in(StockAdjustReason::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "启用库存调整原因,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockAdjustReason.class) + .set(StockAdjustReason::getAvailable, Boolean.TRUE).in(StockAdjustReason::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "新增库存调整原因,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateStockAdjustReasonVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(StockAdjustReason.class) + .eq(StockAdjustReason::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + StockAdjustReason data = new StockAdjustReason(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "修改库存调整原因,ID:{}, 编号:{}", params = {"#id", + "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateStockAdjustReasonVo vo) { + + StockAdjustReason data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整原因不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(StockAdjustReason.class) + .eq(StockAdjustReason::getCode, vo.getCode()).ne(StockAdjustReason::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + StockAdjustReason.class) + .set(StockAdjustReason::getCode, vo.getCode()).set(StockAdjustReason::getName, vo.getName()) + .set(StockAdjustReason::getAvailable, vo.getAvailable()) + .set(StockAdjustReason::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(StockAdjustReason::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = StockAdjustReason.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetDetailServiceImpl.java new file mode 100644 index 0000000..d11b1d2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.stock.adjust; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.StockAdjustSheetDetail; +import com.lframework.xingyun.sc.mappers.StockAdjustSheetDetailMapper; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class StockAdjustSheetDetailServiceImpl + extends BaseMpServiceImpl + implements StockAdjustSheetDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetServiceImpl.java new file mode 100644 index 0000000..53ec0fc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockAdjustSheetServiceImpl.java @@ -0,0 +1,738 @@ +package com.lframework.xingyun.sc.impl.stock.adjust; + +import cn.hutool.core.lang.Dict; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.entity.OrderTimeLine; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.service.OrderTimeLineService; +import com.lframework.xingyun.sc.bo.stock.adjust.stock.StockAdjustSheetFullBo; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockAdjustSheet; +import com.lframework.xingyun.sc.entity.StockAdjustSheetDetail; +import com.lframework.xingyun.sc.enums.*; +import com.lframework.xingyun.sc.mappers.StockAdjustSheetMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustSheetDetailService; +import com.lframework.xingyun.sc.service.stock.adjust.StockAdjustSheetService; +import com.lframework.xingyun.sc.utils.WebUtils; +import com.lframework.xingyun.sc.vo.retail.out.ApprovePassRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.ApproveRefuseRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.ApprovePassStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.ApproveRefuseStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.BatchApprovePassStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.BatchApproveRefuseStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.CreateStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.StockAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.UpdateStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + + +import net.minidev.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StockAdjustSheetServiceImpl extends + BaseMpServiceImpl + implements StockAdjustSheetService { + + @Autowired + private StockAdjustSheetDetailService stockCostAdjustSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private ProductPurchaseService productPurchaseService; + + @Autowired + private ProductService productService; + + @Autowired + private UserDetailsService userDetailsService; + + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryStockAdjustSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryStockAdjustSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public StockAdjustSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "新增库存调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建调整单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateStockAdjustSheetVo vo) { + + StockAdjustSheet data = new StockAdjustSheet(); + data.setId(IdUtil.getId()); + data.setCode(generateCodeService.generate(GenerateCodeTypePool.STOCK_ADJUST_SHEET)); + + this.create(data, vo); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "修改库存调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改调整单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateStockAdjustSheetVo vo) { + + StockAdjustSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整单不存在!"); + } + + if (data.getStatus() != StockAdjustSheetStatus.CREATED + && data.getStatus() != StockAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存调整单已审核通过,无法修改!"); + } + + throw new DefaultClientException("库存调整单无法修改!"); + } + + // 删除出库单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + StockAdjustSheetDetail.class) + .eq(StockAdjustSheetDetail::getSheetId, data.getId()); + stockCostAdjustSheetDetailService.remove(deleteDetailWrapper); + + this.create(data, vo); + + data.setStatus(StockAdjustSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(StockAdjustSheetStatus.CREATED); + statusList.add(StockAdjustSheetStatus.APPROVE_REFUSE); + + Wrapper updateSheetWrapper = Wrappers.lambdaUpdate( + StockAdjustSheet.class) + .set(StockAdjustSheet::getApproveBy, null) + .set(StockAdjustSheet::getApproveTime, null) + .set(StockAdjustSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(StockAdjustSheet::getId, data.getId()) + .in(StockAdjustSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(data, updateSheetWrapper) != 1) { + throw new DefaultClientException("库存调整单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "删除库存调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + StockAdjustSheet data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整单不存在!"); + } + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的库存调整单不允许执行删除操作!"); + } + + Wrapper deleteWrapper = Wrappers.lambdaQuery(StockAdjustSheet.class) + .eq(StockAdjustSheet::getId, id) + .in(StockAdjustSheet::getStatus, StockAdjustSheetStatus.CREATED, + StockAdjustSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().delete(deleteWrapper) != 1) { + throw new DefaultClientException("库存调整单信息已过期,请刷新重试!"); + } + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + StockAdjustSheetDetail.class) + .eq(StockAdjustSheetDetail::getSheetId, id); + stockCostAdjustSheetDetailService.remove(deleteDetailWrapper); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + StockAdjustSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个库存调整单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "审核通过库存调整单,ID:{}", params = {"#vo.id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassStockAdjustSheetVo vo) { + + StockAdjustSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整单不存在!"); + } + + if (data.getStatus() != StockAdjustSheetStatus.CREATED + && data.getStatus() != StockAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存调整单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("库存调整单无法审核通过!"); + } + + LocalDateTime now = LocalDateTime.now(); + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockAdjustSheet.class) + .eq(StockAdjustSheet::getId, data.getId()) + .in(StockAdjustSheet::getStatus, StockAdjustSheetStatus.CREATED, + StockAdjustSheetStatus.APPROVE_REFUSE) + .set(StockAdjustSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(StockAdjustSheet::getApproveTime, now) + .set(StockAdjustSheet::getStatus, StockAdjustSheetStatus.APPROVE_PASS) + .set(StockAdjustSheet::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("库存调整单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + StockAdjustSheetDetail.class) + .eq(StockAdjustSheetDetail::getSheetId, data.getId()) + .orderByAsc(StockAdjustSheetDetail::getOrderNo); + List details = stockCostAdjustSheetDetailService.list( + queryDetailWrapper); + + for (StockAdjustSheetDetail detail : details) { + Product product = productService.findById(detail.getProductId()); + ProductPurchase productPurchase = productPurchaseService.getById(product.getId()); + if (data.getBizType() == StockAdjustSheetBizType.IN) { + // 入库 + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(product.getId()); + addProductStockVo.setScId(data.getScId()); + addProductStockVo.setStockNum(detail.getStockNum()); + addProductStockVo.setDefaultTaxPrice(productPurchase.getPrice()); + addProductStockVo.setCreateTime(now); + addProductStockVo.setBizId(data.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(data.getCode()); + addProductStockVo.setBizType(ProductStockBizType.STOCK_ADJUST.getCode()); + + productStockService.addStock(addProductStockVo); + } else { + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(product.getId()); + subProductStockVo.setScId(data.getScId()); + subProductStockVo.setStockNum(detail.getStockNum()); + subProductStockVo.setCreateTime(now); + subProductStockVo.setBizId(data.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(data.getCode()); + subProductStockVo.setBizType(ProductStockBizType.STOCK_ADJUST.getCode()); + + productStockService.subStock(subProductStockVo); + } + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassStockAdjustSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassStockAdjustSheetVo approvePassVo = new ApprovePassStockAdjustSheetVo(); + approvePassVo.setId(id); + + try { + StockAdjustSheetService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个库存调整单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateStockAdjustSheetVo vo) { + + StockAdjustSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassStockAdjustSheetVo approvePassVo = new ApprovePassStockAdjustSheetVo(); + approvePassVo.setId(id); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return id; + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "审核拒绝库存调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseStockAdjustSheetVo vo) { + + StockAdjustSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整单不存在!"); + } + + if (data.getStatus() != StockAdjustSheetStatus.CREATED + && data.getStatus() != StockAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存调整单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("库存调整单无法审核通过!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockAdjustSheet.class) + .eq(StockAdjustSheet::getId, data.getId()) + .in(StockAdjustSheet::getStatus, StockAdjustSheetStatus.CREATED, + StockAdjustSheetStatus.APPROVE_REFUSE) + .set(StockAdjustSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(StockAdjustSheet::getApproveTime, LocalDateTime.now()) + .set(StockAdjustSheet::getRefuseReason, vo.getRefuseReason()) + .set(StockAdjustSheet::getStatus, StockAdjustSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("库存调整单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseStockAdjustSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseStockAdjustSheetVo approveRefuseVo = new ApproveRefuseStockAdjustSheetVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + StockAdjustSheetService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个库存调整单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + + @Override + public PageResult queryStockAdjustByCondition(Integer pageIndex, + Integer pageSize, String scId, String condition) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryStockAdjustByCondition(scId, + condition); + PageResult pageResult = PageResultUtil.convert( + new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryStockAdjustList(Integer pageIndex, + Integer pageSize, QueryStockAdjustProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryStockAdjustList(vo); + PageResult pageResult = PageResultUtil.convert( + new PageInfo<>(datas)); + + return pageResult; + } + + + + @Override + public void cleanCacheByKey(Serializable key) { + + } + + private void create(StockAdjustSheet data, CreateStockAdjustSheetVo vo) { + + data.setScId(vo.getScId()); + data.setStatus(StockAdjustSheetStatus.CREATED); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + data.setBizType(EnumUtil.getByCode(StockAdjustSheetBizType.class, vo.getBizType())); + data.setReasonId(vo.getReasonId()); + + int productNum = 0; + BigDecimal diffAmount = BigDecimal.ZERO; + int orderNo = 1; + for (StockAdjustProductVo product : vo.getProducts()) { + StockAdjustSheetDetail detail = new StockAdjustSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(data.getId()); + detail.setProductId(product.getProductId()); + detail.setStockNum(product.getStockNum()); + detail.setDescription( + StringUtil.isBlank(product.getDescription()) ? StringPool.EMPTY_STR + : product.getDescription()); + detail.setOrderNo(orderNo++); + productNum++; + + stockCostAdjustSheetDetailService.save(detail); + } + } + + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "发送库存调整单审批流程给ydool系统,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_SEND, orderId = "#id", name = "发送库存调整单审批流程给ydool系统") + @Transactional(rollbackFor = Exception.class) + @Override + public InvokeResult sendApprove(String id) { + StockAdjustSheetFullDto order = this.getDetail(id); + if (order == null) { + throw new DefaultClientException("库存调整单不存在!"); + } + + StockAdjustSheetFullBo bo = new StockAdjustSheetFullBo(order); + + if (order.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存调整单已审核通过,无需再次审核!"); + } + if (order.getStatus() == StockAdjustSheetStatus.APPROVE_ING) { + throw new DefaultClientException("库存调整单正在审核中,请勿重复推送"); + } + + String createCode = bo.getCreateCode(); + if (StringUtil.isBlank(createCode)) { + throw new DefaultClientException("创建人不存在,无法发起审核!"); + } + + List details = bo.getDetails(); + //将商品编号、商品名称、库存数量、采购数量、采购含税金额从details中提取出来 + List list = details.stream().map(detail -> { + //将商品编号、商品名称、库存数量、采购数量、采购含税金额从detail中提取并返回 + return Dict.create() + .set("goods_number", detail.getProductCode()) + .set("goods_name", detail.getProductName()) + .set("number", detail.getStockNum()) + .set("inventory", detail.getCurStockNum()); + }).collect(Collectors.toList()); + Dict dict = Dict.create(); + dict.set("user_id", createCode) + .set("order_id", id) + .set("biz_type", StockAdjustSheetBizType.descByCode(bo.getBizType())) + .set("reason_name", bo.getReasonName()) + .set("audit_person_ids", "120,262") + .set("push_person_ids", "120,262") + .set("remark", bo.getDescription()) + .set("ghd_goodlist_info", list); + + String jsonString = JSONObject.toJSONString(dict); + String json = HttpUtil.post("https://nb.ydool.com/api/ydoolerp/erp_ajax.ashx/send_kc", jsonString); + // 修改订单状态 + StockAdjustSheet stockAdjustSheet = this.baseMapper.selectById(id); + stockAdjustSheet.setStatus(StockAdjustSheetStatus.APPROVE_ING); + int update = getBaseMapper().updateById(stockAdjustSheet); + InvokeResult success = InvokeResultBuilder.success(); + success.setMsg(jsonString); + OpLogUtil.setVariable("code", order.getCode()); + OpLogUtil.setVariable("id", id); + OpLogUtil.setExtra(dict); + return update > 0 ? success : InvokeResultBuilder.fail(jsonString); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void approve(YdoolApproveOrderVo vo) { + String status = vo.getStatus(); + if ("y".equals(status)) { + this.approvePass(vo.getId(), vo.getMsg()); + } else { + this.approveRefuse(vo.getId(), vo.getMsg()); + } + } + + @Override + public StockAdjustProductDto queryStockAdjustBySku(String scId, String sku) { + StockAdjustProductDto datas = getBaseMapper().queryStockAdjustBySku(scId, + sku); + return datas; + } + + @Transactional(rollbackFor = Exception.class) + public void approvePass(String id, String description) { + StockAdjustSheet data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整单不存在!"); + } + + if (data.getStatus() != StockAdjustSheetStatus.APPROVE_ING){ + throw new DefaultClientException("库存调整单无法审核通过!"); + } + + if (data.getStatus() != StockAdjustSheetStatus.CREATED + && data.getStatus() != StockAdjustSheetStatus.APPROVE_ING + && data.getStatus() != StockAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存调整单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("库存调整单无法审核通过!"); + } + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + LocalDateTime now = LocalDateTime.now(); + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockAdjustSheet.class) + .eq(StockAdjustSheet::getId, data.getId()) + .eq(StockAdjustSheet::getStatus, StockAdjustSheetStatus.APPROVE_ING) + .set(StockAdjustSheet::getApproveBy, user.getId()) + .set(StockAdjustSheet::getApproveTime, now) + .set(StockAdjustSheet::getStatus, StockAdjustSheetStatus.APPROVE_PASS) + .set(StockAdjustSheet::getDescription, + StringUtil.isBlank(description) ? StringPool.EMPTY_STR : description); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("库存调整单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + StockAdjustSheetDetail.class) + .eq(StockAdjustSheetDetail::getSheetId, data.getId()) + .orderByAsc(StockAdjustSheetDetail::getOrderNo); + List details = stockCostAdjustSheetDetailService.list( + queryDetailWrapper); + + for (StockAdjustSheetDetail detail : details) { + Product product = productService.findById(detail.getProductId()); + ProductPurchase productPurchase = productPurchaseService.getById(product.getId()); + if (data.getBizType() == StockAdjustSheetBizType.IN) { + // 入库 + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(product.getId()); + addProductStockVo.setScId(data.getScId()); + addProductStockVo.setStockNum(detail.getStockNum()); + addProductStockVo.setDefaultTaxPrice(productPurchase.getPrice()); + addProductStockVo.setCreateTime(now); + addProductStockVo.setBizId(data.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(data.getCode()); + addProductStockVo.setBizType(ProductStockBizType.STOCK_ADJUST.getCode()); + + productStockService.addStock(addProductStockVo); + } else { + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(product.getId()); + subProductStockVo.setScId(data.getScId()); + subProductStockVo.setStockNum(detail.getStockNum()); + subProductStockVo.setCreateTime(now); + subProductStockVo.setBizId(data.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(data.getCode()); + subProductStockVo.setBizType(ProductStockBizType.STOCK_ADJUST.getCode()); + + productStockService.subStock(subProductStockVo); + } + } + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApprovePassStockAdjustSheetVo vo = new ApprovePassStockAdjustSheetVo(); + vo.setId(id); + vo.setDescription(description); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核通过库存调整单,单号:%s", data.getCode())); + opLogs.setLogType(ScOpLogType.STOCK_ADJUST); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(data.getId()); + orderTimeLine.setContent("审核通过"); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_PASS); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + + + } + + @Transactional(rollbackFor = Exception.class) + public void approveRefuse(String id, String refuseReason) { + if (StringUtil.isBlank(refuseReason)) { + throw new InputErrorException("请输入拒绝理由!"); + } + + StockAdjustSheet data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存调整单不存在!"); + } + + if (data.getStatus() != StockAdjustSheetStatus.APPROVE_ING){ + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存调整单已审核通过,不允许继续执行审核!"); + } + + if (data.getStatus() == StockAdjustSheetStatus.APPROVE_REFUSE){ + throw new DefaultClientException("库存调整单已审核拒绝,不允许继续执行审核!"); + } + + throw new DefaultClientException("库存调整单无法审核拒绝!"); + } + + AbstractUserDetails user = userDetailsService.loadUserByUsername("yanxiaomao1"); + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockAdjustSheet.class) + .eq(StockAdjustSheet::getId, data.getId()) + .eq(StockAdjustSheet::getStatus, StockAdjustSheetStatus.APPROVE_ING) + .set(StockAdjustSheet::getApproveBy, user.getId()) + .set(StockAdjustSheet::getApproveTime, LocalDateTime.now()) + .set(StockAdjustSheet::getRefuseReason, refuseReason) + .set(StockAdjustSheet::getStatus, StockAdjustSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("库存调整单信息已过期,请刷新重试!"); + } + + OpLogs opLogs = new OpLogs(); +// OpLogUtil.setVariable("code", order.getCode()); + ApproveRefuseStockAdjustSheetVo vo = new ApproveRefuseStockAdjustSheetVo(); + vo.setId(id); + vo.setRefuseReason(refuseReason); +// OpLogUtil.setExtra(vo); + opLogs.setExtra(JSONUtil.toJsonStr(vo)); + opLogs.setName(String.format("审核拒绝库存调整单,单号:%s", data.getCode())); + opLogs.setLogType(ScOpLogType.STOCK_ADJUST); + opLogs.setCreateBy(user.getName()); + opLogs.setCreateById(user.getId()); + opLogs.setIp(WebUtils.getRemoteIpAddress()); + opLogs.setCreateTime(LocalDateTime.now()); + OpLogsService opLogsService = SpringUtil.getBean(OpLogsService.class); + opLogsService.save(opLogs); + + OrderTimeLine orderTimeLine = new OrderTimeLine(); + orderTimeLine.setOrderId(data.getId()); + orderTimeLine.setContent(String.format("审核拒绝,拒绝理由:%s", refuseReason)); + orderTimeLine.setBizType(OrderTimeLineBizType.APPROVE_RETURN); + orderTimeLine.setCreateBy(user.getName()); + orderTimeLine.setCreateById(user.getId()); + orderTimeLine.setCreateTime(LocalDateTime.now()); + OrderTimeLineService orderTimeLineService = SpringUtil.getBean(OrderTimeLineService.class); + orderTimeLineService.save(orderTimeLine); + } + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetDetailServiceImpl.java new file mode 100644 index 0000000..207331e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.stock.adjust; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheetDetail; +import com.lframework.xingyun.sc.mappers.StockCostAdjustSheetDetailMapper; +import com.lframework.xingyun.sc.service.stock.adjust.StockCostAdjustSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class StockCostAdjustSheetDetailServiceImpl + extends BaseMpServiceImpl + implements StockCostAdjustSheetDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetServiceImpl.java new file mode 100644 index 0000000..2ec7fb2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/adjust/StockCostAdjustSheetServiceImpl.java @@ -0,0 +1,478 @@ +package com.lframework.xingyun.sc.impl.stock.adjust; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustDiffDto; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheet; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheetDetail; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.StockCostAdjustSheetStatus; +import com.lframework.xingyun.sc.mappers.StockCostAdjustSheetMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.adjust.StockCostAdjustSheetDetailService; +import com.lframework.xingyun.sc.service.stock.adjust.StockCostAdjustSheetService; +import com.lframework.xingyun.sc.vo.stock.StockCostAdjustVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.ApprovePassStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.ApproveRefuseStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.BatchApprovePassStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.BatchApproveRefuseStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.CreateStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.StockCostAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.UpdateStockCostAdjustSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StockCostAdjustSheetServiceImpl extends + BaseMpServiceImpl + implements StockCostAdjustSheetService { + + @Autowired + private StockCostAdjustSheetDetailService stockCostAdjustSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private ProductPurchaseService productPurchaseService; + + @Autowired + private ProductService productService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryStockCostAdjustSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryStockCostAdjustSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public StockCostAdjustSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "新增库存成本调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建调整单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateStockCostAdjustSheetVo vo) { + + StockCostAdjustSheet data = new StockCostAdjustSheet(); + data.setId(IdUtil.getId()); + data.setCode(generateCodeService.generate(GenerateCodeTypePool.STOCK_COST_ADJUST_SHEET)); + + this.create(data, vo); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "修改库存成本调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改调整单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateStockCostAdjustSheetVo vo) { + + StockCostAdjustSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存成本调整单不存在!"); + } + + if (data.getStatus() != StockCostAdjustSheetStatus.CREATED + && data.getStatus() != StockCostAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockCostAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存成本调整单已审核通过,无法修改!"); + } + + throw new DefaultClientException("库存成本调整单无法修改!"); + } + + // 删除出库单明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + StockCostAdjustSheetDetail.class) + .eq(StockCostAdjustSheetDetail::getSheetId, data.getId()); + stockCostAdjustSheetDetailService.remove(deleteDetailWrapper); + + this.create(data, vo); + + data.setStatus(StockCostAdjustSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(StockCostAdjustSheetStatus.CREATED); + statusList.add(StockCostAdjustSheetStatus.APPROVE_REFUSE); + + Wrapper updateSheetWrapper = Wrappers.lambdaUpdate( + StockCostAdjustSheet.class) + .set(StockCostAdjustSheet::getApproveBy, null) + .set(StockCostAdjustSheet::getApproveTime, null) + .set(StockCostAdjustSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(StockCostAdjustSheet::getId, data.getId()) + .in(StockCostAdjustSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(data, updateSheetWrapper) != 1) { + throw new DefaultClientException("库存成本调整单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "删除库存成本调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + StockCostAdjustSheet data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存成本调整单不存在!"); + } + + if (data.getStatus() == StockCostAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的库存成本调整单不允许执行删除操作!"); + } + + Wrapper deleteWrapper = Wrappers.lambdaQuery(StockCostAdjustSheet.class) + .eq(StockCostAdjustSheet::getId, id) + .in(StockCostAdjustSheet::getStatus, StockCostAdjustSheetStatus.CREATED, + StockCostAdjustSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().delete(deleteWrapper) != 1) { + throw new DefaultClientException("库存成本调整单信息已过期,请刷新重试!"); + } + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + StockCostAdjustSheetDetail.class) + .eq(StockCostAdjustSheetDetail::getSheetId, id); + stockCostAdjustSheetDetailService.remove(deleteDetailWrapper); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + StockCostAdjustSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个库存成本调整单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "审核通过库存成本调整单,ID:{}", params = {"#vo.id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassStockCostAdjustSheetVo vo) { + + StockCostAdjustSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存成本调整单不存在!"); + } + + if (data.getStatus() != StockCostAdjustSheetStatus.CREATED + && data.getStatus() != StockCostAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockCostAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存成本调整单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("库存成本调整单无法审核通过!"); + } + + LocalDateTime now = LocalDateTime.now(); + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockCostAdjustSheet.class) + .eq(StockCostAdjustSheet::getId, data.getId()) + .in(StockCostAdjustSheet::getStatus, StockCostAdjustSheetStatus.CREATED, + StockCostAdjustSheetStatus.APPROVE_REFUSE) + .set(StockCostAdjustSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(StockCostAdjustSheet::getApproveTime, now) + .set(StockCostAdjustSheet::getStatus, StockCostAdjustSheetStatus.APPROVE_PASS) + .set(StockCostAdjustSheet::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("库存成本调整单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + StockCostAdjustSheetDetail.class) + .eq(StockCostAdjustSheetDetail::getSheetId, data.getId()) + .orderByAsc(StockCostAdjustSheetDetail::getOrderNo); + List details = stockCostAdjustSheetDetailService.list( + queryDetailWrapper); + + BigDecimal totalDiffAmount = BigDecimal.ZERO; + for (StockCostAdjustSheetDetail detail : details) { + Product product = productService.findById(detail.getProductId()); + StockCostAdjustVo adjustVo = new StockCostAdjustVo(); + adjustVo.setProductId(detail.getProductId()); + adjustVo.setScId(data.getScId()); + adjustVo.setTaxPrice(detail.getPrice()); + adjustVo.setTaxRate(product.getTaxRate()); + adjustVo.setCreateTime(now); + adjustVo.setBizId(data.getId()); + adjustVo.setBizDetailId(detail.getId()); + adjustVo.setBizCode(data.getCode()); + + StockCostAdjustDiffDto diff = productStockService.stockCostAdjust(adjustVo); + detail.setStockNum(diff.getStockNum()); + detail.setOriPrice(diff.getOriPrice()); + detail.setDiffAmount(diff.getDiffAmount()); + + stockCostAdjustSheetDetailService.updateById(detail); + + totalDiffAmount = NumberUtil.add(totalDiffAmount, detail.getDiffAmount()); + } + + updateWrapper = Wrappers.lambdaUpdate(StockCostAdjustSheet.class) + .eq(StockCostAdjustSheet::getId, data.getId()) + .set(StockCostAdjustSheet::getDiffAmount, totalDiffAmount); + this.update(updateWrapper); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassStockCostAdjustSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassStockCostAdjustSheetVo approvePassVo = new ApprovePassStockCostAdjustSheetVo(); + approvePassVo.setId(id); + + try { + StockCostAdjustSheetService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个库存成本调整单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateStockCostAdjustSheetVo vo) { + + StockCostAdjustSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassStockCostAdjustSheetVo approvePassVo = new ApprovePassStockCostAdjustSheetVo(); + approvePassVo.setId(id); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return id; + } + + @OpLog(type = ScOpLogType.STOCK_ADJUST, name = "审核拒绝库存成本调整单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseStockCostAdjustSheetVo vo) { + + StockCostAdjustSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("库存成本调整单不存在!"); + } + + if (data.getStatus() != StockCostAdjustSheetStatus.CREATED + && data.getStatus() != StockCostAdjustSheetStatus.APPROVE_REFUSE) { + + if (data.getStatus() == StockCostAdjustSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("库存成本调整单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("库存成本调整单无法审核通过!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(StockCostAdjustSheet.class) + .eq(StockCostAdjustSheet::getId, data.getId()) + .in(StockCostAdjustSheet::getStatus, StockCostAdjustSheetStatus.CREATED, + StockCostAdjustSheetStatus.APPROVE_REFUSE) + .set(StockCostAdjustSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(StockCostAdjustSheet::getApproveTime, LocalDateTime.now()) + .set(StockCostAdjustSheet::getRefuseReason, vo.getRefuseReason()) + .set(StockCostAdjustSheet::getStatus, StockCostAdjustSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("库存成本调整单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseStockCostAdjustSheetVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseStockCostAdjustSheetVo approveRefuseVo = new ApproveRefuseStockCostAdjustSheetVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + StockCostAdjustSheetService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个库存成本调整单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + + @Override + public PageResult queryStockCostAdjustByCondition(Integer pageIndex, + Integer pageSize, String scId, String condition) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryStockCostAdjustByCondition(scId, + condition); + PageResult pageResult = PageResultUtil.convert( + new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryStockCostAdjustList(Integer pageIndex, + Integer pageSize, QueryStockCostAdjustProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryStockCostAdjustList(vo); + PageResult pageResult = PageResultUtil.convert( + new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } + + private void create(StockCostAdjustSheet data, CreateStockCostAdjustSheetVo vo) { + + data.setScId(vo.getScId()); + data.setStatus(StockCostAdjustSheetStatus.CREATED); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + int productNum = 0; + BigDecimal diffAmount = BigDecimal.ZERO; + int orderNo = 1; + for (StockCostAdjustProductVo product : vo.getProducts()) { + StockCostAdjustSheetDetail detail = new StockCostAdjustSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(data.getId()); + detail.setProductId(product.getProductId()); + ProductStock productStock = productStockService.getByProductIdAndScId(product.getProductId(), + data.getScId()); + ProductPurchase productPurchase = productPurchaseService.getById(product.getProductId()); + detail.setStockNum(productStock == null ? 0 : productStock.getStockNum()); + detail.setPurchasePrice(productPurchase.getPrice()); + detail.setOriPrice( + productStock == null ? BigDecimal.ZERO + : NumberUtil.getNumber(productStock.getTaxPrice(), 2)); + detail.setPrice(product.getPrice()); + detail.setDiffAmount(NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.sub(detail.getPrice(), detail.getOriPrice()), + detail.getStockNum()), 2)); + detail.setDescription( + StringUtil.isBlank(product.getDescription()) ? StringPool.EMPTY_STR + : product.getDescription()); + detail.setOrderNo(orderNo++); + productNum++; + + diffAmount = NumberUtil.add(diffAmount, detail.getDiffAmount()); + + stockCostAdjustSheetDetailService.save(detail); + } + + data.setProductNum(productNum); + data.setDiffAmount(diffAmount); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetDetailServiceImpl.java new file mode 100644 index 0000000..6e3d918 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.PreTakeStockSheetDetail; +import com.lframework.xingyun.sc.mappers.PreTakeStockSheetDetailMapper; +import com.lframework.xingyun.sc.service.stock.take.PreTakeStockSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class PreTakeStockSheetDetailServiceImpl + extends BaseMpServiceImpl + implements PreTakeStockSheetDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetServiceImpl.java new file mode 100644 index 0000000..e441404 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/PreTakeStockSheetServiceImpl.java @@ -0,0 +1,246 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockProductDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.QueryPreTakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.sc.entity.PreTakeStockSheetDetail; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.PreTakeStockSheetMapper; +import com.lframework.xingyun.sc.service.stock.take.PreTakeStockSheetDetailService; +import com.lframework.xingyun.sc.service.stock.take.PreTakeStockSheetService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockSheetService; +import com.lframework.xingyun.sc.vo.stock.take.pre.CreatePreTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.PreTakeStockProductVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.PreTakeStockSheetSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockProductVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.UpdatePreTakeStockSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PreTakeStockSheetServiceImpl extends + BaseMpServiceImpl + implements PreTakeStockSheetService { + + @Autowired + private PreTakeStockSheetDetailService preTakeStockSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private TakeStockSheetService takeStockSheetService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryPreTakeStockSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryPreTakeStockSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + PreTakeStockSheetSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PreTakeStockSheetFullDto getDetail(String id) { + + PreTakeStockSheetFullDto data = getBaseMapper().getDetail(id); + if (data == null) { + throw new DefaultClientException("预先盘点单不存在!"); + } + + return data; + } + + @Override + public List getProducts(String id, String planId) { + + return getBaseMapper().getProducts(id, planId); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "新增预先盘点单,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreatePreTakeStockSheetVo vo) { + + PreTakeStockSheet data = new PreTakeStockSheet(); + data.setId(IdUtil.getId()); + data.setCode(generateCodeService.generate(GenerateCodeTypePool.PRE_TAKE_STOCK_SHEET)); + data.setScId(vo.getScId()); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + data.setTakeStatus(EnumUtil.getByCode(PreTakeStockSheetStatus.class, vo.getTakeStatus())); + + getBaseMapper().insert(data); + + int orderNo = 1; + for (PreTakeStockProductVo product : vo.getProducts()) { + PreTakeStockSheetDetail detail = new PreTakeStockSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(data.getId()); + detail.setProductId(product.getProductId()); + detail.setFirstNum(product.getFirstNum()); + detail.setSecondNum(product.getSecondNum()); + detail.setRandNum(product.getRandNum()); + detail.setOrderNo(orderNo++); + + preTakeStockSheetDetailService.save(detail); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "修改预先盘点单,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdatePreTakeStockSheetVo vo) { + + PreTakeStockSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("预先盘点单不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + PreTakeStockSheet.class) + .set(PreTakeStockSheet::getScId, vo.getScId()).set(PreTakeStockSheet::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(PreTakeStockSheet::getTakeStatus, + EnumUtil.getByCode(PreTakeStockSheetStatus.class, vo.getTakeStatus())) + .eq(PreTakeStockSheet::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + PreTakeStockSheetDetail.class) + .eq(PreTakeStockSheetDetail::getSheetId, data.getId()); + preTakeStockSheetDetailService.remove(deleteDetailWrapper); + + int orderNo = 1; + for (PreTakeStockProductVo product : vo.getProducts()) { + PreTakeStockSheetDetail detail = new PreTakeStockSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(data.getId()); + detail.setProductId(product.getProductId()); + detail.setFirstNum(product.getFirstNum()); + detail.setSecondNum(product.getSecondNum()); + detail.setRandNum(product.getRandNum()); + detail.setOrderNo(orderNo++); + + preTakeStockSheetDetailService.save(detail); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "删除预先盘点单,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + if (takeStockSheetService.hasRelatePreTakeStockSheet(id)) { + throw new DefaultClientException("已有库存盘点单关联此预先盘点单,不允许执行删除操作!"); + } + + getBaseMapper().deleteById(id); + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + PreTakeStockSheetDetail.class) + .eq(PreTakeStockSheetDetail::getSheetId, id); + preTakeStockSheetDetailService.remove(deleteDetailWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(List ids) { + + for (String id : ids) { + getThis(this.getClass()).deleteById(id); + } + } + + @Override + public PageResult queryPreTakeStockByCondition(Integer pageIndex, + Integer pageSize, String condition) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryPreTakeStockByCondition(condition); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryPreTakeStockList(Integer pageIndex, + Integer pageSize, QueryPreTakeStockProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryPreTakeStockList(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockConfigServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockConfigServiceImpl.java new file mode 100644 index 0000000..ace3db2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockConfigServiceImpl.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.mappers.TakeStockConfigMapper; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import com.lframework.xingyun.sc.vo.stock.take.config.UpdateTakeStockConfigVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class TakeStockConfigServiceImpl extends + BaseMpServiceImpl + implements TakeStockConfigService { + + @Cacheable(value = TakeStockConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'", unless = "#result == null") + @Override + public TakeStockConfig get() { + + return getBaseMapper().selectOne(Wrappers.query()); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "修改盘点参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateTakeStockConfigVo vo) { + + TakeStockConfig data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点参数不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + TakeStockConfig.class) + .set(TakeStockConfig::getShowProduct, vo.getShowProduct()) + .set(TakeStockConfig::getShowStock, vo.getShowStock()) + .set(TakeStockConfig::getAutoChangeStock, vo.getAutoChangeStock()) + .set(TakeStockConfig::getAllowChangeNum, vo.getAllowChangeNum()) + .set(TakeStockConfig::getCancelHours, vo.getCancelHours()) + .eq(TakeStockConfig::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = TakeStockConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + 'config'") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanDetailServiceImpl.java new file mode 100644 index 0000000..42b78ec --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanDetailServiceImpl.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.sc.dto.stock.take.plan.GetTakeStockPlanDetailProductDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.entity.TakeStockPlanDetail; +import com.lframework.xingyun.sc.mappers.TakeStockPlanDetailMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanDetailService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class TakeStockPlanDetailServiceImpl extends + BaseMpServiceImpl + implements TakeStockPlanDetailService { + + @Autowired + private ProductStockService productStockService; + + @Autowired + private TakeStockPlanService takeStockPlanService; + + @Override + public GetTakeStockPlanDetailProductDto getByPlanIdAndProductId(String planId, String productId) { + + return getBaseMapper().getByPlanIdAndProductId(planId, productId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void savePlanDetailBySimple(String planId, List productIds) { + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(planId); + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + TakeStockPlanDetail.class) + .eq(TakeStockPlanDetail::getPlanId, planId).orderByAsc(TakeStockPlanDetail::getOrderNo); + + List planDetails = getBaseMapper().selectList(queryDetailWrapper); + + int orderNo = planDetails.size() + 1; + for (String productId : productIds) { + if (planDetails.stream().anyMatch(t -> t.getProductId().equals(productId))) { + continue; + } + + TakeStockPlanDetail detail = new TakeStockPlanDetail(); + detail.setId(IdUtil.getId()); + detail.setPlanId(planId); + detail.setProductId(productId); + + ProductStock productStock = productStockService.getByProductIdAndScId(productId, + takeStockPlan.getScId()); + detail.setStockNum(productStock == null ? 0 : productStock.getStockNum()); + + detail.setDescription(StringPool.EMPTY_STR); + detail.setOrderNo(orderNo++); + getBaseMapper().insert(detail); + } + } + + @Override + public List getDetailsByPlanId(String planId) { + + return getBaseMapper().getDetailsByPlanId(planId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateOriTakeNum(String planId, String productId, Integer num) { + + getBaseMapper().updateOriTakeNum(planId, productId, num); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanServiceImpl.java new file mode 100644 index 0000000..eeadbe6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockPlanServiceImpl.java @@ -0,0 +1,490 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.entity.ProductPurchase; +import com.lframework.xingyun.basedata.enums.ProductType; +import com.lframework.xingyun.basedata.service.product.ProductPurchaseService; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.basedata.vo.product.info.QueryProductVo; +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import com.lframework.xingyun.core.events.stock.AddStockEvent; +import com.lframework.xingyun.core.events.stock.SubStockEvent; +import com.lframework.xingyun.core.events.stock.take.DeleteTakeStockPlanEvent; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.stock.take.plan.QueryTakeStockPlanProductDto; +import com.lframework.xingyun.sc.dto.stock.take.plan.TakeStockPlanFullDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.entity.TakeStockPlanDetail; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import com.lframework.xingyun.sc.mappers.TakeStockPlanDetailMapper; +import com.lframework.xingyun.sc.mappers.TakeStockPlanMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockConfigService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanDetailService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockSheetService; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.CancelTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.CreateTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.HandleTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.QueryTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.TakeStockPlanSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.UpdateTakeStockPlanVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.components.qrtz.QrtzJob; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.quartz.JobExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class TakeStockPlanServiceImpl extends BaseMpServiceImpl + implements TakeStockPlanService { + + @Autowired + private TakeStockPlanDetailService takeStockPlanDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private ProductService productService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private TakeStockConfigService takeStockConfigService; + + @Autowired + private TakeStockSheetService takeStockSheetService; + + @Autowired + private ProductPurchaseService productPurchaseService; + + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryTakeStockPlanVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryTakeStockPlanVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + TakeStockPlanSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public TakeStockPlanFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "新增盘点任务,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateTakeStockPlanVo vo) { + + TakeStockPlan data = new TakeStockPlan(); + data.setId(IdUtil.getId()); + data.setCode(generateCodeService.generate(GenerateCodeTypePool.TAKE_STOCK_PLAN)); + data.setScId(vo.getScId()); + data.setTakeType(EnumUtil.getByCode(TakeStockPlanType.class, vo.getTakeType())); + if (data.getTakeType() == TakeStockPlanType.CATEGORY + || data.getTakeType() == TakeStockPlanType.BRAND) { + data.setBizId(StringUtil.join(",", vo.getBizIds())); + } + + data.setTakeStatus(TakeStockPlanStatus.CREATED); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + List products = null; + if (data.getTakeType() != TakeStockPlanType.SIMPLE) { + // 单品盘点不生成明细 + if (data.getTakeType() == TakeStockPlanType.ALL) { + // 全场盘点 + // 将所有商品添加明细 + QueryProductVo queryProductVo = new QueryProductVo(); + queryProductVo.setAvailable(Boolean.TRUE); + queryProductVo.setProductType(ProductType.NORMAL.getCode()); + Integer count = productService.queryCount(queryProductVo); + if (count > 2000) { + throw new DefaultClientException( + TakeStockPlanType.ALL.getDesc() + "最多支持2000个商品,当前系统内已经超过2000个商品,无法进行" + + TakeStockPlanType.ALL.getDesc()); + } + products = productService.query(queryProductVo); + } else if (data.getTakeType() == TakeStockPlanType.CATEGORY) { + // 类目盘点 + products = productService.getByCategoryIds(vo.getBizIds(), ProductType.NORMAL.getCode()); + } else if (data.getTakeType() == TakeStockPlanType.BRAND) { + // 品牌盘点 + products = productService.getByBrandIds(vo.getBizIds(), ProductType.NORMAL.getCode()); + } + } + + if (data.getTakeType() != TakeStockPlanType.SIMPLE && CollectionUtil.isEmpty(products)) { + throw new DefaultClientException("没有查询到商品信息,无法生成盘点任务!"); + } + + if (products != null) { + List productIds = products.stream().map(Product::getId) + .collect(Collectors.toList()); + List productStocks = productStockService.getByProductIdsAndScId(productIds, + vo.getScId(), ProductType.NORMAL.getCode()); + int orderNo = 1; + for (Product product : products) { + ProductStock productStock = productStocks.stream() + .filter(t -> t.getProductId().equals(product.getId())) + .findFirst().orElse(null); + + TakeStockPlanDetail detail = new TakeStockPlanDetail(); + detail.setId(IdUtil.getId()); + detail.setPlanId(data.getId()); + detail.setProductId(product.getId()); + + detail.setStockNum(productStock == null ? 0 : productStock.getStockNum()); + detail.setTotalOutNum(0); + detail.setTotalInNum(0); + detail.setOrderNo(orderNo++); + + takeStockPlanDetailService.save(detail); + } + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "修改盘点任务,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateTakeStockPlanVo vo) { + + TakeStockPlan data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点任务不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockPlan.class) + .set(TakeStockPlan::getScId, vo.getScId()) + .set(TakeStockPlan::getDescription, vo.getDescription()) + .eq(TakeStockPlan::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @Override + public List getProducts(String planId) { + + return getBaseMapper().getProducts(planId); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "差异生成,盘点任务ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void createDiff(String id) { + + TakeStockPlan data = getBaseMapper().selectById(id); + if (data == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + // 判断是否还有没审核通过的盘点单 + if (takeStockSheetService.hasUnApprove(data.getId())) { + throw new DefaultClientException("盘点任务存在未审核的库存盘点单,请优先处理库存盘点单!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockPlan.class) + .set(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.DIFF_CREATED) + .eq(TakeStockPlan::getId, data.getId()) + .eq(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.CREATED); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点任务信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + TakeStockPlanDetail.class) + .eq(TakeStockPlanDetail::getPlanId, data.getId()) + .orderByAsc(TakeStockPlanDetail::getOrderNo); + List details = takeStockPlanDetailService.list(queryDetailWrapper); + if (CollectionUtil.isEmpty(details)) { + throw new DefaultClientException("盘点任务不存在商品信息,不允许执行差异生成操作!"); + } + for (TakeStockPlanDetail detail : details) { + if (detail.getOriTakeNum() != null) { + continue; + } + LambdaUpdateWrapper updateDetailWrapper = Wrappers.lambdaUpdate( + TakeStockPlanDetail.class).set(TakeStockPlanDetail::getOriTakeNum, 0) + .eq(TakeStockPlanDetail::getId, detail.getId()); + + takeStockPlanDetailService.update(updateDetailWrapper); + } + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "差异处理,盘点任务ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void handleDiff(HandleTakeStockPlanVo vo) { + + TakeStockPlan data = getBaseMapper().selectById(vo.getId()); + if (data == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockPlan.class) + .set(TakeStockPlan::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.FINISHED) + .eq(TakeStockPlan::getId, data.getId()) + .eq(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.DIFF_CREATED); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点任务信息已过期,请刷新重试!"); + } + + TakeStockConfig config = takeStockConfigService.get(); + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + TakeStockPlanDetail.class) + .eq(TakeStockPlanDetail::getPlanId, data.getId()) + .orderByAsc(TakeStockPlanDetail::getOrderNo); + List details = takeStockPlanDetailService.list(queryDetailWrapper); + if (CollectionUtil.isEmpty(details)) { + throw new DefaultClientException("盘点任务不存在商品信息,不允许执行差异处理操作!"); + } + + if (!config.getAllowChangeNum().equals(vo.getAllowChangeNum()) || !config.getAutoChangeStock() + .equals(vo.getAutoChangeStock())) { + throw new DefaultClientException("系统参数发生改变,请刷新页面后重试!"); + } + + for (TakeStockPlanDetail detail : details) { + HandleTakeStockPlanVo.ProductVo productVo = vo.getProducts().stream() + .filter(t -> t.getProductId().equals(detail.getProductId())).findFirst().get(); + if (config.getAllowChangeNum()) { + // 如果允许修改盘点数量 + detail.setTakeNum(productVo.getTakeNum()); + } else { + // 如果允许自动调整,那么盘点数量=盘点单的盘点数量 - 进项数量 + 出项数量,否则就等于盘点单的盘点数量 + detail.setTakeNum(config.getAutoChangeStock() ? + detail.getOriTakeNum() - detail.getTotalInNum() + detail.getTotalOutNum() : + detail.getOriTakeNum()); + } + detail.setDescription( + StringUtil.isBlank(productVo.getDescription()) ? StringPool.EMPTY_STR + : productVo.getDescription()); + + LambdaUpdateWrapper updateDetailWrapper = Wrappers.lambdaUpdate( + TakeStockPlanDetail.class).set(TakeStockPlanDetail::getTakeNum, detail.getTakeNum()) + .set(TakeStockPlanDetail::getDescription, detail.getDescription()) + .eq(TakeStockPlanDetail::getId, detail.getId()); + takeStockPlanDetailService.update(updateDetailWrapper); + } + + // 进行出入库操作 + int orderNo = 0; + for (TakeStockPlanDetail detail : details) { + orderNo++; + if (!NumberUtil.equal(detail.getStockNum(), detail.getTakeNum())) { + if (NumberUtil.lt(detail.getStockNum(), detail.getTakeNum())) { + Product product = productService.findById(detail.getProductId()); + ProductPurchase purchase = productPurchaseService.getById(product.getId()); + // 如果库存数量小于盘点数量,则报溢 + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(detail.getProductId()); + addProductStockVo.setScId(data.getScId()); + addProductStockVo.setStockNum(detail.getTakeNum() - detail.getStockNum()); + addProductStockVo.setDefaultTaxPrice(purchase.getPrice()); + addProductStockVo.setBizId(data.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(data.getCode()); + addProductStockVo.setBizType(ProductStockBizType.TAKE_STOCK_IN.getCode()); + + productStockService.addStock(addProductStockVo); + } else { + // 如果库存数量大于盘点数量,则报损 + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(detail.getProductId()); + subProductStockVo.setScId(data.getScId()); + subProductStockVo.setStockNum(detail.getStockNum() - detail.getTakeNum()); + subProductStockVo.setBizId(data.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(data.getCode()); + subProductStockVo.setBizType(ProductStockBizType.TAKE_STOCK_OUT.getCode()); + + productStockService.subStock(subProductStockVo); + } + } + } + + OpLogUtil.setVariable("id", vo.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "作废盘点任务,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void cancel(CancelTakeStockPlanVo vo) { + + TakeStockPlan data = getBaseMapper().selectById(vo.getId()); + if (data == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockPlan.class) + .set(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.CANCELED) + .eq(TakeStockPlan::getId, data.getId()) + .in(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.CREATED, + TakeStockPlanStatus.DIFF_CREATED); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点任务信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", vo.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "删除盘点任务,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + TakeStockPlan data = getBaseMapper().selectById(id); + if (data == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + Wrapper deleteWrapper = Wrappers.lambdaQuery(TakeStockPlan.class) + .eq(TakeStockPlan::getId, data.getId()) + .eq(TakeStockPlan::getTakeStatus, TakeStockPlanStatus.CANCELED); + if (getBaseMapper().delete(deleteWrapper) != 1) { + throw new DefaultClientException("盘点任务信息已过期,请刷新重试!"); + } + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + TakeStockPlanDetail.class) + .eq(TakeStockPlanDetail::getPlanId, data.getId()); + takeStockPlanDetailService.remove(deleteDetailWrapper); + + DeleteTakeStockPlanEvent deleteEvent = new DeleteTakeStockPlanEvent(this, data.getId()); + ApplicationUtil.publishEvent(deleteEvent); + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } + + @Service + public static class AddStockListener implements ApplicationListener { + + @Autowired + private TakeStockPlanDetailMapper takeStockPlanDetailMapper; + + @Transactional(rollbackFor = Exception.class) + @Override + public void onApplicationEvent(AddStockEvent addStockEvent) { + + ProductStockChangeDto change = addStockEvent.getChange(); + takeStockPlanDetailMapper.addTotalInNum(change.getScId(), change.getProductId(), + change.getNum()); + } + } + + @Service + public static class SubStockListener implements ApplicationListener { + + @Autowired + private TakeStockPlanDetailMapper takeStockPlanDetailMapper; + + @Transactional(rollbackFor = Exception.class) + @Override + public void onApplicationEvent(SubStockEvent addStockEvent) { + + ProductStockChangeDto change = addStockEvent.getChange(); + takeStockPlanDetailMapper.addTotalOutNum(change.getScId(), change.getProductId(), + change.getNum()); + } + } + + /** + * 自动作废任务 + */ + @Slf4j + public static class AutoCancelJob extends QrtzJob { + + @Autowired + private TakeStockPlanService takeStockPlanService; + + @Override + public void onExecute(JobExecutionContext context) { + + String id = (String) context.getMergedJobDataMap().get("id"); + + CancelTakeStockPlanVo cancelVo = new CancelTakeStockPlanVo(); + cancelVo.setId(id); + takeStockPlanService.cancel(cancelVo); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetDetailServiceImpl.java new file mode 100644 index 0000000..9c5d6de --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.TakeStockSheetDetail; +import com.lframework.xingyun.sc.mappers.TakeStockSheetDetailMapper; +import com.lframework.xingyun.sc.service.stock.take.TakeStockSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class TakeStockSheetDetailServiceImpl extends + BaseMpServiceImpl + implements TakeStockSheetDetailService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetServiceImpl.java new file mode 100644 index 0000000..a1911a0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/take/TakeStockSheetServiceImpl.java @@ -0,0 +1,533 @@ +package com.lframework.xingyun.sc.impl.stock.take; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.core.events.stock.take.DeleteTakeStockPlanEvent; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.entity.TakeStockSheet; +import com.lframework.xingyun.sc.entity.TakeStockSheetDetail; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import com.lframework.xingyun.sc.enums.TakeStockSheetStatus; +import com.lframework.xingyun.sc.mappers.TakeStockSheetMapper; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanDetailService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockPlanService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockSheetDetailService; +import com.lframework.xingyun.sc.service.stock.take.TakeStockSheetService; +import com.lframework.xingyun.sc.vo.stock.take.sheet.ApprovePassTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.ApproveRefuseTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.BatchApprovePassTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.BatchApproveRefuseTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.CreateTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetProductVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.TakeStockSheetProductVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.UpdateTakeStockSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class TakeStockSheetServiceImpl extends + BaseMpServiceImpl + implements TakeStockSheetService { + + @Autowired + private TakeStockSheetDetailService takeStockSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private TakeStockPlanService takeStockPlanService; + + @Autowired + private TakeStockPlanDetailService takeStockPlanDetailService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryTakeStockSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryTakeStockSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public TakeStockSheetFullDto getDetail(String id) { + + TakeStockSheetFullDto data = getBaseMapper().getDetail(id); + if (data == null) { + throw new DefaultClientException("盘点单不存在!"); + } + + return data; + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "新增盘点单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建盘点单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateTakeStockSheetVo vo) { + + TakeStockSheet data = new TakeStockSheet(); + data.setId(IdUtil.getId()); + data.setCode(generateCodeService.generate(GenerateCodeTypePool.TAKE_STOCK_SHEET)); + data.setPlanId(vo.getPlanId()); + data.setPreSheetId(vo.getPreSheetId()); + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(vo.getPlanId()); + if (takeStockPlan == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + if (takeStockPlan.getTakeStatus() != TakeStockPlanStatus.CREATED) { + throw new DefaultClientException("关联盘点任务的盘点状态已改变,不允许进行新增!"); + } + + data.setScId(takeStockPlan.getScId()); + data.setStatus(TakeStockSheetStatus.CREATED); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + int orderNo = 1; + for (TakeStockSheetProductVo product : vo.getProducts()) { + TakeStockSheetDetail detail = new TakeStockSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(data.getId()); + detail.setProductId(product.getProductId()); + detail.setTakeNum(product.getTakeNum()); + detail.setDescription( + StringUtil.isBlank(product.getDescription()) ? StringPool.EMPTY_STR + : product.getDescription()); + detail.setOrderNo(orderNo++); + + takeStockSheetDetailService.save(detail); + } + + // 盘点任务如果是单品盘点 + if (takeStockPlan.getTakeType() == TakeStockPlanType.SIMPLE) { + takeStockPlanDetailService.savePlanDetailBySimple(takeStockPlan.getId(), + vo.getProducts().stream().map(TakeStockSheetProductVo::getProductId) + .collect(Collectors.toList())); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "修改盘点单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#_result", name = "修改盘点单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateTakeStockSheetVo vo) { + + TakeStockSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点单不存在!"); + } + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(data.getPlanId()); + if (takeStockPlan == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + if (takeStockPlan.getTakeStatus() != TakeStockPlanStatus.CREATED) { + throw new DefaultClientException("关联盘点任务的盘点状态已改变,不允许进行修改!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockSheet.class) + .set(TakeStockSheet::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(TakeStockSheet::getApproveBy, null).set(TakeStockSheet::getApproveTime, null) + .set(TakeStockSheet::getRefuseReason, null) + .set(TakeStockSheet::getStatus, TakeStockSheetStatus.CREATED) + .eq(TakeStockSheet::getId, vo.getId()) + .in(TakeStockSheet::getStatus, TakeStockSheetStatus.CREATED, + TakeStockSheetStatus.APPROVE_REFUSE); + + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点单信息已过期,请刷新重试!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + TakeStockSheetDetail.class) + .eq(TakeStockSheetDetail::getSheetId, data.getId()); + takeStockSheetDetailService.remove(deleteDetailWrapper); + + int orderNo = 1; + for (TakeStockSheetProductVo product : vo.getProducts()) { + TakeStockSheetDetail detail = new TakeStockSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(data.getId()); + detail.setProductId(product.getProductId()); + detail.setTakeNum(product.getTakeNum()); + detail.setDescription( + StringUtil.isBlank(product.getDescription()) ? StringPool.EMPTY_STR + : product.getDescription()); + detail.setOrderNo(orderNo++); + + takeStockSheetDetailService.save(detail); + } + + // 盘点任务如果是单品盘点 + if (takeStockPlan.getTakeType() == TakeStockPlanType.SIMPLE) { + takeStockPlanDetailService.savePlanDetailBySimple(takeStockPlan.getId(), + vo.getProducts().stream().map(TakeStockSheetProductVo::getProductId) + .collect(Collectors.toList())); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "审核通过盘点单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassTakeStockSheetVo vo) { + + TakeStockSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点单不存在!"); + } + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(data.getPlanId()); + if (takeStockPlan == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + if (takeStockPlan.getTakeStatus() != TakeStockPlanStatus.CREATED) { + throw new DefaultClientException("关联盘点任务的盘点状态已改变,不允许继续执行审核!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockSheet.class) + .set(TakeStockSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(TakeStockSheet::getApproveTime, LocalDateTime.now()) + .set(TakeStockSheet::getStatus, TakeStockSheetStatus.APPROVE_PASS) + .eq(TakeStockSheet::getId, data.getId()) + .in(TakeStockSheet::getStatus, TakeStockSheetStatus.CREATED, + TakeStockSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + TakeStockSheetDetail.class) + .eq(TakeStockSheetDetail::getSheetId, data.getId()) + .orderByAsc(TakeStockSheetDetail::getOrderNo); + List details = takeStockSheetDetailService.list(queryDetailWrapper); + for (TakeStockSheetDetail detail : details) { + takeStockPlanDetailService.updateOriTakeNum(data.getPlanId(), detail.getProductId(), + detail.getTakeNum()); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassTakeStockSheetVo vo) { + + TakeStockSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassTakeStockSheetVo approveVo = new ApprovePassTakeStockSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个库存盘点单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateTakeStockSheetVo vo) { + + TakeStockSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassTakeStockSheetVo approveVo = new ApprovePassTakeStockSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "审核拒绝盘点单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseTakeStockSheetVo vo) { + + TakeStockSheet data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点单不存在!"); + } + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(data.getPlanId()); + if (takeStockPlan == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + if (takeStockPlan.getTakeStatus() != TakeStockPlanStatus.CREATED) { + throw new DefaultClientException("关联盘点任务的盘点状态已改变,不允许继续执行审核!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockSheet.class) + .set(TakeStockSheet::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(TakeStockSheet::getApproveTime, LocalDateTime.now()) + .set(TakeStockSheet::getRefuseReason, + StringUtil.isBlank(vo.getRefuseReason()) ? StringPool.EMPTY_STR : vo.getRefuseReason()) + .set(TakeStockSheet::getStatus, TakeStockSheetStatus.APPROVE_REFUSE) + .eq(TakeStockSheet::getId, data.getId()) + .eq(TakeStockSheet::getStatus, TakeStockSheetStatus.CREATED); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseTakeStockSheetVo vo) { + + TakeStockSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseTakeStockSheetVo approveVo = new ApproveRefuseTakeStockSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个库存盘点单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.CANCEL_APPROVE, orderId = "#id", name = "取消审核") + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "取消审核通过盘点单,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void cancelApprovePass(String id) { + + TakeStockSheet data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点单不存在!"); + } + + TakeStockPlan takeStockPlan = takeStockPlanService.getById(data.getPlanId()); + if (takeStockPlan == null) { + throw new DefaultClientException("盘点任务不存在!"); + } + + if (takeStockPlan.getTakeStatus() != TakeStockPlanStatus.CREATED) { + throw new DefaultClientException("关联盘点任务的盘点状态已改变,不允许执行取消审核!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(TakeStockSheet.class) + .set(TakeStockSheet::getApproveBy, null).set(TakeStockSheet::getApproveTime, null) + .set(TakeStockSheet::getRefuseReason, null) + .set(TakeStockSheet::getStatus, TakeStockSheetStatus.CREATED) + .eq(TakeStockSheet::getId, data.getId()) + .eq(TakeStockSheet::getStatus, TakeStockSheetStatus.APPROVE_PASS); + + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("盘点单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + TakeStockSheetDetail.class) + .eq(TakeStockSheetDetail::getSheetId, data.getId()) + .orderByAsc(TakeStockSheetDetail::getOrderNo); + List details = takeStockSheetDetailService.list(queryDetailWrapper); + for (TakeStockSheetDetail detail : details) { + takeStockPlanDetailService.updateOriTakeNum(data.getPlanId(), detail.getProductId(), + -detail.getTakeNum()); + } + + OpLogUtil.setVariable("id", data.getId()); + } + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "删除盘点单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + TakeStockSheet data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("盘点单不存在!"); + } + + Wrapper deleteWrapper = Wrappers.lambdaQuery(TakeStockSheet.class) + .eq(TakeStockSheet::getId, id) + .in(TakeStockSheet::getStatus, TakeStockSheetStatus.CREATED, + TakeStockSheetStatus.APPROVE_REFUSE); + if (getBaseMapper().delete(deleteWrapper) != 1) { + throw new DefaultClientException("盘点单信息已过期,请刷新重试!"); + } + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + TakeStockSheetDetail.class) + .eq(TakeStockSheetDetail::getSheetId, data.getId()); + takeStockSheetDetailService.remove(deleteDetailWrapper); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(List ids) { + + TakeStockSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : ids) { + try { + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个库存盘点单删除失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @Override + public Boolean hasRelatePreTakeStockSheet(String preSheetId) { + + return getBaseMapper().hasRelatePreTakeStockSheet(preSheetId); + } + + @Override + public Boolean hasUnApprove(String planId) { + + return getBaseMapper().hasUnApprove(planId); + } + + @Override + public PageResult queryTakeStockByCondition(Integer pageIndex, + Integer pageSize, String planId, String condition) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryTakeStockByCondition(planId, + condition); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryTakeStockList(Integer pageIndex, + Integer pageSize, QueryTakeStockSheetProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryTakeStockList(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } + + @Service + public static class DeleteTakeStockPlanListener implements + ApplicationListener { + + @Autowired + private TakeStockSheetService takeStockSheetService; + + @Autowired + private TakeStockSheetDetailService takeStockSheetDetailService; + + @OpLog(type = ScOpLogType.TAKE_STOCK, name = "删除库存盘点表,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void onApplicationEvent(DeleteTakeStockPlanEvent deleteTakeStockPlanEvent) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(TakeStockSheet.class) + .eq(TakeStockSheet::getPlanId, deleteTakeStockPlanEvent.getId()); + List sheets = takeStockSheetService.list(deleteWrapper); + + List ids = CollectionUtil.emptyList(); + + if (!CollectionUtil.isEmpty(sheets)) { + ids = sheets.stream().map(TakeStockSheet::getId).collect(Collectors.toList()); + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + TakeStockSheetDetail.class) + .in(TakeStockSheetDetail::getSheetId, ids); + takeStockSheetDetailService.remove(deleteDetailWrapper); + } + + takeStockSheetService.remove(deleteWrapper); + + OpLogUtil.setVariable("ids", ids); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailReceiveServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailReceiveServiceImpl.java new file mode 100644 index 0000000..0016ea2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailReceiveServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.sc.impl.stock.transfer; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetailReceive; +import com.lframework.xingyun.sc.mappers.ScTransferOrderDetailReceiveMapper; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderDetailReceiveService; +import org.springframework.stereotype.Service; + +@Service +public class ScTransferOrderDetailReceiveServiceImpl + extends BaseMpServiceImpl + implements ScTransferOrderDetailReceiveService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailServiceImpl.java new file mode 100644 index 0000000..24bef3d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderDetailServiceImpl.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.sc.impl.stock.transfer; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetail; +import com.lframework.xingyun.sc.mappers.ScTransferOrderDetailMapper; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderDetailService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ScTransferOrderDetailServiceImpl + extends BaseMpServiceImpl + implements ScTransferOrderDetailService { + + @Transactional(rollbackFor = Exception.class) + @Override + public int receive(String orderId, String productId, Integer receiveNum) { + return getBaseMapper().receive(orderId, productId, receiveNum); + } + + @Override + public int countUnReceive(String orderId) { + return getBaseMapper().countUnReceive(orderId); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderServiceImpl.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderServiceImpl.java new file mode 100644 index 0000000..b3cbf1d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/impl/stock/transfer/ScTransferOrderServiceImpl.java @@ -0,0 +1,541 @@ +package com.lframework.xingyun.sc.impl.stock.transfer; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.basedata.entity.Product; +import com.lframework.xingyun.basedata.service.product.ProductService; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferOrderFullDto; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferProductDto; +import com.lframework.xingyun.sc.entity.ScTransferOrder; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetail; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetailReceive; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import com.lframework.xingyun.sc.enums.ScOpLogType; +import com.lframework.xingyun.sc.enums.ScTransferOrderStatus; +import com.lframework.xingyun.sc.mappers.ScTransferOrderMapper; +import com.lframework.xingyun.sc.service.stock.ProductStockService; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderDetailReceiveService; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderDetailService; +import com.lframework.xingyun.sc.service.stock.transfer.ScTransferOrderService; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ApprovePassScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ApproveRefuseScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.BatchApprovePassScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.BatchApproveRefuseScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.CreateScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferProductVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ReceiveScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ReceiveScTransferOrderVo.ReceiveScTransferProductVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ScTransferProductVo; +import com.lframework.xingyun.sc.vo.stock.transfer.UpdateScTransferOrderVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ScTransferOrderServiceImpl extends + BaseMpServiceImpl + implements ScTransferOrderService { + + @Autowired + private ScTransferOrderDetailService scTransferOrderDetailService; + + @Autowired + private ScTransferOrderDetailReceiveService scTransferOrderDetailReceiveService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private ProductStockService productStockService; + + @Autowired + private ProductService productService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryScTransferOrderVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryScTransferOrderVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public ScTransferOrderFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = ScOpLogType.SC_TRANSFER, name = "新增仓库调拨单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建调拨单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateScTransferOrderVo vo) { + + ScTransferOrder data = new ScTransferOrder(); + data.setId(IdUtil.getId()); + data.setCode(generateCodeService.generate(GenerateCodeTypePool.SC_TRANSFER_ORDER)); + + this.create(data, vo); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = ScOpLogType.SC_TRANSFER, name = "修改仓库调拨单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改调拨单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateScTransferOrderVo vo) { + + ScTransferOrder data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("仓库调拨单不存在!"); + } + + if (data.getStatus() != ScTransferOrderStatus.CREATED + && data.getStatus() != ScTransferOrderStatus.APPROVE_REFUSE) { + + if (data.getStatus() == ScTransferOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("仓库调拨单已审核通过,无法修改!"); + } + + throw new DefaultClientException("仓库调拨单无法修改!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + ScTransferOrderDetail.class) + .eq(ScTransferOrderDetail::getOrderId, data.getId()); + scTransferOrderDetailService.remove(deleteDetailWrapper); + + this.create(data, vo); + + data.setStatus(ScTransferOrderStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(ScTransferOrderStatus.CREATED); + statusList.add(ScTransferOrderStatus.APPROVE_REFUSE); + + Wrapper updateSheetWrapper = Wrappers.lambdaUpdate( + ScTransferOrder.class) + .set(ScTransferOrder::getApproveBy, null) + .set(ScTransferOrder::getApproveTime, null) + .set(ScTransferOrder::getRefuseReason, StringPool.EMPTY_STR) + .eq(ScTransferOrder::getId, data.getId()) + .in(ScTransferOrder::getStatus, statusList); + if (getBaseMapper().updateAllColumn(data, updateSheetWrapper) != 1) { + throw new DefaultClientException("仓库调拨单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = ScOpLogType.SC_TRANSFER, name = "删除仓库调拨单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + ScTransferOrder data = getBaseMapper().selectById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("仓库调拨单不存在!"); + } + + if (data.getStatus() == ScTransferOrderStatus.APPROVE_PASS + || data.getStatus() == ScTransferOrderStatus.PART_RECEIVED + || data.getStatus() == ScTransferOrderStatus.RECEIVED) { + throw new DefaultClientException("“审核通过”的仓库调拨单不允许执行删除操作!"); + } + + Wrapper deleteWrapper = Wrappers.lambdaQuery(ScTransferOrder.class) + .eq(ScTransferOrder::getId, id) + .in(ScTransferOrder::getStatus, ScTransferOrderStatus.CREATED, + ScTransferOrderStatus.APPROVE_REFUSE); + if (getBaseMapper().delete(deleteWrapper) != 1) { + throw new DefaultClientException("仓库调拨单信息已过期,请刷新重试!"); + } + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + ScTransferOrderDetail.class) + .eq(ScTransferOrderDetail::getOrderId, id); + scTransferOrderDetailService.remove(deleteDetailWrapper); + + Wrapper deleteDetailReceiveWrapper = Wrappers.lambdaQuery( + ScTransferOrderDetailReceive.class).eq(ScTransferOrderDetailReceive::getOrderId, id); + scTransferOrderDetailReceiveService.remove(deleteDetailReceiveWrapper); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + ScTransferOrderService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个仓库调拨单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @OpLog(type = ScOpLogType.SC_TRANSFER, name = "审核通过仓库调拨单,ID:{}", params = {"#vo.id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassScTransferOrderVo vo) { + + ScTransferOrder data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("仓库调拨单不存在!"); + } + + if (data.getStatus() != ScTransferOrderStatus.CREATED + && data.getStatus() != ScTransferOrderStatus.APPROVE_REFUSE) { + + if (data.getStatus() == ScTransferOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("仓库调拨单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("仓库调拨单无法审核通过!"); + } + + LocalDateTime now = LocalDateTime.now(); + Wrapper updateWrapper = Wrappers.lambdaUpdate(ScTransferOrder.class) + .eq(ScTransferOrder::getId, data.getId()) + .in(ScTransferOrder::getStatus, ScTransferOrderStatus.CREATED, + ScTransferOrderStatus.APPROVE_REFUSE) + .set(ScTransferOrder::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(ScTransferOrder::getApproveTime, now) + .set(ScTransferOrder::getStatus, ScTransferOrderStatus.APPROVE_PASS) + .set(ScTransferOrder::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("仓库调拨单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + ScTransferOrderDetail.class) + .eq(ScTransferOrderDetail::getOrderId, data.getId()) + .orderByAsc(ScTransferOrderDetail::getOrderNo); + List details = scTransferOrderDetailService.list( + queryDetailWrapper); + + BigDecimal totalAmount = BigDecimal.ZERO; + for (ScTransferOrderDetail detail : details) { + Product product = productService.findById(detail.getProductId()); + SubProductStockVo subProductStockVo = new SubProductStockVo(); + subProductStockVo.setProductId(product.getId()); + subProductStockVo.setScId(data.getSourceScId()); + subProductStockVo.setStockNum(detail.getTransferNum()); + subProductStockVo.setCreateTime(now); + subProductStockVo.setBizId(data.getId()); + subProductStockVo.setBizDetailId(detail.getId()); + subProductStockVo.setBizCode(data.getCode()); + subProductStockVo.setBizType(ProductStockBizType.SC_TRANSFER.getCode()); + + ProductStockChangeDto changeDto = productStockService.subStock(subProductStockVo); + + detail.setTaxPrice(changeDto.getCurTaxPrice()); + + Wrapper updateDetailWrapper = Wrappers.lambdaUpdate( + ScTransferOrderDetail.class).eq(ScTransferOrderDetail::getId, detail.getId()) + .set(ScTransferOrderDetail::getTaxPrice, detail.getTaxPrice()); + scTransferOrderDetailService.update(updateDetailWrapper); + totalAmount = NumberUtil.add(totalAmount, + NumberUtil.mul(detail.getTaxPrice(), detail.getTransferNum())); + } + + updateWrapper = Wrappers.lambdaUpdate(ScTransferOrder.class) + .eq(ScTransferOrder::getId, data.getId()).set(ScTransferOrder::getTotalAmount, totalAmount); + this.update(updateWrapper); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassScTransferOrderVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassScTransferOrderVo approvePassVo = new ApprovePassScTransferOrderVo(); + approvePassVo.setId(id); + + try { + ScTransferOrderService thisService = getThis(this.getClass()); + thisService.approvePass(approvePassVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个仓库调拨单审核通过失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateScTransferOrderVo vo) { + + ScTransferOrderService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassScTransferOrderVo approvePassVo = new ApprovePassScTransferOrderVo(); + approvePassVo.setId(id); + approvePassVo.setDescription(vo.getDescription()); + + thisService.approvePass(approvePassVo); + + return id; + } + + @OpLog(type = ScOpLogType.SC_TRANSFER, name = "审核拒绝仓库调拨单,ID:{}", params = {"#id"}) + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseScTransferOrderVo vo) { + + ScTransferOrder data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("仓库调拨单不存在!"); + } + + if (data.getStatus() != ScTransferOrderStatus.CREATED + && data.getStatus() != ScTransferOrderStatus.APPROVE_REFUSE) { + + if (data.getStatus() == ScTransferOrderStatus.APPROVE_PASS) { + throw new DefaultClientException("仓库调拨单已审核通过,不允许继续执行审核!"); + } + + throw new DefaultClientException("仓库调拨单无法审核通过!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ScTransferOrder.class) + .eq(ScTransferOrder::getId, data.getId()) + .in(ScTransferOrder::getStatus, ScTransferOrderStatus.CREATED, + ScTransferOrderStatus.APPROVE_REFUSE) + .set(ScTransferOrder::getApproveBy, SecurityUtil.getCurrentUser().getId()) + .set(ScTransferOrder::getApproveTime, LocalDateTime.now()) + .set(ScTransferOrder::getRefuseReason, vo.getRefuseReason()) + .set(ScTransferOrder::getStatus, ScTransferOrderStatus.APPROVE_REFUSE); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("仓库调拨单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseScTransferOrderVo vo) { + + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseScTransferOrderVo approveRefuseVo = new ApproveRefuseScTransferOrderVo(); + approveRefuseVo.setId(id); + approveRefuseVo.setRefuseReason(vo.getRefuseReason()); + + try { + ScTransferOrderService thisService = getThis(this.getClass()); + thisService.approveRefuse(approveRefuseVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个仓库调拨单审核拒绝失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.RECEIVE, orderId = "#vo.id", name = "仓库调拨单收货") + @Transactional(rollbackFor = Exception.class) + @Override + public void receive(ReceiveScTransferOrderVo vo) { + ScTransferOrder data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("仓库调拨单不存在!"); + } + + if (data.getStatus() != ScTransferOrderStatus.APPROVE_PASS + && data.getStatus() != ScTransferOrderStatus.PART_RECEIVED) { + + throw new DefaultClientException("仓库调拨单信息已过期,请刷新重试!"); + } + + for (ReceiveScTransferProductVo productVo : vo.getProducts()) { + if (scTransferOrderDetailService.receive(data.getId(), productVo.getProductId(), + productVo.getReceiveNum()) != 1) { + Product product = productService.findById(productVo.getProductId()); + throw new DefaultClientException( + "商品(" + product.getCode() + ")" + product.getName() + "待收货数量不足,请检查!"); + } + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(ScTransferOrder.class) + .set(ScTransferOrder::getStatus, + scTransferOrderDetailService.countUnReceive(data.getId()) > 0 + ? ScTransferOrderStatus.PART_RECEIVED : ScTransferOrderStatus.RECEIVED) + .eq(ScTransferOrder::getId, data.getId()) + .in(ScTransferOrder::getStatus, ScTransferOrderStatus.APPROVE_PASS, + ScTransferOrderStatus.PART_RECEIVED); + if (!this.update(updateWrapper)) { + throw new DefaultClientException("仓库调拨单信息已过期,请刷新重试!"); + } + + LocalDateTime now = LocalDateTime.now(); + for (ReceiveScTransferProductVo productVo : vo.getProducts()) { + Wrapper queryWrapper = Wrappers.lambdaQuery( + ScTransferOrderDetail.class).eq(ScTransferOrderDetail::getOrderId, data.getId()) + .eq(ScTransferOrderDetail::getProductId, productVo.getProductId()); + ScTransferOrderDetail detail = scTransferOrderDetailService.getOne(queryWrapper); + // 入库 + AddProductStockVo addProductStockVo = new AddProductStockVo(); + addProductStockVo.setProductId(detail.getProductId()); + addProductStockVo.setScId(data.getTargetScId()); + addProductStockVo.setStockNum(productVo.getReceiveNum()); + addProductStockVo.setTaxPrice(detail.getTaxPrice()); + addProductStockVo.setCreateTime(now); + addProductStockVo.setBizId(data.getId()); + addProductStockVo.setBizDetailId(detail.getId()); + addProductStockVo.setBizCode(data.getCode()); + addProductStockVo.setBizType(ProductStockBizType.SC_TRANSFER.getCode()); + + productStockService.addStock(addProductStockVo); + + ScTransferOrderDetailReceive detailReceive = new ScTransferOrderDetailReceive(); + detailReceive.setId(IdUtil.getId()); + detailReceive.setOrderId(data.getId()); + detailReceive.setDetailId(detail.getId()); + detailReceive.setReceiveNum(productVo.getReceiveNum()); + scTransferOrderDetailReceiveService.save(detailReceive); + } + } + + + @Override + public PageResult queryScTransferByCondition(Integer pageIndex, + Integer pageSize, String scId, String condition) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryScTransferByCondition(scId, + condition); + PageResult pageResult = PageResultUtil.convert( + new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public PageResult queryScTransferList(Integer pageIndex, + Integer pageSize, QueryScTransferProductVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().queryScTransferList(vo); + PageResult pageResult = PageResultUtil.convert( + new PageInfo<>(datas)); + + return pageResult; + } + + @Override + public void cleanCacheByKey(Serializable key) { + + } + + private void create(ScTransferOrder data, CreateScTransferOrderVo vo) { + + data.setSourceScId(vo.getSourceScId()); + data.setTargetScId(vo.getTargetScId()); + if (StringUtil.equals(vo.getSourceScId(), vo.getTargetScId())) { + throw new DefaultClientException("转出仓库和转入仓库不允许相同!"); + } + data.setStatus(ScTransferOrderStatus.CREATED); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + int totalNum = 0; + int orderNo = 1; + for (ScTransferProductVo product : vo.getProducts()) { + ScTransferOrderDetail detail = new ScTransferOrderDetail(); + detail.setId(IdUtil.getId()); + detail.setOrderId(data.getId()); + detail.setProductId(product.getProductId()); + detail.setTransferNum(product.getTransferNum()); + detail.setDescription( + StringUtil.isBlank(product.getDescription()) ? StringPool.EMPTY_STR + : product.getDescription()); + detail.setOrderNo(orderNo++); + + totalNum += detail.getTransferNum(); + + scTransferOrderDetailService.save(detail); + } + data.setTotalNum(totalNum); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetDetailMapper.java new file mode 100644 index 0000000..447a083 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetDetailMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.LogisticsSheetDetail; + +/** + *

+ * 物流单明细 Mapper 接口 + *

+ * + * @author zmj + */ +public interface LogisticsSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetMapper.java new file mode 100644 index 0000000..44979a5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/LogisticsSheetMapper.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetBizOrderDto; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetFullDto; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.sc.vo.logistics.LogisticsSheetSelectorVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetBizOrderVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 物流单 Mapper 接口 + *

+ * + * @author zmj + */ +public interface LogisticsSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "o", autoParse = true), + @Sort(value = "logisticsNo", alias = "o", autoParse = true), + @Sort(value = "createTime", alias = "o", autoParse = true), + @Sort(value = "deliveryTime", alias = "o", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List query(@Param("vo") QueryLogisticsSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + LogisticsSheetFullDto getDetail(String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List selector(@Param("vo") LogisticsSheetSelectorVo vo); + + /** + * 查询业务单据列表 + * + * @param vo + * @param dataPermission + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List queryBizOrder(@Param("vo") QueryLogisticsSheetBizOrderVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/OrderPayTypeMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/OrderPayTypeMapper.java new file mode 100644 index 0000000..24e7a1b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/OrderPayTypeMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.OrderPayType; + +/** + *

+ * 订单支付方式 Mapper 接口 + *

+ * + * @author zmj + */ +public interface OrderPayTypeMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetDetailMapper.java new file mode 100644 index 0000000..fbf7bec --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetDetailMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.PreTakeStockSheetDetail; + +/** + *

+ * 预先盘点单详情 Mapper 接口 + *

+ * + * @author zmj + */ +public interface PreTakeStockSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetMapper.java new file mode 100644 index 0000000..84b98f6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PreTakeStockSheetMapper.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockProductDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.QueryPreTakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.sc.vo.stock.take.pre.PreTakeStockSheetSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockProductVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 预先盘点单 Mapper 接口 + *

+ * + * @author zmj + */ +public interface PreTakeStockSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "updateTime", alias = "tb", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List query(@Param("vo") QueryPreTakeStockSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PreTakeStockSheetFullDto getDetail(@Param("id") String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List selector(@Param("vo") PreTakeStockSheetSelectorVo vo); + + /** + * 根据预先盘点单、盘点任务查询商品信息 + * + * @param id + * @param planId + * @return + */ + List getProducts(@Param("id") String id, + @Param("planId") String planId); + + /** + * 根据关键字查询预先盘点单商品信息 + * + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryPreTakeStockByCondition(@Param("condition") String condition); + + /** + * 查询预先盘点单商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryPreTakeStockList(@Param("vo") QueryPreTakeStockProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockLogMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockLogMapper.java new file mode 100644 index 0000000..87c6304 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockLogMapper.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.ProductStockLog; +import com.lframework.xingyun.sc.vo.stock.log.QueryProductStockLogVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-14 + */ +public interface ProductStockLogMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "scCode", alias = "sc.code"), + @Sort(value = "productCode", alias = "g.code"), + @Sort(value = "oriStockNum", alias = "gsl", autoParse = true), + @Sort(value = "curStockNum", alias = "gsl", autoParse = true), + @Sort(value = "stockNum", alias = "gsl", autoParse = true), + @Sort(value = "oriTaxPrice", alias = "gsl", autoParse = true), + @Sort(value = "curTaxPrice", alias = "gsl", autoParse = true), + @Sort(value = "taxAmount", alias = "gsl", autoParse = true), + @Sort(value = "createTime", alias = "gsl", autoParse = true), + @Sort(value = "bizCode", alias = "gsl", autoParse = true), + @Sort(value = "bizType", alias = "gsl", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List query(@Param("vo") QueryProductStockLogVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockMapper.java new file mode 100644 index 0000000..e6a785a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ProductStockMapper.java @@ -0,0 +1,106 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.vo.stock.QueryProductStockVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.math.BigDecimal; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-09-12 + */ +public interface ProductStockMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "scCode", alias = "sc.code"), + @Sort(value = "productCode", alias = "g.code"), + @Sort(value = "stockNum", alias = "gs.stock_num"), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List query(@Param("vo") QueryProductStockVo vo); + + /** + * 根据商品ID、仓库ID查询 + * + * @param productId + * @param scId + * @return + */ + ProductStock getByProductIdAndScId(@Param("productId") String productId, + @Param("scId") String scId); + + /** + * 根据商品ID、仓库ID查询 + * + * @param productIds + * @param scId + * @return + */ + List getByProductIdsAndScId(@Param("productIds") List productIds, + @Param("scId") String scId, @Param("productType") Integer productType); + + /** + * 入库 + * + * @param productId + * @param scId + * @param stockNum + * @param taxAmount + * @param oriStockNum + * @param oriTaxAmount + * @return + */ + int addStock(@Param("productId") String productId, @Param("scId") String scId, + @Param("stockNum") Integer stockNum, + @Param("taxAmount") BigDecimal taxAmount, + @Param("oriStockNum") Integer oriStockNum, @Param("oriTaxAmount") BigDecimal oriTaxAmount, + @Param("reCalcCostPrice") boolean reCalcCostPrice); + + /** + * 出库 + * + * @param productId + * @param scId + * @param stockNum + * @param taxAmount + * @param oriStockNum + * @param oriTaxAmount + * @return + */ + int subStock(@Param("productId") String productId, @Param("scId") String scId, + @Param("stockNum") Integer stockNum, + @Param("taxAmount") BigDecimal taxAmount, + @Param("oriStockNum") Integer oriStockNum, @Param("oriTaxAmount") BigDecimal oriTaxAmount, + @Param("reCalcCostPrice") boolean reCalcCostPrice); + + /** + * 库存成本调整 + * + * @param productId + * @param scId + * @param taxPrice + */ + void stockCostAdjust(@Param("productId") String productId, @Param("scId") String scId, + @Param("taxPrice") BigDecimal taxPrice); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseConfigMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseConfigMapper.java new file mode 100644 index 0000000..66112b5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseConfigMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.PurchaseConfig; + +public interface PurchaseConfigMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderDetailMapper.java new file mode 100644 index 0000000..80707c7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderDetailMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-09-12 + */ +public interface PurchaseOrderDetailMapper extends BaseMapper { + + /** + * 根据订单ID查询 + * + * @param orderId + * @return + */ + List getByOrderId(String orderId); + + /** + * 增加收货数量 + * + * @param id + * @param num + * @return + */ + int addReceiveNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少收货数量 + * + * @param id + * @param num + * @return + */ + int subReceiveNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderMapper.java new file mode 100644 index 0000000..e5d2c30 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseOrderMapper.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderWithReceiveDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.vo.purchase.PurchaseOrderSelectorVo; +import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderWithReceiveVo; +import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseProductVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-09-12 + */ +public interface PurchaseOrderMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "o", autoParse = true), + @Sort(value = "createTime", alias = "o", autoParse = true), + @Sort(value = "approveTime", alias = "o", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List query(@Param("vo") QueryPurchaseOrderVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PurchaseOrderFullDto getDetail(String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List selector(@Param("vo") PurchaseOrderSelectorVo vo); + + /** + * 根据ID查询(收货业务) + * + * @param id + * @return + */ + PurchaseOrderWithReceiveDto getWithReceive(@Param("id") String id, + @Param("requirePurchase") Boolean requirePurchase); + + /** + * 查询列表(收货业务) + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List queryWithReceive(@Param("vo") QueryPurchaseOrderWithReceiveVo vo, + @Param("multipleRelate") boolean multipleRelate); + + /** + * 根据关键字查询采购商品信息 + * + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryPurchaseByCondition( + @Param("condition") String condition); + + /** + * 查询可采购商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryPurchaseList(@Param("vo") QueryPurchaseProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PurchaseProductDto getPurchaseById(String id); + + /** + * 根据SKU查询可采购商品信息 + * @param sku + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + PurchaseProductDto queryPurchaseBySku( @Param("sku") String sku); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnDetailMapper.java new file mode 100644 index 0000000..1e19448 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.PurchaseReturnDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-16 + */ +public interface PurchaseReturnDetailMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnMapper.java new file mode 100644 index 0000000..4618a17 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/PurchaseReturnMapper.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.purchase.returned.PurchaseReturnFullDto; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.purchase.returned.QueryPurchaseReturnVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-16 + */ +public interface PurchaseReturnMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "o", autoParse = true), + @Sort(value = "createTime", alias = "o", autoParse = true), + @Sort(value = "approveTime", alias = "o", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "r") + }) + List query(@Param("vo") QueryPurchaseReturnVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PurchaseReturnFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("supplierId") String supplierId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetDetailMapper.java new file mode 100644 index 0000000..a11c523 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetDetailMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-09 + */ +public interface ReceiveSheetDetailMapper extends BaseMapper { + + /** + * 根据收货单ID查询 + * + * @param sheetId + * @return + */ + List getBySheetId(String sheetId); + + /** + * 增加退货数量 + * + * @param id + * @param num + * @return + */ + int addReturnNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + * @return + */ + int subReturnNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetMapper.java new file mode 100644 index 0000000..7777b18 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ReceiveSheetMapper.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetFullDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ReceiveSheetSelectorVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-09 + */ +public interface ReceiveSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "r", autoParse = true), + @Sort(value = "createTime", alias = "r", autoParse = true), + @Sort(value = "approveTime", alias = "r", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "r") + }) + List query(@Param("vo") QueryReceiveSheetVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "r") + }) + List selector(@Param("vo") ReceiveSheetSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ReceiveSheetFullDto getDetail(String id); + + /** + * 根据ID查询(采购退货业务) + * + * @param id + * @return + */ + ReceiveSheetWithReturnDto getWithReturn(@Param("id") String id, + @Param("requireReceive") Boolean requireReceive); + + /** + * 查询列表(采购退货业务) + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "r") + }) + List queryWithReturn(@Param("vo") QueryReceiveSheetWithReturnVo vo, + @Param("multipleRelate") boolean multipleRelate); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("supplierId") String supplierId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailConfigMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailConfigMapper.java new file mode 100644 index 0000000..b07774b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailConfigMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.RetailConfig; + +public interface RetailConfigMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailBundleMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailBundleMapper.java new file mode 100644 index 0000000..f0ccd52 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailBundleMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailBundle; + +public interface RetailOutSheetDetailBundleMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailLotMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailLotMapper.java new file mode 100644 index 0000000..5821fde --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailLotMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailLot; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-03 + */ +public interface RetailOutSheetDetailLotMapper extends BaseMapper { + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailOutSheetDetailLotDto findById(String id); + + /** + * 增加退货数量 + * + * @param id + * @param num + * @return + */ + int addReturnNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + * @return + */ + int subReturnNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailMapper.java new file mode 100644 index 0000000..4c034a2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetDetailMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetail; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-26 + */ +public interface RetailOutSheetDetailMapper extends BaseMapper { + + /** + * 根据出库单ID查询 + * + * @param sheetId + * @return + */ + List getBySheetId(String sheetId); + + /** + * 增加退货数量 + * + * @param id + * @param num + * @return + */ + int addReturnNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + * @return + */ + int subReturnNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetMapper.java new file mode 100644 index 0000000..52670cd --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailOutSheetMapper.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetFullDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailOutSheetVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.retail.out.QueryRetailProductVo; +import com.lframework.xingyun.sc.vo.retail.out.RetailOutSheetSelectorVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-26 + */ +public interface RetailOutSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QueryRetailOutSheetVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List selector(@Param("vo") RetailOutSheetSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailOutSheetFullDto getDetail(String id); + + /** + * 根据ID查询(销售退货业务) + * + * @param id + * @return + */ + RetailOutSheetWithReturnDto getWithReturn(@Param("id") String id, + @Param("requireOut") Boolean requireOut); + + /** + * 查询列表(销售退货业务) + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List queryWithReturn(@Param("vo") QueryRetailOutSheetWithReturnVo vo, + @Param("multipleRelate") boolean multipleRelate); + + /** + * 根据关键字零售采购商品信息 + * + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryRetailByCondition( + @Param("condition") String condition, @Param("isReturn") Boolean isReturn); + + /** + * 查询可零售商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryRetailList(@Param("vo") QueryRetailProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailProductDto getRetailById(String id); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnDetailMapper.java new file mode 100644 index 0000000..9a88428 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.RetailReturnDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-04 + */ +public interface RetailReturnDetailMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnMapper.java new file mode 100644 index 0000000..a23e01d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/RetailReturnMapper.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.retail.returned.RetailReturnFullDto; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.vo.retail.returned.QueryRetailReturnVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-04 + */ +public interface RetailReturnMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "r", autoParse = true), + @Sort(value = "createTime", alias = "r", autoParse = true), + @Sort(value = "approveTime", alias = "r", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "r") + }) + List query(@Param("vo") QueryRetailReturnVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailReturnFullDto getDetail(String id); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleConfigMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleConfigMapper.java new file mode 100644 index 0000000..ca4c1f6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleConfigMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.SaleConfig; + +public interface SaleConfigMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailBundleMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailBundleMapper.java new file mode 100644 index 0000000..90475fd --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailBundleMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.SaleOrderDetailBundle; + +public interface SaleOrderDetailBundleMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailMapper.java new file mode 100644 index 0000000..f20065e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderDetailMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-21 + */ +public interface SaleOrderDetailMapper extends BaseMapper { + + /** + * 根据订单ID查询 + * + * @param orderId + * @return + */ + List getByOrderId(String orderId); + + /** + * 增加出库数量 + * + * @param id + * @param num + * @return + */ + int addOutNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少出库数量 + * + * @param id + * @param num + * @return + */ + int subOutNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderMapper.java new file mode 100644 index 0000000..e82c3ef --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOrderMapper.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto; +import com.lframework.xingyun.sc.dto.sale.SaleOrderWithOutDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderWithOutVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleProductVo; +import com.lframework.xingyun.sc.vo.sale.SaleOrderSelectorVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-21 + */ +public interface SaleOrderMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "o", autoParse = true), + @Sort(value = "createTime", alias = "o", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List query(@Param("vo") QuerySaleOrderVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleOrderFullDto getDetail(String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List selector(@Param("vo") SaleOrderSelectorVo vo); + + /** + * 根据ID查询(出库业务) + * + * @param id + * @return + */ + SaleOrderWithOutDto getWithOut(@Param("id") String id, @Param("requireSale") Boolean requireSale); + + /** + * 查询列表(出库业务) + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "o") + }) + List queryWithOut(@Param("vo") QuerySaleOrderWithOutVo vo, + @Param("multipleRelate") boolean multipleRelate); + + /** + * 根据关键字销售采购商品信息 + * + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List querySaleByCondition( + @Param("condition") String condition, @Param("isReturn") Boolean isReturn); + + /** + * 查询可销售商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List querySaleList(@Param("vo") QuerySaleProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleProductDto getSaleById(String id); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailBundleMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailBundleMapper.java new file mode 100644 index 0000000..56d1c6e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailBundleMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailBundle; + +public interface SaleOutSheetDetailBundleMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailLotMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailLotMapper.java new file mode 100644 index 0000000..0379f90 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailLotMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailLot; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-03 + */ +public interface SaleOutSheetDetailLotMapper extends BaseMapper { + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleOutSheetDetailLotDto findById(String id); + + /** + * 增加退货数量 + * + * @param id + * @param num + * @return + */ + int addReturnNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + * @return + */ + int subReturnNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailMapper.java new file mode 100644 index 0000000..e46ab28 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetDetailMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-26 + */ +public interface SaleOutSheetDetailMapper extends BaseMapper { + + /** + * 根据出库单ID查询 + * + * @param sheetId + * @return + */ + List getBySheetId(String sheetId); + + /** + * 增加退货数量 + * + * @param id + * @param num + * @return + */ + int addReturnNum(@Param("id") String id, @Param("num") Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + * @return + */ + int subReturnNum(@Param("id") String id, @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetMapper.java new file mode 100644 index 0000000..81044a8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleOutSheetMapper.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetFullDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.sale.out.SaleOutSheetSelectorVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-10-26 + */ +public interface SaleOutSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QuerySaleOutSheetVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List selector(@Param("vo") SaleOutSheetSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleOutSheetFullDto getDetail(String id); + + /** + * 根据ID查询(销售退货业务) + * + * @param id + * @return + */ + SaleOutSheetWithReturnDto getWithReturn(@Param("id") String id, + @Param("requireOut") Boolean requireOut); + + /** + * 查询列表(销售退货业务) + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List queryWithReturn(@Param("vo") QuerySaleOutSheetWithReturnVo vo, + @Param("multipleRelate") boolean multipleRelate); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("customerId") String customerId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnDetailMapper.java new file mode 100644 index 0000000..4beb6b2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.SaleReturnDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-04 + */ +public interface SaleReturnDetailMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnMapper.java new file mode 100644 index 0000000..4a76d9c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/SaleReturnMapper.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.sale.returned.SaleReturnFullDto; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.sale.returned.QuerySaleReturnVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-04 + */ +public interface SaleReturnMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "r", autoParse = true), + @Sort(value = "createTime", alias = "r", autoParse = true), + @Sort(value = "approveTime", alias = "r", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "r") + }) + List query(@Param("vo") QuerySaleReturnVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleReturnFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("customerId") String customerId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailMapper.java new file mode 100644 index 0000000..adf1765 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailMapper.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetail; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 仓库调拨单明细 Mapper 接口 + *

+ * + * @author zmj + */ +public interface ScTransferOrderDetailMapper extends BaseMapper { + + /** + * 收货 + * + * @param productId + * @param receiveNum + * @return + */ + int receive(@Param("orderId") String orderId, @Param("productId") String productId, + @Param("receiveNum") Integer receiveNum); + + /** + * 统计未收货的商品 + * + * @param orderId + * @return + */ + int countUnReceive(@Param("orderId") String orderId); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailReceiveMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailReceiveMapper.java new file mode 100644 index 0000000..7e4925e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderDetailReceiveMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetailReceive; + +/** + *

+ * 仓库调拨单收货明细 Mapper 接口 + *

+ * + * @author zmj + */ +public interface ScTransferOrderDetailReceiveMapper extends + BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderMapper.java new file mode 100644 index 0000000..19c315b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/ScTransferOrderMapper.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferOrderFullDto; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferProductDto; +import com.lframework.xingyun.sc.entity.ScTransferOrder; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferProductVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 仓库调拨单 Mapper 接口 + *

+ * + * @author zmj + */ +public interface ScTransferOrderMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "createTime", alias = "tb", autoParse = true), + @Sort(value = "approveTime", alias = "tb", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List query(@Param("vo") QueryScTransferOrderVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ScTransferOrderFullDto getDetail(@Param("id") String id); + + /** + * 根据关键字查询库存成本调整单商品信息 + * + * @param scId + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryScTransferByCondition( + @Param("scId") String scId, @Param("condition") String condition); + + /** + * 查询库存成本调整单商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryScTransferList( + @Param("vo") QueryScTransferProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustReasonMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustReasonMapper.java new file mode 100644 index 0000000..f7bb9b4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustReasonMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.QueryStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.StockAdjustReasonSelectorVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2023-04-18 + */ +public interface StockAdjustReasonMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + @Sort(value = "createTime", alias = "tb", autoParse = true), + @Sort(value = "updateTime", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QueryStockAdjustReasonVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") StockAdjustReasonSelectorVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetDetailMapper.java new file mode 100644 index 0000000..3937183 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetDetailMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.StockAdjustSheetDetail; + +/** + *

+ * 库存调整单明细 Mapper 接口 + *

+ * + * @author zmj + */ +public interface StockAdjustSheetDetailMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetMapper.java new file mode 100644 index 0000000..053270a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockAdjustSheetMapper.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockAdjustSheet; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 库存调整单 Mapper 接口 + *

+ * + * @author zmj + */ +public interface StockAdjustSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "updateTime", alias = "tb", autoParse = true), + @Sort(value = "approveTime", alias = "tb", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List query(@Param("vo") QueryStockAdjustSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + StockAdjustSheetFullDto getDetail(@Param("id") String id); + + /** + * 根据关键字查询库存成本调整单商品信息 + * + * @param scId + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryStockAdjustByCondition( + @Param("scId") String scId, @Param("condition") String condition); + + /** + * 查询库存成本调整单商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryStockAdjustList( + @Param("vo") QueryStockAdjustProductVo vo); + + /** + * 根据商品ID查询库存成本调整单商品信息 + * + * @param scId + * @param sku + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + StockAdjustProductDto queryStockAdjustBySku( @Param("scId") String scId, @Param("sku") String sku); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetDetailMapper.java new file mode 100644 index 0000000..8752b56 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetDetailMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheetDetail; + +/** + *

+ * 库存成本调整单明细 Mapper 接口 + *

+ * + * @author zmj + */ +public interface StockCostAdjustSheetDetailMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetMapper.java new file mode 100644 index 0000000..817f1ae --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/StockCostAdjustSheetMapper.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheet; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 库存成本调整单 Mapper 接口 + *

+ * + * @author zmj + */ +public interface StockCostAdjustSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "updateTime", alias = "tb", autoParse = true), + @Sort(value = "approveTime", alias = "tb", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List query(@Param("vo") QueryStockCostAdjustSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + StockCostAdjustSheetFullDto getDetail(@Param("id") String id); + + /** + * 根据关键字查询库存成本调整单商品信息 + * + * @param scId + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryStockCostAdjustByCondition( + @Param("scId") String scId, @Param("condition") String condition); + + /** + * 查询库存成本调整单商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryStockCostAdjustList( + @Param("vo") QueryStockCostAdjustProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockConfigMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockConfigMapper.java new file mode 100644 index 0000000..82e738a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockConfigMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.TakeStockConfig; + +/** + *

+ * 盘点参数 Mapper 接口 + *

+ * + * @author zmj + */ +public interface TakeStockConfigMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanDetailMapper.java new file mode 100644 index 0000000..f315b8d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanDetailMapper.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.take.plan.GetTakeStockPlanDetailProductDto; +import com.lframework.xingyun.sc.entity.TakeStockPlanDetail; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 盘点任务详情 Mapper 接口 + *

+ * + * @author zmj + */ +public interface TakeStockPlanDetailMapper extends BaseMapper { + + /** + * 根据盘点任务ID、商品ID查询 + * + * @param planId + * @param productId + * @return + */ + GetTakeStockPlanDetailProductDto getByPlanIdAndProductId(@Param("planId") String planId, + @Param("productId") String productId); + + /** + * 根据盘点任务ID查询 + * + * @param planId + * @return + */ + List getDetailsByPlanId(String planId); + + /** + * 更新盘点数量 + * + * @param planId + * @param productId + * @param num + */ + void updateOriTakeNum(@Param("planId") String planId, @Param("productId") String productId, + @Param("num") Integer num); + + /** + * 增加进项数量 + * + * @param scId + * @param productId + * @param num + */ + void addTotalInNum(@Param("scId") String scId, @Param("productId") String productId, + @Param("num") Integer num); + + /** + * 增加出项数量 + * + * @param scId + * @param productId + * @param num + */ + void addTotalOutNum(@Param("scId") String scId, @Param("productId") String productId, + @Param("num") Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanMapper.java new file mode 100644 index 0000000..f7e8acc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockPlanMapper.java @@ -0,0 +1,68 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.take.plan.QueryTakeStockPlanProductDto; +import com.lframework.xingyun.sc.dto.stock.take.plan.TakeStockPlanFullDto; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.vo.stock.take.plan.QueryTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.TakeStockPlanSelectorVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 盘点任务 Mapper 接口 + *

+ * + * @author zmj + */ +public interface TakeStockPlanMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "createTime", alias = "tb", autoParse = true), + @Sort(value = "updateTime", alias = "tb", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List query(@Param("vo") QueryTakeStockPlanVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List selector(@Param("vo") TakeStockPlanSelectorVo vo); + + /** + * 根据盘点任务ID查询商品信息 + * + * @param planId + * @return + */ + List getProducts(@Param("planId") String planId); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + TakeStockPlanFullDto getDetail(String id); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetDetailMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetDetailMapper.java new file mode 100644 index 0000000..a3d2616 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetDetailMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.entity.TakeStockSheetDetail; + +/** + *

+ * 盘点单详情 Mapper 接口 + *

+ * + * @author zmj + */ +public interface TakeStockSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetMapper.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetMapper.java new file mode 100644 index 0000000..eaad548 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/mappers/TakeStockSheetMapper.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.sc.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.TakeStockSheet; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetProductVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 盘点单 Mapper 接口 + *

+ * + * @author zmj + */ +public interface TakeStockSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "updateTime", alias = "tb", autoParse = true), + @Sort(value = "approveTime", alias = "tb", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "tb") + }) + List query(@Param("vo") QueryTakeStockSheetVo vo); + + /** + * 根据ID查询详情 + * + * @param id + * @return + */ + TakeStockSheetFullDto getDetail(String id); + + /** + * 根据预先盘点单ID判断是否有盘点单关联 + * + * @param preSheetId + * @return + */ + Boolean hasRelatePreTakeStockSheet(String preSheetId); + + /** + * 根据盘点任务ID查询是否有未审核通过的盘点单 + * + * @param planId + * @return + */ + Boolean hasUnApprove(String planId); + + /** + * 根据关键字查询盘点单商品信息 + * + * @param condition + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryTakeStockByCondition(@Param("planId") String planId, + @Param("condition") String condition); + + /** + * 查询盘点单商品信息 + * + * @param vo + * @return + */ + @DataPermissions(type = SysDataPermissionDataPermissionType.PRODUCT, value = { + @DataPermission(template = "product", alias = "g"), + @DataPermission(template = "brand", alias = "b"), + @DataPermission(template = "category", alias = "c") + }) + List queryTakeStockList(@Param("vo") QueryTakeStockSheetProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetDetailService.java new file mode 100644 index 0000000..aa62115 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetDetailService.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.sc.service.logistics; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.LogisticsSheetDetail; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; + +public interface LogisticsSheetDetailService extends BaseMpService { + + /** + * 根据业务ID查询 + * + * @param bizId + * @param bizType + * @return + */ + LogisticsSheetDetail getByBizId(String bizId, LogisticsSheetDetailBizType bizType); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetService.java new file mode 100644 index 0000000..b03a024 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/logistics/LogisticsSheetService.java @@ -0,0 +1,101 @@ +package com.lframework.xingyun.sc.service.logistics; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetBizOrderDto; +import com.lframework.xingyun.sc.dto.logistics.LogisticsSheetFullDto; +import com.lframework.xingyun.sc.entity.LogisticsSheet; +import com.lframework.xingyun.sc.vo.logistics.CreateLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.DeliveryLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.LogisticsSheetSelectorVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetBizOrderVo; +import com.lframework.xingyun.sc.vo.logistics.QueryLogisticsSheetVo; +import com.lframework.xingyun.sc.vo.logistics.UpdateLogisticsSheetVo; +import java.util.List; + +public interface LogisticsSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryLogisticsSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryLogisticsSheetVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + LogisticsSheetSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + LogisticsSheetFullDto getDetail(String id); + + /** + * 查询业务单据列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryBizOrder(Integer pageIndex, Integer pageSize, + QueryLogisticsSheetBizOrderVo vo); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateLogisticsSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateLogisticsSheetVo vo); + + /** + * 发货 + * + * @param vo + */ + void delivery(DeliveryLogisticsSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/paytype/OrderPayTypeService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/paytype/OrderPayTypeService.java new file mode 100644 index 0000000..839ce00 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/paytype/OrderPayTypeService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.service.paytype; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.OrderPayType; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import java.util.List; + +public interface OrderPayTypeService extends BaseMpService { + + /** + * 创建 + * + * @param orderId + * @param data + */ + void create(String orderId, List data); + + /** + * 根据订单ID删除 + * + * @param orderId + */ + void deleteByOrderId(String orderId); + + /** + * 根据订单ID查询 + * + * @param orderId + * @return + */ + List findByOrderId(String orderId); +} \ No newline at end of file diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseConfigService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseConfigService.java new file mode 100644 index 0000000..342023a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseConfigService.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.vo.purchase.config.UpdatePurchaseConfigVo; + +public interface PurchaseConfigService extends BaseMpService { + + /** + * 查询 + * + * @return + */ + PurchaseConfig get(); + + /** + * 修改 + * + * @param vo + */ + void update(UpdatePurchaseConfigVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderDetailService.java new file mode 100644 index 0000000..967ef3c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderDetailService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import java.util.List; + +public interface PurchaseOrderDetailService extends BaseMpService { + + /** + * 根据订单ID查询 + * + * @param orderId + * @return + */ + List getByOrderId(String orderId); + + /** + * 增加收货数量 + * + * @param id + * @param num + */ + void addReceiveNum(String id, Integer num); + + /** + * 减少收货数量 + * + * @param id + * @param num + */ + void subReceiveNum(String id, Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderService.java new file mode 100644 index 0000000..81358b6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseOrderService.java @@ -0,0 +1,200 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderWithReceiveDto; +import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto; +import com.lframework.xingyun.sc.entity.PurchaseOrder; +import com.lframework.xingyun.sc.vo.purchase.ApprovePassPurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.ApproveRefusePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.BatchApprovePassPurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.BatchApproveRefusePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.CreatePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.PurchaseOrderSelectorVo; +import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderVo; +import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderWithReceiveVo; +import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseProductVo; +import com.lframework.xingyun.sc.vo.purchase.UpdatePurchaseOrderVo; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; + +import java.util.List; + +public interface PurchaseOrderService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryPurchaseOrderVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryPurchaseOrderVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + PurchaseOrderSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PurchaseOrderFullDto getDetail(String id); + + /** + * 根据ID查询(收货业务) + * + * @param id + * @return + */ + PurchaseOrderWithReceiveDto getWithReceive(String id); + + /** + * 查询列表(收货业务) + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryWithReceive(Integer pageIndex, Integer pageSize, + QueryPurchaseOrderWithReceiveVo vo); + + /** + * 创建订单 + * + * @param vo + * @return + */ + String create(CreatePurchaseOrderVo vo); + + /** + * 修改订单 + * + * @param vo + */ + void update(UpdatePurchaseOrderVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassPurchaseOrderVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassPurchaseOrderVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreatePurchaseOrderVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefusePurchaseOrderVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefusePurchaseOrderVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 取消审核 + * + * @param id + */ + void cancelApprovePass(String id); + + /** + * 根据关键字查询采购商品信息 + * + * @param pageIndex + * @param pageSize + * @param condition + * @return + */ + PageResult queryPurchaseByCondition(Integer pageIndex, Integer pageSize, String condition); + + /** + * 查询可采购商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryPurchaseList(Integer pageIndex, Integer pageSize, QueryPurchaseProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PurchaseProductDto getPurchaseById(String id); + + /** + * 云朵里审批反馈接收接口 + * @param vo + */ + void approve(YdoolApproveOrderVo vo); + + /** + * 发送审批 + * @param id + * @return + */ + InvokeResult sendApprove(String id); + + /** + * 根据SKU查询采购商品信息 + * @param sku + * @return + */ + PurchaseProductDto queryPurchaseBySku(String sku); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnDetailService.java new file mode 100644 index 0000000..643fa56 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.PurchaseReturnDetail; + +public interface PurchaseReturnDetailService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnService.java new file mode 100644 index 0000000..b4f928e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/PurchaseReturnService.java @@ -0,0 +1,145 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.purchase.returned.PurchaseReturnFullDto; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.purchase.returned.ApprovePassPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.ApproveRefusePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.BatchApprovePassPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.BatchApproveRefusePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.CreatePurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.QueryPurchaseReturnVo; +import com.lframework.xingyun.sc.vo.purchase.returned.UpdatePurchaseReturnVo; +import java.time.LocalDateTime; +import java.util.List; + +public interface PurchaseReturnService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryPurchaseReturnVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryPurchaseReturnVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PurchaseReturnFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreatePurchaseReturnVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdatePurchaseReturnVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassPurchaseReturnVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassPurchaseReturnVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreatePurchaseReturnVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefusePurchaseReturnVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefusePurchaseReturnVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String supplierId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetDetailService.java new file mode 100644 index 0000000..6c1dd5a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetDetailService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import java.util.List; + +public interface ReceiveSheetDetailService extends BaseMpService { + + /** + * 根据收货单ID查询 + * + * @param sheetId + * @return + */ + List getBySheetId(String sheetId); + + /** + * 增加退货数量 + * + * @param id + * @param num + */ + void addReturnNum(String id, Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + */ + void subReturnNum(String id, Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetService.java new file mode 100644 index 0000000..eef3036 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/purchase/ReceiveSheetService.java @@ -0,0 +1,185 @@ +package com.lframework.xingyun.sc.service.purchase; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetFullDto; +import com.lframework.xingyun.sc.dto.purchase.receive.ReceiveSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.purchase.receive.ApprovePassReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ApproveRefuseReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.BatchApprovePassReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.BatchApproveRefuseReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.CreateReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetVo; +import com.lframework.xingyun.sc.vo.purchase.receive.QueryReceiveSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.purchase.receive.ReceiveSheetSelectorVo; +import com.lframework.xingyun.sc.vo.purchase.receive.UpdateReceiveSheetVo; +import java.time.LocalDateTime; +import java.util.List; + +public interface ReceiveSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryReceiveSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryReceiveSheetVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, ReceiveSheetSelectorVo vo); + + /** + * 根据供应商ID查询默认付款日期 + * + * @param supplierId + */ + GetPaymentDateDto getPaymentDate(String supplierId); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ReceiveSheetFullDto getDetail(String id); + + /** + * 根据ID查询(采购退货业务) + * + * @param id + * @return + */ + ReceiveSheetWithReturnDto getWithReturn(String id); + + /** + * 查询列表(采购退货业务) + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryWithReturn(Integer pageIndex, Integer pageSize, + QueryReceiveSheetWithReturnVo vo); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateReceiveSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateReceiveSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassReceiveSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassReceiveSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateReceiveSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseReceiveSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseReceiveSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String supplierId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailConfigService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailConfigService.java new file mode 100644 index 0000000..a22e672 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailConfigService.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.RetailConfig; +import com.lframework.xingyun.sc.vo.retail.config.UpdateRetailConfigVo; + +public interface RetailConfigService extends BaseMpService { + + /** + * 查询 + * + * @return + */ + RetailConfig get(); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateRetailConfigVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailBundleService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailBundleService.java new file mode 100644 index 0000000..6355ab8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailBundleService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailBundle; + +public interface RetailOutSheetDetailBundleService extends + BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailLotService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailLotService.java new file mode 100644 index 0000000..15f4c91 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailLotService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetailLot; + +public interface RetailOutSheetDetailLotService extends BaseMpService { + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailOutSheetDetailLotDto findById(String id); + + /** + * 增加退货数量 + * + * @param id + * @param num + */ + void addReturnNum(String id, Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + */ + void subReturnNum(String id, Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailService.java new file mode 100644 index 0000000..e4bd908 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetDetailService.java @@ -0,0 +1,47 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetail; +import java.math.BigDecimal; +import java.util.List; + +public interface RetailOutSheetDetailService extends BaseMpService { + + /** + * 根据出库单ID查询 + * + * @param sheetId + * @return + */ + List getBySheetId(String sheetId); + + /** + * 增加退货数量 + * + * @param id + * @param num + */ + void addReturnNum(String id, Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + */ + void subReturnNum(String id, Integer num); + + /** + * 根据出库单ID查询商品总重量 + * @param sheetIds + * @return + */ + BigDecimal getTotalWeightBySheetIds(List sheetIds); + + /** + * 根据出库单ID查询商品总体积 + * @param sheetIds + * @return + */ + BigDecimal getTotalVolumeBySheetIds(List sheetIds); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetService.java new file mode 100644 index 0000000..58cea6f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailOutSheetService.java @@ -0,0 +1,188 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.retail.RetailProductDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetFullDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.RetailOutSheet; +import com.lframework.xingyun.sc.vo.retail.out.*; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; + +import java.util.List; + +public interface RetailOutSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryRetailOutSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryRetailOutSheetVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + RetailOutSheetSelectorVo vo); + + /** + * 根据会员ID查询默认付款日期 + * + * @param memberId + */ + GetPaymentDateDto getPaymentDate(String memberId); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailOutSheetFullDto getDetail(String id); + + /** + * 根据ID查询(零售退货业务) + * + * @param id + * @return + */ + RetailOutSheetWithReturnDto getWithReturn(String id); + + /** + * 查询列表(零售退货业务) + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryWithReturn(Integer pageIndex, Integer pageSize, + QueryRetailOutSheetWithReturnVo vo); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateRetailOutSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateRetailOutSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassRetailOutSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassRetailOutSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateRetailOutSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseRetailOutSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseRetailOutSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 根据关键字查询零售商品信息 + * + * @param pageIndex + * @param pageSize + * @param condition + * @return + */ + PageResult queryRetailByCondition(Integer pageIndex, Integer pageSize, + String condition, Boolean isReturn); + + /** + * 查询可零售商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryRetailList(Integer pageIndex, Integer pageSize, + QueryRetailProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailProductDto getRetailById(String id); + + /** + * 发送审批 + * + * @param id + * @return + */ + InvokeResult sendApprove(String id); + + /** + * 云朵里审批反馈接收接口 + * @param vo + */ + void approve(YdoolApproveOrderVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnDetailService.java new file mode 100644 index 0000000..f5a9358 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.RetailReturnDetail; + +public interface RetailReturnDetailService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnService.java new file mode 100644 index 0000000..0bdda78 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/retail/RetailReturnService.java @@ -0,0 +1,107 @@ +package com.lframework.xingyun.sc.service.retail; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.retail.returned.RetailReturnFullDto; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.vo.retail.returned.ApprovePassRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.ApproveRefuseRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.BatchApprovePassRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.BatchApproveRefuseRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.CreateRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.QueryRetailReturnVo; +import com.lframework.xingyun.sc.vo.retail.returned.UpdateRetailReturnVo; +import java.util.List; + +public interface RetailReturnService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryRetailReturnVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryRetailReturnVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + RetailReturnFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateRetailReturnVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateRetailReturnVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassRetailReturnVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassRetailReturnVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateRetailReturnVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseRetailReturnVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseRetailReturnVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleConfigService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleConfigService.java new file mode 100644 index 0000000..96059a1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleConfigService.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.vo.sale.config.UpdateSaleConfigVo; + +public interface SaleConfigService extends BaseMpService { + + /** + * 查询 + * + * @return + */ + SaleConfig get(); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSaleConfigVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailBundleService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailBundleService.java new file mode 100644 index 0000000..e3d565a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailBundleService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.SaleOrderDetailBundle; + +public interface SaleOrderDetailBundleService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailService.java new file mode 100644 index 0000000..1527c62 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderDetailService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import java.util.List; + +public interface SaleOrderDetailService extends BaseMpService { + + /** + * 根据订单ID查询 + * + * @param orderId + * @return + */ + List getByOrderId(String orderId); + + /** + * 增加出库数量 + * + * @param id + * @param num + */ + void addOutNum(String id, Integer num); + + /** + * 减少出库数量 + * + * @param id + * @param num + */ + void subOutNum(String id, Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderService.java new file mode 100644 index 0000000..3f4ffb1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOrderService.java @@ -0,0 +1,186 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto; +import com.lframework.xingyun.sc.dto.sale.SaleOrderWithOutDto; +import com.lframework.xingyun.sc.dto.sale.SaleProductDto; +import com.lframework.xingyun.sc.entity.SaleOrder; +import com.lframework.xingyun.sc.vo.sale.ApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.ApproveRefuseSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.BatchApprovePassSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.BatchApproveRefuseSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.CreateSaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderWithOutVo; +import com.lframework.xingyun.sc.vo.sale.QuerySaleProductVo; +import com.lframework.xingyun.sc.vo.sale.SaleOrderSelectorVo; +import com.lframework.xingyun.sc.vo.sale.UpdateSaleOrderVo; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; + +import java.util.List; + +public interface SaleOrderService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySaleOrderVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySaleOrderVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SaleOrderSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleOrderFullDto getDetail(String id); + + /** + * 根据ID查询(发货业务) + * + * @param id + * @return + */ + SaleOrderWithOutDto getWithOut(String id); + + /** + * 查询列表(出库业务) + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryWithOut(Integer pageIndex, Integer pageSize, + QuerySaleOrderWithOutVo vo); + + /** + * 创建订单 + * + * @param vo + * @return + */ + String create(CreateSaleOrderVo vo); + + /** + * 修改订单 + * + * @param vo + */ + void update(UpdateSaleOrderVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSaleOrderVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSaleOrderVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSaleOrderVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSaleOrderVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSaleOrderVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 根据关键字查询销售商品信息 + * + * @param pageIndex + * @param pageSize + * @param condition + * @return + */ + PageResult querySaleByCondition(Integer pageIndex, Integer pageSize, String condition, Boolean isReturn); + + /** + * 查询可销售商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult querySaleList(Integer pageIndex, Integer pageSize, QuerySaleProductVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleProductDto getSaleById(String id); + + /** + * 发送审批流程给ydool系统 + * @param id + * @return + */ + InvokeResult sendApprove(String id); + + + /** + * 云朵里审批反馈接收接口 + * @param vo + */ + void approve(YdoolApproveOrderVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailBundleService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailBundleService.java new file mode 100644 index 0000000..072a2eb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailBundleService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailBundle; + +public interface SaleOutSheetDetailBundleService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailLotService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailLotService.java new file mode 100644 index 0000000..319aed2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailLotService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailLot; + +public interface SaleOutSheetDetailLotService extends BaseMpService { + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleOutSheetDetailLotDto findById(String id); + + /** + * 增加退货数量 + * + * @param id + * @param num + */ + void addReturnNum(String id, Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + */ + void subReturnNum(String id, Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailService.java new file mode 100644 index 0000000..e349ce8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetDetailService.java @@ -0,0 +1,47 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import java.math.BigDecimal; +import java.util.List; + +public interface SaleOutSheetDetailService extends BaseMpService { + + /** + * 根据出库单ID查询 + * + * @param sheetId + * @return + */ + List getBySheetId(String sheetId); + + /** + * 增加退货数量 + * + * @param id + * @param num + */ + void addReturnNum(String id, Integer num); + + /** + * 减少退货数量 + * + * @param id + * @param num + */ + void subReturnNum(String id, Integer num); + + /** + * 根据出库单ID查询商品总重量 + * @param sheetIds + * @return + */ + BigDecimal getTotalWeightBySheetIds(List sheetIds); + + /** + * 根据出库单ID查询商品总体积 + * @param sheetIds + * @return + */ + BigDecimal getTotalVolumeBySheetIds(List sheetIds); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetService.java new file mode 100644 index 0000000..a7d1cce --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleOutSheetService.java @@ -0,0 +1,185 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetFullDto; +import com.lframework.xingyun.sc.dto.sale.out.SaleOutSheetWithReturnDto; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.sale.out.ApprovePassSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.ApproveRefuseSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.BatchApprovePassSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.BatchApproveRefuseSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.CreateSaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetVo; +import com.lframework.xingyun.sc.vo.sale.out.QuerySaleOutSheetWithReturnVo; +import com.lframework.xingyun.sc.vo.sale.out.SaleOutSheetSelectorVo; +import com.lframework.xingyun.sc.vo.sale.out.UpdateSaleOutSheetVo; +import java.time.LocalDateTime; +import java.util.List; + +public interface SaleOutSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySaleOutSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySaleOutSheetVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SaleOutSheetSelectorVo vo); + + /** + * 根据客户ID查询默认付款日期 + * + * @param customerId + */ + GetPaymentDateDto getPaymentDate(String customerId); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleOutSheetFullDto getDetail(String id); + + /** + * 根据ID查询(销售退货业务) + * + * @param id + * @return + */ + SaleOutSheetWithReturnDto getWithReturn(String id); + + /** + * 查询列表(销售退货业务) + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryWithReturn(Integer pageIndex, Integer pageSize, + QuerySaleOutSheetWithReturnVo vo); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSaleOutSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSaleOutSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSaleOutSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSaleOutSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSaleOutSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSaleOutSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSaleOutSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnDetailService.java new file mode 100644 index 0000000..d972783 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.SaleReturnDetail; + +public interface SaleReturnDetailService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnService.java new file mode 100644 index 0000000..0ae4253 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/sale/SaleReturnService.java @@ -0,0 +1,145 @@ +package com.lframework.xingyun.sc.service.sale; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.sale.returned.SaleReturnFullDto; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.vo.sale.returned.ApprovePassSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.ApproveRefuseSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.BatchApprovePassSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.BatchApproveRefuseSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.CreateSaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.QuerySaleReturnVo; +import com.lframework.xingyun.sc.vo.sale.returned.UpdateSaleReturnVo; +import java.time.LocalDateTime; +import java.util.List; + +public interface SaleReturnService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySaleReturnVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySaleReturnVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SaleReturnFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSaleReturnVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSaleReturnVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSaleReturnVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSaleReturnVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSaleReturnVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSaleReturnVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSaleReturnVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockLogService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockLogService.java new file mode 100644 index 0000000..9991a35 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockLogService.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.service.stock; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.ProductStockLog; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithAddStockVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithStockCostAdjustVo; +import com.lframework.xingyun.sc.vo.stock.log.AddLogWithSubStockVo; +import com.lframework.xingyun.sc.vo.stock.log.QueryProductStockLogVo; +import java.util.List; + +public interface ProductStockLogService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryProductStockLogVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryProductStockLogVo vo); + + /** + * 添加入库记录 + */ + void addLogWithAddStock(AddLogWithAddStockVo vo); + + /** + * 添加出库记录 + */ + void addLogWithSubStock(AddLogWithSubStockVo vo); + + /** + * 添加库存成本调整记录 + * + * @param vo + */ + void addLogWithStockCostAdjust(AddLogWithStockCostAdjustVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockService.java new file mode 100644 index 0000000..33b5dc6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/ProductStockService.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.sc.service.stock; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.core.dto.stock.ProductStockChangeDto; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustDiffDto; +import com.lframework.xingyun.sc.entity.ProductStock; +import com.lframework.xingyun.sc.vo.stock.AddProductStockVo; +import com.lframework.xingyun.sc.vo.stock.QueryProductStockVo; +import com.lframework.xingyun.sc.vo.stock.StockCostAdjustVo; +import com.lframework.xingyun.sc.vo.stock.SubProductStockVo; +import java.util.List; + +public interface ProductStockService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryProductStockVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryProductStockVo vo); + + /** + * 根据商品ID、仓库ID查询 + * + * @param productId + * @param scId + * @return + */ + ProductStock getByProductIdAndScId(String productId, String scId); + + /** + * 根据商品ID、仓库ID查询 + * + * @param productIds + * @param scId + * @return + */ + List getByProductIdsAndScId(List productIds, String scId, + Integer productType); + + /** + * 入库 + * + * @param vo + */ + ProductStockChangeDto addStock(AddProductStockVo vo); + + /** + * 出库 + * + * @param vo + */ + ProductStockChangeDto subStock(SubProductStockVo vo); + + /** + * 库存成本调整 + * + * @param vo + */ + StockCostAdjustDiffDto stockCostAdjust(StockCostAdjustVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustReasonService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustReasonService.java new file mode 100644 index 0000000..e3cc00f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustReasonService.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.sc.service.stock.adjust; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.StockAdjustReason; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.CreateStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.QueryStockAdjustReasonVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.StockAdjustReasonSelectorVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.reason.UpdateStockAdjustReasonVo; +import java.util.Collection; +import java.util.List; + +public interface StockAdjustReasonService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryStockAdjustReasonVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryStockAdjustReasonVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + StockAdjustReasonSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + StockAdjustReason findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateStockAdjustReasonVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateStockAdjustReasonVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetDetailService.java new file mode 100644 index 0000000..5874b5a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetDetailService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.sc.service.stock.adjust; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.StockAdjustSheetDetail; + +public interface StockAdjustSheetDetailService extends + BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetService.java new file mode 100644 index 0000000..59964b4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockAdjustSheetService.java @@ -0,0 +1,161 @@ +package com.lframework.xingyun.sc.service.stock.adjust; + +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.stock.StockAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockAdjustSheet; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.ApprovePassStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.ApproveRefuseStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.BatchApprovePassStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.BatchApproveRefuseStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.CreateStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.QueryStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.stock.UpdateStockAdjustSheetVo; +import com.lframework.xingyun.sc.vo.ydool.YdoolApproveOrderVo; + +import java.util.List; + +/** + * 库存调整单 Service + * + * @author zmj + */ +public interface StockAdjustSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryStockAdjustSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryStockAdjustSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + StockAdjustSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateStockAdjustSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateStockAdjustSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + * @return + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassStockAdjustSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassStockAdjustSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateStockAdjustSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseStockAdjustSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseStockAdjustSheetVo vo); + + /** + * 根据关键字查询库存成本调整单商品信息 + * + * @param pageIndex + * @param pageSize + * @param scId + * @param condition + * @return + */ + PageResult queryStockAdjustByCondition(Integer pageIndex, Integer pageSize, + String scId, String condition); + + /** + * 查询库存成本调整单商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryStockAdjustList(Integer pageIndex, Integer pageSize, + QueryStockAdjustProductVo vo); + + /** + * 发送审批 + * + * @param id + * @return + */ + InvokeResult sendApprove(String id); + + /** + * 云朵里审批反馈接收接口 + * @param vo + */ + void approve(YdoolApproveOrderVo vo); + + /** + * 根据SKU查询库存成本调整单商品信息 + * @param scId + * @param sku + * @return + */ + StockAdjustProductDto queryStockAdjustBySku(String scId, String sku); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetDetailService.java new file mode 100644 index 0000000..47a455e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetDetailService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.sc.service.stock.adjust; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheetDetail; + +public interface StockCostAdjustSheetDetailService extends + BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetService.java new file mode 100644 index 0000000..f1084fb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/adjust/StockCostAdjustSheetService.java @@ -0,0 +1,136 @@ +package com.lframework.xingyun.sc.service.stock.adjust; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustProductDto; +import com.lframework.xingyun.sc.dto.stock.adjust.cost.StockCostAdjustSheetFullDto; +import com.lframework.xingyun.sc.entity.StockCostAdjustSheet; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.ApprovePassStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.ApproveRefuseStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.BatchApprovePassStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.BatchApproveRefuseStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.CreateStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustProductVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.QueryStockCostAdjustSheetVo; +import com.lframework.xingyun.sc.vo.stock.adjust.cost.UpdateStockCostAdjustSheetVo; +import java.util.List; + +/** + * 库存成本调整单 Service + * + * @author zmj + */ +public interface StockCostAdjustSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryStockCostAdjustSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryStockCostAdjustSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + StockCostAdjustSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateStockCostAdjustSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateStockCostAdjustSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + * @return + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassStockCostAdjustSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassStockCostAdjustSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateStockCostAdjustSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseStockCostAdjustSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseStockCostAdjustSheetVo vo); + + /** + * 根据关键字查询库存成本调整单商品信息 + * + * @param pageIndex + * @param pageSize + * @param scId + * @param condition + * @return + */ + PageResult queryStockCostAdjustByCondition(Integer pageIndex, Integer pageSize, + String scId, String condition); + + /** + * 查询库存成本调整单商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryStockCostAdjustList(Integer pageIndex, Integer pageSize, + QueryStockCostAdjustProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetDetailService.java new file mode 100644 index 0000000..e12bb66 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.PreTakeStockSheetDetail; + +public interface PreTakeStockSheetDetailService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetService.java new file mode 100644 index 0000000..c494536 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/PreTakeStockSheetService.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockProductDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.PreTakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.pre.QueryPreTakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.PreTakeStockSheet; +import com.lframework.xingyun.sc.vo.stock.take.pre.CreatePreTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.PreTakeStockSheetSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockProductVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.QueryPreTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.pre.UpdatePreTakeStockSheetVo; +import java.util.List; + +/** + * 预先盘点单 Service + * + * @author zmj + */ +public interface PreTakeStockSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryPreTakeStockSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryPreTakeStockSheetVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + PreTakeStockSheetSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + PreTakeStockSheetFullDto getDetail(String id); + + /** + * 根据预先盘点单、盘点任务查询商品信息 + * + * @param id + * @param planId + * @return + */ + List getProducts(String id, String planId); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreatePreTakeStockSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdatePreTakeStockSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据ID批量删除 + * + * @param ids + */ + void batchDelete(List ids); + + /** + * 根据关键字查询预先盘点单商品信息 + * + * @param pageIndex + * @param pageSize + * @param condition + * @return + */ + PageResult queryPreTakeStockByCondition(Integer pageIndex, Integer pageSize, + String condition); + + /** + * 查询预先盘点单商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryPreTakeStockList(Integer pageIndex, Integer pageSize, + QueryPreTakeStockProductVo vo); + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockConfigService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockConfigService.java new file mode 100644 index 0000000..c42ae83 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockConfigService.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.TakeStockConfig; +import com.lframework.xingyun.sc.vo.stock.take.config.UpdateTakeStockConfigVo; + +/** + * 盘点参数 Service + * + * @author zmj + */ +public interface TakeStockConfigService extends BaseMpService { + + /** + * 根据ID查询 + * + * @return + */ + TakeStockConfig get(); + + + /** + * 修改 + * + * @param vo + */ + void update(UpdateTakeStockConfigVo vo); + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanDetailService.java new file mode 100644 index 0000000..9ba6817 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanDetailService.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.take.plan.GetTakeStockPlanDetailProductDto; +import com.lframework.xingyun.sc.entity.TakeStockPlanDetail; +import java.util.List; + +public interface TakeStockPlanDetailService extends BaseMpService { + + /** + * 根据盘点任务ID、商品ID查询 + * + * @param planId + * @param productId + * @return + */ + GetTakeStockPlanDetailProductDto getByPlanIdAndProductId(String planId, String productId); + + /** + * 单品盘点-保存盘点任务明细 + * + * @param planId + * @param productIds + */ + void savePlanDetailBySimple(String planId, List productIds); + + /** + * 根据盘点任务ID查询 + * + * @param planId + * @return + */ + List getDetailsByPlanId(String planId); + + /** + * 更新盘点数量 + * + * @param planId + * @param productId + * @param num + */ + void updateOriTakeNum(String planId, String productId, Integer num); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanService.java new file mode 100644 index 0000000..33fb192 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockPlanService.java @@ -0,0 +1,108 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.take.plan.QueryTakeStockPlanProductDto; +import com.lframework.xingyun.sc.dto.stock.take.plan.TakeStockPlanFullDto; +import com.lframework.xingyun.sc.entity.TakeStockPlan; +import com.lframework.xingyun.sc.vo.stock.take.plan.CancelTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.CreateTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.HandleTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.QueryTakeStockPlanVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.TakeStockPlanSelectorVo; +import com.lframework.xingyun.sc.vo.stock.take.plan.UpdateTakeStockPlanVo; +import java.util.List; + +/** + * 盘点任务 Service + * + * @author zmj + */ +public interface TakeStockPlanService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryTakeStockPlanVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryTakeStockPlanVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + TakeStockPlanSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + TakeStockPlanFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateTakeStockPlanVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateTakeStockPlanVo vo); + + /** + * 根据盘点任务ID查询商品信息 + * + * @param planId + * @return + */ + List getProducts(String planId); + + /** + * 差异生成 + * + * @param id + */ + void createDiff(String id); + + /** + * 差异处理 + * + * @param vo + */ + void handleDiff(HandleTakeStockPlanVo vo); + + /** + * 作废 + * + * @param vo + */ + void cancel(CancelTakeStockPlanVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetDetailService.java new file mode 100644 index 0000000..664d577 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.TakeStockSheetDetail; + +public interface TakeStockSheetDetailService extends BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetService.java new file mode 100644 index 0000000..0625f02 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/take/TakeStockSheetService.java @@ -0,0 +1,156 @@ +package com.lframework.xingyun.sc.service.stock.take; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetFullDto; +import com.lframework.xingyun.sc.dto.stock.take.sheet.TakeStockSheetProductDto; +import com.lframework.xingyun.sc.entity.TakeStockSheet; +import com.lframework.xingyun.sc.vo.stock.take.sheet.ApprovePassTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.ApproveRefuseTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.BatchApprovePassTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.BatchApproveRefuseTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.CreateTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetProductVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.QueryTakeStockSheetVo; +import com.lframework.xingyun.sc.vo.stock.take.sheet.UpdateTakeStockSheetVo; +import java.util.List; + +/** + * 盘点单 Service + * + * @author zmj + */ +public interface TakeStockSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryTakeStockSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryTakeStockSheetVo vo); + + /** + * 根据ID查询详情 + * + * @param id + * @return + */ + TakeStockSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateTakeStockSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateTakeStockSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassTakeStockSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassTakeStockSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateTakeStockSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseTakeStockSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseTakeStockSheetVo vo); + + /** + * 取消审核 + * + * @param id + */ + void cancelApprovePass(String id); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据ID删除 + * + * @param ids + */ + void batchDelete(List ids); + + /** + * 根据预先盘点单ID判断是否有盘点单关联 + * + * @param preSheetId + * @return + */ + Boolean hasRelatePreTakeStockSheet(String preSheetId); + + /** + * 根据盘点任务ID查询是否有未审核通过的盘点单 + * + * @param planId + * @return + */ + Boolean hasUnApprove(String planId); + + /** + * 根据关键字查询盘点单商品信息 + * + * @param pageIndex + * @param pageSize + * @param condition + * @return + */ + PageResult queryTakeStockByCondition(Integer pageIndex, Integer pageSize, String planId, + String condition); + + /** + * 查询盘点单商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryTakeStockList(Integer pageIndex, Integer pageSize, + QueryTakeStockSheetProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailReceiveService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailReceiveService.java new file mode 100644 index 0000000..0d13bda --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailReceiveService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.sc.service.stock.transfer; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetailReceive; + +public interface ScTransferOrderDetailReceiveService extends + BaseMpService { + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailService.java new file mode 100644 index 0000000..745eab8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderDetailService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.sc.service.stock.transfer; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.entity.ScTransferOrderDetail; + +public interface ScTransferOrderDetailService extends BaseMpService { + + /** + * 收货 + * + * @param productId + * @param receiveNum + * @return + */ + int receive(String orderId, String productId, Integer receiveNum); + + /** + * 统计未收货的商品 + * + * @param orderId + * @return + */ + int countUnReceive(String orderId); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderService.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderService.java new file mode 100644 index 0000000..86189ef --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/service/stock/transfer/ScTransferOrderService.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.sc.service.stock.transfer; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferOrderFullDto; +import com.lframework.xingyun.sc.dto.stock.transfer.ScTransferProductDto; +import com.lframework.xingyun.sc.entity.ScTransferOrder; +import com.lframework.xingyun.sc.vo.stock.transfer.ApprovePassScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ApproveRefuseScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.BatchApprovePassScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.BatchApproveRefuseScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.CreateScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.QueryScTransferProductVo; +import com.lframework.xingyun.sc.vo.stock.transfer.ReceiveScTransferOrderVo; +import com.lframework.xingyun.sc.vo.stock.transfer.UpdateScTransferOrderVo; +import java.util.List; + +public interface ScTransferOrderService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryScTransferOrderVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryScTransferOrderVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + ScTransferOrderFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateScTransferOrderVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateScTransferOrderVo vo); + + /** + * 根据ID删除 + * + * @param id + * @return + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassScTransferOrderVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassScTransferOrderVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateScTransferOrderVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseScTransferOrderVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseScTransferOrderVo vo); + + /** + * 收货 + * @param vo + */ + void receive(ReceiveScTransferOrderVo vo); + + /** + * 根据关键字查询仓库调拨单商品信息 + * + * @param pageIndex + * @param pageSize + * @param scId + * @param condition + * @return + */ + PageResult queryScTransferByCondition(Integer pageIndex, Integer pageSize, + String scId, String condition); + + /** + * 查询仓库调拨单商品信息 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryScTransferList(Integer pageIndex, Integer pageSize, + QueryScTransferProductVo vo); +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/utils/WebUtils.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/utils/WebUtils.java new file mode 100644 index 0000000..657d512 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/utils/WebUtils.java @@ -0,0 +1,109 @@ +package com.lframework.xingyun.sc.utils; + +import cn.hutool.core.collection.ArrayIter; +import cn.hutool.core.collection.IterUtil; +import cn.hutool.core.map.CaseInsensitiveMap; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.ArrayUtil; + +import org.springframework.util.Assert; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; + + +public class WebUtils { + + private static final String UNKNOWN ="unknown"; + + public static HttpServletRequest getHttpRequest() { + ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + Assert.notNull(attributes, "RequestContextHolder.getRequestAttributes can't be NULL"); + return attributes.getRequest(); + } + + public static HttpServletRequest getRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getRequest(); + } + + public static HttpServletResponse getResponse() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getResponse(); + } + + public static void redirect(String url) throws Exception { + redirect(getResponse(), url); + } + + public static void redirect(HttpServletResponse response, String url) throws Exception { + response.sendRedirect(url); + } + + public static void addCookie(String name, String value) { + getResponse().addCookie(new Cookie(name, value)); + } + + public static void addCookie(String name, String value, int expiry) { + Cookie cookie = new Cookie(name, value); + cookie.setMaxAge(expiry); + cookie.setPath("/"); + getResponse().addCookie(cookie); + } + + public static String getCookie(String name) { + Map cookieMap = readCookieMap(getRequest()); + return cookieMap.containsKey(name) ? ((Cookie)cookieMap.get(name)).getValue() : null; + } + + public static Map readCookieMap(HttpServletRequest httpServletRequest) { + Cookie[] cookies = httpServletRequest.getCookies(); + return ArrayUtil.isEmpty(cookies) ? MapUtil.empty() : IterUtil.toMap(new ArrayIter(httpServletRequest.getCookies()), new CaseInsensitiveMap(), Cookie::getName); + } + + + + public static String getRemoteIpAddress() { + return getRemoteIpAddress(getRequest()); + } + + public static String getRemoteIpAddress(HttpServletRequest request) { + String ip = null; + // X-Forwarded-For:Squid 服务代理 + String ipAddresses = request.getHeader("X-Forwarded-For"); + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // Proxy-Client-IP:apache 服务代理 + ipAddresses = request.getHeader("Proxy-Client-IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ipAddresses = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // WL-Proxy-Client-IP:weblogic 服务代理 + ipAddresses = request.getHeader("WL-Proxy-Client-IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // HTTP_CLIENT_IP:有些代理服务器 + ipAddresses = request.getHeader("HTTP_CLIENT_IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // X-Real-IP:nginx服务代理 + ipAddresses = request.getHeader("X-Real-IP"); + } + // 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP + if (CharSequenceUtil.isNotBlank(ipAddresses)) { + ip = ipAddresses.split(",")[0]; + } + // 还是不能获取到,最后再通过request.getRemoteAddr();获取 + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ip = request.getRemoteAddr(); + } + return ip; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/address/CreateOrderAddressVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/address/CreateOrderAddressVo.java new file mode 100644 index 0000000..38b44bc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/address/CreateOrderAddressVo.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.sc.vo.address; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.basedata.enums.AddressType; +import com.lframework.xingyun.sc.enums.OrderAddressOrderType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateOrderAddressVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + private String orderId; + + /** + * 地址类型 + */ + @ApiModelProperty(value = "订单类型", required = true) + @NotNull(message = "订单类型不能为空!") + @IsEnum(message = "订单类型格式错误!", enumClass = OrderAddressOrderType.class) + private Integer orderType; + + /** + * 地址类型 + */ + @ApiModelProperty(value = "地址类型", required = true) + @NotNull(message = "地址类型不能为空!") + @IsEnum(message = "地址类型格式错误!", enumClass = AddressType.class) + private Integer addressType; + + /** + * 姓名 + */ + @ApiModelProperty(value = "姓名", required = true) + @NotBlank(message = "姓名不能为空!") + private String name; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 省ID + */ + @ApiModelProperty(value = "省ID", required = true) + @NotBlank(message = "省ID不能为空!") + private String provinceId; + + /** + * 市ID + */ + @ApiModelProperty(value = "市ID", required = true) + @NotBlank(message = "市ID不能为空!") + private String cityId; + + /** + * 区ID + */ + @ApiModelProperty(value = "区ID", required = true) + @NotBlank(message = "区ID不能为空!") + private String districtId; + + /** + * 详细地址 + */ + @ApiModelProperty(value = "详细地址", required = true) + @NotBlank(message = "详细地址不能为空!") + private String address; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/CreateLogisticsSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/CreateLogisticsSheetVo.java new file mode 100644 index 0000000..e37ae62 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/CreateLogisticsSheetVo.java @@ -0,0 +1,149 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateLogisticsSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 物流单号 + */ + @ApiModelProperty(value = "物流单号") + private String logisticsNo; + + /** + * 物流公司ID + */ + @ApiModelProperty(value = "物流公司ID", required = true) + @NotBlank(message = "物流公司ID不能为空!") + private String logisticsCompanyId; + + /** + * 寄件人姓名 + */ + @ApiModelProperty(value = "寄件人姓名", required = true) + @NotBlank(message = "寄件人姓名不能为空!") + private String senderName; + + /** + * 寄件人联系电话 + */ + @ApiModelProperty(value = "寄件人联系电话", required = true) + @NotBlank(message = "寄件人联系电话不能为空!") + private String senderTelephone; + + /** + * 寄件人省 + */ + @ApiModelProperty(value = "寄件人省", required = true) + @NotBlank(message = "寄件人省不能为空!") + private String senderProvinceId; + + /** + * 寄件人市 + */ + @ApiModelProperty(value = "寄件人市", required = true) + @NotBlank(message = "寄件人市不能为空!") + private String senderCityId; + + /** + * 寄件人区 + */ + @ApiModelProperty(value = "寄件人区", required = true) + @NotBlank(message = "寄件人区不能为空!") + private String senderDistrictId; + + /** + * 寄件人地址 + */ + @ApiModelProperty(value = "寄件人地址", required = true) + @NotBlank(message = "寄件人地址不能为空!") + private String senderAddress; + + /** + * 收件人姓名 + */ + @ApiModelProperty(value = "收件人姓名", required = true) + @NotBlank(message = "收件人姓名不能为空!") + private String receiverName; + + /** + * 收件人联系电话 + */ + @ApiModelProperty(value = "收件人联系电话", required = true) + @NotBlank(message = "收件人联系电话不能为空!") + private String receiverTelephone; + + /** + * 收件人省 + */ + @ApiModelProperty(value = "收件人省", required = true) + @NotBlank(message = "收件人省不能为空!") + private String receiverProvinceId; + + /** + * 收件人市 + */ + @ApiModelProperty(value = "收件人市", required = true) + @NotBlank(message = "收件人市不能为空!") + private String receiverCityId; + + /** + * 收件人区 + */ + @ApiModelProperty(value = "收件人区", required = true) + @NotBlank(message = "收件人区不能为空!") + private String receiverDistrictId; + + /** + * 收件人地址 + */ + @ApiModelProperty(value = "收件人地址", required = true) + @NotBlank(message = "收件人地址不能为空!") + private String receiverAddress; + + /** + * 总重量 + */ + @ApiModelProperty(value = "总重量") + @Min(value = 0, message = "总重量必须大于0!") + private BigDecimal totalWeight; + + /** + * 总体积 + */ + @ApiModelProperty(value = "总体积") + @Min(value = 0, message = "总体积必须大于0!") + private BigDecimal totalVolume; + + /** + * 物流费 + */ + @ApiModelProperty(value = "物流费") + @Min(value = 0, message = "物流费必须大于0!") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 业务单据 + */ + @NotEmpty(message = "业务单据不能为空!") + @Valid + private List bizOrders; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/DeliveryLogisticsSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/DeliveryLogisticsSheetVo.java new file mode 100644 index 0000000..34bc818 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/DeliveryLogisticsSheetVo.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class DeliveryLogisticsSheetVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 物流单号 + */ + @ApiModelProperty("物流单号") + private String logisticsNo; + + /** + * 物流费 + */ + @ApiModelProperty("物流费") + @Min(value = 0, message = "物流费必须大于0!") + private BigDecimal totalAmount; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetBizOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetBizOrderVo.java new file mode 100644 index 0000000..0ef3e52 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetBizOrderVo.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class LogisticsSheetBizOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据ID + */ + @ApiModelProperty(value = "业务单据ID", required = true) + @NotBlank(message = "业务单据ID不能为空!") + private String bizId; + + /** + * 业务类型 + */ + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型格式错误!", enumClass = LogisticsSheetDetailBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetCalcWeightOrVolumeVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetCalcWeightOrVolumeVo.java new file mode 100644 index 0000000..06eb4dc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetCalcWeightOrVolumeVo.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.LogisticsSheetDetailBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class LogisticsSheetCalcWeightOrVolumeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据 + */ + @ApiModelProperty(value = "业务单据", required = true) + @NotEmpty(message = "业务单据不能为空!") + @Valid + private List bizOrders; + + @Data + public static class BizOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据ID + */ + @ApiModelProperty(value = "业务单据ID", required = true) + @NotBlank(message = "业务单据ID不能为空!") + private String bizId; + + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型格式错误!", enumClass = LogisticsSheetDetailBizType.class) + private Integer bizType; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetSelectorVo.java new file mode 100644 index 0000000..565dfb4 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/LogisticsSheetSelectorVo.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.LogisticsSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class LogisticsSheetSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 物流单号 + */ + @ApiModelProperty("物流单号") + private String logisticsNo; + + /** + * 物流公司ID + */ + @ApiModelProperty("物流公司ID") + private String logisticsCompanyId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 发货人ID + */ + @ApiModelProperty("发货人ID") + private String deliveryBy; + + /** + * 发货起始时间 + */ + @ApiModelProperty("发货起始时间") + private LocalDateTime deliveryStartTime; + + /** + * 发货截止时间 + */ + @ApiModelProperty("发货截止时间") + private LocalDateTime deliveryEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = LogisticsSheetStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetBizOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetBizOrderVo.java new file mode 100644 index 0000000..80f90ce --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetBizOrderVo.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryLogisticsSheetBizOrderVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetVo.java new file mode 100644 index 0000000..083b33f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/QueryLogisticsSheetVo.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.LogisticsSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryLogisticsSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 物流单号 + */ + @ApiModelProperty("物流单号") + private String logisticsNo; + + /** + * 物流公司ID + */ + @ApiModelProperty("物流公司ID") + private String logisticsCompanyId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 发货人ID + */ + @ApiModelProperty("发货人ID") + private String deliveryBy; + + /** + * 发货起始时间 + */ + @ApiModelProperty("发货起始时间") + private LocalDateTime deliveryStartTime; + + /** + * 发货截止时间 + */ + @ApiModelProperty("发货截止时间") + private LocalDateTime deliveryEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = LogisticsSheetStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/UpdateLogisticsSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/UpdateLogisticsSheetVo.java new file mode 100644 index 0000000..8ad4631 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/logistics/UpdateLogisticsSheetVo.java @@ -0,0 +1,19 @@ +package com.lframework.xingyun.sc.vo.logistics; + +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateLogisticsSheetVo extends CreateLogisticsSheetVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/paytype/OrderPayTypeVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/paytype/OrderPayTypeVo.java new file mode 100644 index 0000000..b806a87 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/paytype/OrderPayTypeVo.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.sc.vo.paytype; + +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class OrderPayTypeVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 支付金额 + */ + @ApiModelProperty("支付金额") + @NotNull(message = "支付金额不能为空!") + private BigDecimal payAmount; + + /** + * 支付内容 + */ + @ApiModelProperty("支付内容") + private String text; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApprovePassPurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApprovePassPurchaseOrderVo.java new file mode 100644 index 0000000..da20469 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApprovePassPurchaseOrderVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassPurchaseOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotBlank(message = "订单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApproveRefusePurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApproveRefusePurchaseOrderVo.java new file mode 100644 index 0000000..870ae59 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/ApproveRefusePurchaseOrderVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefusePurchaseOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotBlank(message = "订单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApprovePassPurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApprovePassPurchaseOrderVo.java new file mode 100644 index 0000000..d98babc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApprovePassPurchaseOrderVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassPurchaseOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotEmpty(message = "订单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApproveRefusePurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApproveRefusePurchaseOrderVo.java new file mode 100644 index 0000000..08994be --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/BatchApproveRefusePurchaseOrderVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefusePurchaseOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotEmpty(message = "订单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/CreatePurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/CreatePurchaseOrderVo.java new file mode 100644 index 0000000..23493b2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/CreatePurchaseOrderVo.java @@ -0,0 +1,111 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreatePurchaseOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotBlank(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 预计到货日期 + */ + @ApiModelProperty(value = "预计到货日期", required = true) + @NotNull(message = "预计到货日期不能为空!") + private LocalDate expectArriveDate; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 支付方式 + */ + @ApiModelProperty("约定支付") + @Valid + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (PurchaseProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getPurchaseNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品采购数量不能为空!"); + } + + if (product.getPurchaseNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品采购数量必须大于0!"); + } + + if (product.getPurchasePrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品采购价不能为空!"); + } + + if (product.getPurchasePrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品采购价不允许小于0!"); + } + + orderNo++; + } + + BigDecimal totalAmount = this.products.stream() + .map(t -> NumberUtil.mul(t.getPurchaseNum(), t.getPurchasePrice())).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + BigDecimal payTypeAmount = CollectionUtil.isEmpty(this.payTypes) ? BigDecimal.ZERO + : this.payTypes.stream().map(OrderPayTypeVo::getPayAmount).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(totalAmount, payTypeAmount)) { + throw new InputErrorException("所有支付方式的支付金额不等于含税总金额,请检查!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseOrderSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseOrderSelectorVo.java new file mode 100644 index 0000000..3912ec9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseOrderSelectorVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class PurchaseOrderSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = PurchaseOrderStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseProductVo.java new file mode 100644 index 0000000..f3e554e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/PurchaseProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class PurchaseProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 采购数量 + */ + @ApiModelProperty("采购数量") + private Integer purchaseNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderVo.java new file mode 100644 index 0000000..3bb5787 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderVo.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.PurchaseOrderStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPurchaseOrderVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = PurchaseOrderStatus.class) + private Integer status; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderWithReceiveVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderWithReceiveVo.java new file mode 100644 index 0000000..c8348da --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseOrderWithReceiveVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPurchaseOrderWithReceiveVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseProductVo.java new file mode 100644 index 0000000..2bc96c6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/QueryPurchaseProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryPurchaseProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/UpdatePurchaseOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/UpdatePurchaseOrderVo.java new file mode 100644 index 0000000..223beac --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/UpdatePurchaseOrderVo.java @@ -0,0 +1,19 @@ +package com.lframework.xingyun.sc.vo.purchase; + +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdatePurchaseOrderVo extends CreatePurchaseOrderVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotBlank(message = "订单ID不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/config/UpdatePurchaseConfigVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/config/UpdatePurchaseConfigVo.java new file mode 100644 index 0000000..e64fa1a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/config/UpdatePurchaseConfigVo.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.sc.vo.purchase.config; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdatePurchaseConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 采购收货单是否关联采购订单 + */ + @ApiModelProperty(value = "采购收货单是否关联采购订单", required = true) + @NotNull(message = "采购收货单是否关联采购订单不能为空!") + private Boolean receiveRequirePurchase; + + /** + * 采购收货单是否多次关联采购订单 + */ + @ApiModelProperty(value = "采购收货单是否多次关联采购订单", required = true) + @NotNull(message = "采购收货单是否多次关联采购订单不能为空!") + private Boolean receiveMultipleRelatePurchase; + + /** + * 采购退货单是否关联采购收货单 + */ + @ApiModelProperty(value = "采购退货单是否关联采购收货单", required = true) + @NotNull(message = "采购退货单是否关联采购收货单不能为空!") + private Boolean purchaseReturnRequireReceive; + + /** + * 采购退货单是否多次关联采购收货单 + */ + @ApiModelProperty(value = "采购退货单是否多次关联采购收货单", required = true) + @NotNull(message = "采购退货单是否多次关联采购收货单不能为空!") + private Boolean purchaseReturnMultipleRelateReceive; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApprovePassReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApprovePassReceiveSheetVo.java new file mode 100644 index 0000000..f63af93 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApprovePassReceiveSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassReceiveSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 收货单ID + */ + @ApiModelProperty(value = "收货单ID", required = true) + @NotBlank(message = "收货单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApproveRefuseReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApproveRefuseReceiveSheetVo.java new file mode 100644 index 0000000..197197c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ApproveRefuseReceiveSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseReceiveSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 收货单ID + */ + @ApiModelProperty(value = "收货单ID", required = true) + @NotBlank(message = "收货单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApprovePassReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApprovePassReceiveSheetVo.java new file mode 100644 index 0000000..ed17eb0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApprovePassReceiveSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassReceiveSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 收货单ID + */ + @ApiModelProperty(value = "收货单ID", required = true) + @NotEmpty(message = "收货单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApproveRefuseReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApproveRefuseReceiveSheetVo.java new file mode 100644 index 0000000..7a2e62d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/BatchApproveRefuseReceiveSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseReceiveSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 收货单ID + */ + @ApiModelProperty(value = "收货单ID", required = true) + @NotEmpty(message = "收货单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/CreateReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/CreateReceiveSheetVo.java new file mode 100644 index 0000000..a137b37 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/CreateReceiveSheetVo.java @@ -0,0 +1,168 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.entity.PurchaseOrderDetail; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.service.purchase.PurchaseOrderDetailService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateReceiveSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotBlank(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private LocalDate paymentDate; + + /** + * 是否允许修改付款日期 + */ + @ApiModelProperty("是否允许修改付款日期") + private Boolean allowModifyPaymentDate = Boolean.FALSE; + + /** + * 到货日期 + */ + @ApiModelProperty(value = "到货日期", required = true) + @NotNull(message = "到货日期不能为空!") + private LocalDate receiveDate; + + /** + * 采购订单ID + */ + @ApiModelProperty("采购订单ID") + private String purchaseOrderId; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否关联采购订单 + */ + @ApiModelProperty("是否关联采购订单") + private Boolean required; + + public void validate() { + + PurchaseConfigService purchaseConfigService = ApplicationUtil.getBean( + PurchaseConfigService.class); + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + if (!purchaseConfig.getReceiveRequirePurchase().equals(this.required)) { + throw new DefaultClientException("系统参数发生改变,请刷新页面后重试!"); + } + + this.validate(purchaseConfig.getReceiveRequirePurchase()); + } + + protected void validate(boolean requirePurchase) { + + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + GetPaymentDateDto paymentDate = receiveSheetService.getPaymentDate(this.supplierId); + if (paymentDate.getAllowModify()) { + if (this.getPaymentDate() == null) { + throw new InputErrorException("付款日期不能为空!"); + } + } + + if (requirePurchase) { + if (StringUtil.isBlank(this.getPurchaseOrderId())) { + throw new InputErrorException("采购订单不能为空!"); + } + } + + PurchaseOrderDetailService purchaseOrderDetailService = ApplicationUtil.getBean( + PurchaseOrderDetailService.class); + + int orderNo = 1; + for (ReceiveProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getReceiveNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品收货数量不能为空!"); + } + + if (product.getReceiveNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品收货数量必须大于0!"); + } + + if (!requirePurchase) { + if (product.getPurchasePrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品采购价不能为空!"); + } + + if (product.getPurchasePrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品采购价不允许小于0!"); + } + + if (!NumberUtil.isNumberPrecision(product.getPurchasePrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品采购价最多允许2位小数!"); + } + } else { + if (StringUtil.isNotBlank(product.getPurchaseOrderDetailId())) { + PurchaseOrderDetail orderDetail = purchaseOrderDetailService.getById( + product.getPurchaseOrderDetailId()); + product.setPurchasePrice(orderDetail.getTaxPrice()); + } else { + product.setPurchasePrice(BigDecimal.ZERO); + } + } + + orderNo++; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetVo.java new file mode 100644 index 0000000..33d4e47 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetVo.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryReceiveSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = ReceiveSheetStatus.class) + private Integer status; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购订单号 + */ + @ApiModelProperty("采购订单号") + private String purchaseOrderCode; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetWithReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetWithReturnVo.java new file mode 100644 index 0000000..03490a5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/QueryReceiveSheetWithReturnVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryReceiveSheetWithReturnVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveProductVo.java new file mode 100644 index 0000000..ad5072a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveProductVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class ReceiveProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 收货数量 + */ + @ApiModelProperty("收货数量") + private Integer receiveNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 采购订单明细ID + */ + @ApiModelProperty("采购订单明细ID") + private String purchaseOrderDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveSheetSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveSheetSelectorVo.java new file mode 100644 index 0000000..123a315 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/ReceiveSheetSelectorVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.ReceiveSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class ReceiveSheetSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = ReceiveSheetStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/UpdateReceiveSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/UpdateReceiveSheetVo.java new file mode 100644 index 0000000..4b7a651 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/receive/UpdateReceiveSheetVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.vo.purchase.receive; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateReceiveSheetVo extends CreateReceiveSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * 收货单ID + */ + @ApiModelProperty(value = "收货单ID", required = true) + @NotBlank(message = "收货单ID不能为空!") + private String id; + + @Override + public void validate() { + + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + ReceiveSheet receiveSheet = receiveSheetService.getById(this.getId()); + + this.validate(!StringUtil.isBlank(receiveSheet.getPurchaseOrderId())); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApprovePassPurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApprovePassPurchaseReturnVo.java new file mode 100644 index 0000000..e088109 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApprovePassPurchaseReturnVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassPurchaseReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退货单ID + */ + @ApiModelProperty(value = "退货单ID", required = true) + @NotBlank(message = "退货单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApproveRefusePurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApproveRefusePurchaseReturnVo.java new file mode 100644 index 0000000..1882843 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ApproveRefusePurchaseReturnVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefusePurchaseReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退货单ID + */ + @ApiModelProperty(value = "退货单ID", required = true) + @NotBlank(message = "退货单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApprovePassPurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApprovePassPurchaseReturnVo.java new file mode 100644 index 0000000..8c44cf9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApprovePassPurchaseReturnVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassPurchaseReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退货单ID + */ + @ApiModelProperty(value = "退货单ID", required = true) + @NotEmpty(message = "退货单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApproveRefusePurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApproveRefusePurchaseReturnVo.java new file mode 100644 index 0000000..fc0837a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/BatchApproveRefusePurchaseReturnVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefusePurchaseReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退货单ID + */ + @ApiModelProperty(value = "退货单ID", required = true) + @NotEmpty(message = "退货单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/CreatePurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/CreatePurchaseReturnVo.java new file mode 100644 index 0000000..f647c76 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/CreatePurchaseReturnVo.java @@ -0,0 +1,162 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.entity.PurchaseConfig; +import com.lframework.xingyun.sc.entity.ReceiveSheetDetail; +import com.lframework.xingyun.sc.service.purchase.PurchaseConfigService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetDetailService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreatePurchaseReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotBlank(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private LocalDate paymentDate; + + /** + * 收货单ID + */ + @ApiModelProperty("收货单ID") + private String receiveSheetId; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + @Valid + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否关联采购收货单 + */ + @ApiModelProperty("是否关联采购收货单") + private Boolean required; + + public void validate() { + + PurchaseConfigService purchaseConfigService = ApplicationUtil.getBean( + PurchaseConfigService.class); + PurchaseConfig purchaseConfig = purchaseConfigService.get(); + + if (!purchaseConfig.getPurchaseReturnRequireReceive().equals(this.required)) { + throw new DefaultClientException("系统参数发生改变,请刷新页面后重试!"); + } + + this.validate(purchaseConfig.getPurchaseReturnRequireReceive()); + } + + protected void validate(boolean requireReceive) { + + ReceiveSheetService receiveSheetService = ApplicationUtil.getBean(ReceiveSheetService.class); + GetPaymentDateDto paymentDate = receiveSheetService.getPaymentDate(this.supplierId); + if (paymentDate.getAllowModify()) { + if (this.getPaymentDate() == null) { + throw new InputErrorException("付款日期不能为空!"); + } + } + + if (requireReceive) { + if (StringUtil.isBlank(this.getReceiveSheetId())) { + throw new InputErrorException("采购收货单不能为空!"); + } + } + + ReceiveSheetDetailService receiveSheetDetailService = ApplicationUtil.getBean( + ReceiveSheetDetailService.class); + + int orderNo = 1; + for (ReturnProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getReturnNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品退货数量不能为空!"); + } + + if (product.getReturnNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品退货数量必须大于0!"); + } + + if (!requireReceive) { + if (product.getPurchasePrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品采购价不能为空!"); + } + + if (product.getPurchasePrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品采购价不允许小于0!"); + } + + if (!NumberUtil.isNumberPrecision(product.getPurchasePrice(), 2)) { + throw new InputErrorException("第" + orderNo + "行商品采购价最多允许2位小数!"); + } + } else { + if (StringUtil.isNotBlank(product.getReceiveSheetDetailId())) { + ReceiveSheetDetail detail = receiveSheetDetailService.getById( + product.getReceiveSheetDetailId()); + product.setPurchasePrice(detail.getTaxPrice()); + } else { + product.setPurchasePrice(BigDecimal.ZERO); + } + } + + orderNo++; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/QueryPurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/QueryPurchaseReturnVo.java new file mode 100644 index 0000000..1fa0b04 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/QueryPurchaseReturnVo.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.PurchaseReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPurchaseReturnVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = PurchaseReturnStatus.class) + private Integer status; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String purchaserId; + + /** + * 采购订单号 + */ + @ApiModelProperty("采购订单号") + private String receiveSheetCode; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ReturnProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ReturnProductVo.java new file mode 100644 index 0000000..ca3b35f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/ReturnProductVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class ReturnProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 采购价 + */ + @ApiModelProperty("采购价") + private BigDecimal purchasePrice; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 收货单明细ID + */ + @ApiModelProperty("收货单明细ID") + private String receiveSheetDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/UpdatePurchaseReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/UpdatePurchaseReturnVo.java new file mode 100644 index 0000000..ba96ac6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/purchase/returned/UpdatePurchaseReturnVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.sc.vo.purchase.returned; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.service.purchase.PurchaseReturnService; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdatePurchaseReturnVo extends CreatePurchaseReturnVo { + + private static final long serialVersionUID = 1L; + + /** + * 退货单ID + */ + @ApiModelProperty(value = "退货单ID", required = true) + @NotBlank(message = "退货单ID不能为空!") + private String id; + + @Override + public void validate() { + + PurchaseReturnService purchaseReturnService = ApplicationUtil.getBean( + PurchaseReturnService.class); + PurchaseReturn purchaseReturn = purchaseReturnService.getById(this.getId()); + + this.validate(!StringUtil.isBlank(purchaseReturn.getReceiveSheetId())); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/config/UpdateRetailConfigVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/config/UpdateRetailConfigVo.java new file mode 100644 index 0000000..ec3c63b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/config/UpdateRetailConfigVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.retail.config; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateRetailConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 零售出库单上的会员是否必填 + */ + @ApiModelProperty(value = "零售出库单上的会员是否必填", required = true) + @NotNull(message = "零售出库单上的会员是否必填不能为空!") + private Boolean retailOutSheetRequireMember; + + /** + * 零售退货单是否关联零售出库单 + */ + @ApiModelProperty(value = "零售退货单是否关联零售出库单", required = true) + @NotNull(message = "零售退货单是否关联零售出库单不能为空!") + private Boolean retailReturnRequireOutStock; + + /** + * 零售退货单是否多次关联零售出库单 + */ + @ApiModelProperty(value = "零售退货单是否多次关联零售出库单", required = true) + @NotNull(message = "零售退货单是否多次关联零售出库单不能为空!") + private Boolean retailReturnMultipleRelateOutStock; + + /** + * 零售退货单上的会员是否必填 + */ + @ApiModelProperty(value = "零售退货单上的会员是否必填", required = true) + @NotNull(message = "零售退货单上的会员是否必填不能为空!") + private Boolean retailReturnRequireMember; + + /** + * 零售出库单是否需要发货 + */ + @ApiModelProperty(value = "零售出库单是否需要发货", required = true) + @NotNull(message = "零售出库单是否需要发货不能为空!") + private Boolean retailOutSheetRequireLogistics; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApprovePassRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApprovePassRetailOutSheetVo.java new file mode 100644 index 0000000..17fec3f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApprovePassRetailOutSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassRetailOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotBlank(message = "出库单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApproveRefuseRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApproveRefuseRetailOutSheetVo.java new file mode 100644 index 0000000..ce0aa88 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/ApproveRefuseRetailOutSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseRetailOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotBlank(message = "出库单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApprovePassRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApprovePassRetailOutSheetVo.java new file mode 100644 index 0000000..ab0094f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApprovePassRetailOutSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassRetailOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotEmpty(message = "出库单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApproveRefuseRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApproveRefuseRetailOutSheetVo.java new file mode 100644 index 0000000..fdaee38 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/BatchApproveRefuseRetailOutSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseRetailOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotEmpty(message = "出库单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/CreateRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/CreateRetailOutSheetVo.java new file mode 100644 index 0000000..cb440cb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/CreateRetailOutSheetVo.java @@ -0,0 +1,151 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.entity.RetailConfig; +import com.lframework.xingyun.sc.service.retail.RetailConfigService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateRetailOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 会员ID + */ + @ApiModelProperty(value = "会员ID") + private String memberId; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private LocalDate paymentDate; + + /** + * 是否允许修改付款日期 + */ + @ApiModelProperty("是否允许修改付款日期") + private Boolean allowModifyPaymentDate = Boolean.FALSE; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + @Valid + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + RetailConfigService retailConfigService = ApplicationUtil.getBean(RetailConfigService.class); + RetailConfig config = retailConfigService.get(); + if (config.getRetailOutSheetRequireMember()) { + if (StringUtil.isBlank(this.memberId)) { + throw new DefaultClientException("请选择会员!"); + } + } + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + GetPaymentDateDto paymentDate = retailOutSheetService.getPaymentDate(this.getMemberId()); + if (paymentDate.getAllowModify()) { + if (this.getPaymentDate() == null) { + throw new InputErrorException("付款日期不能为空!"); + } + } + + int orderNo = 1; + for (RetailOutProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getOrderNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品零售数量不能为空!"); + } + + if (product.getOrderNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品零售数量必须大于0!"); + } + + if (product.getOriPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品参考零售价不能为空!"); + } + + if (product.getTaxPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品价格不能为空!"); + } + + if (product.getTaxPrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品价格不允许小于0!"); + } + + if (!NumberUtil.equal(product.getOriPrice(), 0D)) { + // 由 根据原价和折扣率校验现价 更改为 根据原价、现价计算折扣率,即:不以传入的折扣率为准 + BigDecimal discountRate = NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.div(product.getTaxPrice(), product.getOriPrice()), 100), 2); + product.setDiscountRate(discountRate); + } else { + //如果原价为0,折扣率固定为100 + product.setDiscountRate(BigDecimal.valueOf(100)); + } + + orderNo++; + } + + BigDecimal totalAmount = this.products.stream() + .map(t -> NumberUtil.mul(t.getOrderNum(), t.getTaxPrice())).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + BigDecimal payTypeAmount = CollectionUtil.isEmpty(this.payTypes) ? BigDecimal.ZERO + : this.payTypes.stream().map(OrderPayTypeVo::getPayAmount).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(totalAmount, payTypeAmount)) { + throw new InputErrorException("所有支付方式的支付金额不等于含税总金额,请检查!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetVo.java new file mode 100644 index 0000000..21e24df --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetVo.java @@ -0,0 +1,89 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.RetailOutSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryRetailOutSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = RetailOutSheetStatus.class) + private Integer status; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetWithReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetWithReturnVo.java new file mode 100644 index 0000000..2e60ba0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailOutSheetWithReturnVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryRetailOutSheetWithReturnVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailProductVo.java new file mode 100644 index 0000000..a632d34 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/QueryRetailProductVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryRetailProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 是否退货 + */ + @ApiModelProperty("是否退货") + private Boolean isReturn = Boolean.FALSE; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutProductVo.java new file mode 100644 index 0000000..ad003a5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutProductVo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class RetailOutProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal oriPrice; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + @ApiModelProperty("折扣(%)") + private BigDecimal discountRate; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer orderNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutSheetSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutSheetSelectorVo.java new file mode 100644 index 0000000..54db747 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/RetailOutSheetSelectorVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.RetailOutSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class RetailOutSheetSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = RetailOutSheetStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/UpdateRetailOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/UpdateRetailOutSheetVo.java new file mode 100644 index 0000000..a7cb637 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/out/UpdateRetailOutSheetVo.java @@ -0,0 +1,20 @@ +package com.lframework.xingyun.sc.vo.retail.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateRetailOutSheetVo extends CreateRetailOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotBlank(message = "出库单ID不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApprovePassRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApprovePassRetailReturnVo.java new file mode 100644 index 0000000..140a60a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApprovePassRetailReturnVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassRetailReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotBlank(message = "退单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApproveRefuseRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApproveRefuseRetailReturnVo.java new file mode 100644 index 0000000..0128b54 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/ApproveRefuseRetailReturnVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseRetailReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotBlank(message = "退单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApprovePassRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApprovePassRetailReturnVo.java new file mode 100644 index 0000000..274c6d5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApprovePassRetailReturnVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassRetailReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotEmpty(message = "退单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApproveRefuseRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApproveRefuseRetailReturnVo.java new file mode 100644 index 0000000..440c947 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/BatchApproveRefuseRetailReturnVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseRetailReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotEmpty(message = "退单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/CreateRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/CreateRetailReturnVo.java new file mode 100644 index 0000000..652929e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/CreateRetailReturnVo.java @@ -0,0 +1,200 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.dto.retail.out.RetailOutSheetDetailLotDto; +import com.lframework.xingyun.sc.entity.RetailConfig; +import com.lframework.xingyun.sc.entity.RetailOutSheetDetail; +import com.lframework.xingyun.sc.service.retail.RetailConfigService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetDetailService; +import com.lframework.xingyun.sc.service.retail.RetailOutSheetService; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateRetailReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String salerId; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private LocalDate paymentDate; + + /** + * 是否允许修改付款日期 + */ + @ApiModelProperty("是否允许修改付款日期") + private Boolean allowModifyPaymentDate = Boolean.FALSE; + + /** + * 收货单ID + */ + @ApiModelProperty("收货单ID") + private String outSheetId; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 支付方式 + */ + @ApiModelProperty("支付方式") + @Valid + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否关联零售出库单 + */ + @ApiModelProperty("是否关联零售出库单") + private Boolean required; + + public void validate() { + + RetailConfigService retailConfigService = ApplicationUtil.getBean(RetailConfigService.class); + RetailConfig retailConfig = retailConfigService.get(); + + if (retailConfig.getRetailReturnRequireMember()) { + if (StringUtil.isBlank(this.memberId)) { + throw new DefaultClientException("请选择会员!"); + } + } + + if (!retailConfig.getRetailReturnRequireOutStock().equals(this.required)) { + throw new DefaultClientException("系统参数发生改变,请刷新页面后重试!"); + } + + this.validate(retailConfig.getRetailReturnRequireOutStock()); + } + + protected void validate(boolean requireOut) { + + RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean( + RetailOutSheetService.class); + GetPaymentDateDto paymentDate = retailOutSheetService.getPaymentDate(this.getMemberId()); + if (paymentDate.getAllowModify()) { + if (this.getPaymentDate() == null) { + throw new InputErrorException("付款日期不能为空!"); + } + } + + if (requireOut) { + if (StringUtil.isBlank(this.getOutSheetId())) { + throw new InputErrorException("零售出库单不能为空!"); + } + } + + RetailOutSheetDetailService retailOutSheetDetailService = ApplicationUtil.getBean( + RetailOutSheetDetailService.class); + RetailOutSheetDetailLotService retailOutSheetDetailLotService = ApplicationUtil.getBean( + RetailOutSheetDetailLotService.class); + int orderNo = 1; + for (RetailReturnProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getReturnNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品退货数量不能为空!"); + } + + if (product.getReturnNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品退货数量必须大于0!"); + } + + if (!requireOut) { + + if (product.getOriPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品参考零售价不能为空!"); + } + + if (product.getTaxPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品价格不能为空!"); + } + + if (product.getTaxPrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品价格不允许小于0!"); + } + + if (!NumberUtil.equal(product.getOriPrice(), 0D)) { + // 由 根据原价和折扣率校验现价 更改为 根据原价、现价计算折扣率,即:不以传入的折扣率为准 + BigDecimal discountRate = NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.div(product.getTaxPrice(), product.getOriPrice()), 100), 2); + product.setDiscountRate(discountRate); + } else { + //如果原价为0,折扣率固定为100 + product.setDiscountRate(BigDecimal.valueOf(100)); + } + } else { + if (StringUtil.isNotBlank(product.getOutSheetDetailId())) { + RetailOutSheetDetailLotDto detailLot = retailOutSheetDetailLotService.findById( + product.getOutSheetDetailId()); + RetailOutSheetDetail detail = retailOutSheetDetailService.getById( + detailLot.getDetailId()); + product.setTaxPrice(detail.getTaxPrice()); + } else { + product.setTaxPrice(BigDecimal.ZERO); + } + } + + orderNo++; + } + + BigDecimal totalAmount = this.products.stream() + .map(t -> NumberUtil.mul(t.getReturnNum(), t.getTaxPrice())).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + BigDecimal payTypeAmount = CollectionUtil.isEmpty(this.payTypes) ? BigDecimal.ZERO + : this.payTypes.stream().map(OrderPayTypeVo::getPayAmount).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(totalAmount, payTypeAmount)) { + throw new InputErrorException("所有支付方式的支付金额不等于含税总金额,请检查!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/QueryRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/QueryRetailReturnVo.java new file mode 100644 index 0000000..29e966a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/QueryRetailReturnVo.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.RetailReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryRetailReturnVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 会员ID + */ + @ApiModelProperty("会员ID") + private String memberId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = RetailReturnStatus.class) + private Integer status; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 出库单号 + */ + @ApiModelProperty("出库单号") + private String outSheetCode; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/RetailReturnProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/RetailReturnProductVo.java new file mode 100644 index 0000000..9e14e14 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/RetailReturnProductVo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class RetailReturnProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal oriPrice; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + @ApiModelProperty("折扣(%)") + private BigDecimal discountRate; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 出库单明细ID + */ + @ApiModelProperty("出库单明细ID") + private String outSheetDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/UpdateRetailReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/UpdateRetailReturnVo.java new file mode 100644 index 0000000..281835c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/retail/returned/UpdateRetailReturnVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.vo.retail.returned; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.entity.RetailReturn; +import com.lframework.xingyun.sc.service.retail.RetailReturnService; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateRetailReturnVo extends CreateRetailReturnVo { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotBlank(message = "退单ID不能为空!") + private String id; + + @Override + public void validate() { + + RetailReturnService saleReturnService = ApplicationUtil.getBean(RetailReturnService.class); + RetailReturn saleReturn = saleReturnService.getById(this.getId()); + + this.validate(!StringUtil.isBlank(saleReturn.getOutSheetId())); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApprovePassSaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApprovePassSaleOrderVo.java new file mode 100644 index 0000000..f7c6b63 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApprovePassSaleOrderVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassSaleOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotBlank(message = "订单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApproveRefuseSaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApproveRefuseSaleOrderVo.java new file mode 100644 index 0000000..25fe187 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/ApproveRefuseSaleOrderVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSaleOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotBlank(message = "订单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApprovePassSaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApprovePassSaleOrderVo.java new file mode 100644 index 0000000..513a197 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApprovePassSaleOrderVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassSaleOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotEmpty(message = "订单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApproveRefuseSaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApproveRefuseSaleOrderVo.java new file mode 100644 index 0000000..1bb758a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/BatchApproveRefuseSaleOrderVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseSaleOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotEmpty(message = "订单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/CreateSaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/CreateSaleOrderVo.java new file mode 100644 index 0000000..870bed1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/CreateSaleOrderVo.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.vo.paytype.OrderPayTypeVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateSaleOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotBlank(message = "客户ID不能为空!") + private String customerId; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 支付方式 + */ + @ApiModelProperty("约定支付") + @Valid + private List payTypes; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (SaleProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getOrderNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品销售数量不能为空!"); + } + + if (product.getOrderNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品销售数量必须大于0!"); + } + + if (product.getOriPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品参考销售价不能为空!"); + } + + if (product.getTaxPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品价格不能为空!"); + } + + if (product.getTaxPrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品价格不允许小于0!"); + } + + if (!NumberUtil.equal(product.getOriPrice(), 0D)) { + // 由 根据原价和折扣率校验现价 更改为 根据原价、现价计算折扣率,即:不以传入的折扣率为准 + BigDecimal discountRate = NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.div(product.getTaxPrice(), product.getOriPrice()), 100), 2); + product.setDiscountRate(discountRate); + } else { + //如果原价为0,折扣率固定为100 + product.setDiscountRate(BigDecimal.valueOf(100)); + } + + orderNo++; + } + + BigDecimal totalAmount = this.products.stream() + .map(t -> NumberUtil.mul(t.getOrderNum(), t.getTaxPrice())).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + BigDecimal payTypeAmount = CollectionUtil.isEmpty(this.payTypes) ? BigDecimal.ZERO + : this.payTypes.stream().map(OrderPayTypeVo::getPayAmount).reduce(NumberUtil::add) + .orElse(BigDecimal.ZERO); + if (!NumberUtil.equal(totalAmount, payTypeAmount)) { + throw new InputErrorException("所有支付方式的支付金额不等于含税总金额,请检查!"); + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderVo.java new file mode 100644 index 0000000..5586549 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderVo.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.SaleOrderStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOrderVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = SaleOrderStatus.class) + private Integer status; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderWithOutVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderWithOutVo.java new file mode 100644 index 0000000..7e5cde9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleOrderWithOutVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOrderWithOutVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleProductVo.java new file mode 100644 index 0000000..75904b2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/QuerySaleProductVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QuerySaleProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 是否退货 + */ + @ApiModelProperty("是否退货") + private Boolean isReturn = Boolean.FALSE; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleOrderSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleOrderSelectorVo.java new file mode 100644 index 0000000..d18441c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleOrderSelectorVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.SaleOrderStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class SaleOrderSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = SaleOrderStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleProductVo.java new file mode 100644 index 0000000..d6a16f0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/SaleProductVo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.sc.vo.sale; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SaleProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal oriPrice; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + @ApiModelProperty("折扣(%)") + private BigDecimal discountRate; + + /** + * 销售数量 + */ + @ApiModelProperty("销售数量") + private Integer orderNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/UpdateSaleOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/UpdateSaleOrderVo.java new file mode 100644 index 0000000..5dcba8f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/UpdateSaleOrderVo.java @@ -0,0 +1,19 @@ +package com.lframework.xingyun.sc.vo.sale; + +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateSaleOrderVo extends CreateSaleOrderVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", required = true) + @NotBlank(message = "订单ID不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/config/UpdateSaleConfigVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/config/UpdateSaleConfigVo.java new file mode 100644 index 0000000..a5cbebf --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/config/UpdateSaleConfigVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.sale.config; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSaleConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 销售出库单是否关联销售订单 + */ + @ApiModelProperty(value = "销售出库单是否关联销售订单", required = true) + @NotNull(message = "销售出库单是否关联销售订单不能为空!") + private Boolean outStockRequireSale; + + /** + * 销售出库单是否多次关联销售订单 + */ + @ApiModelProperty(value = "销售出库单是否多次关联销售订单", required = true) + @NotNull(message = "销售出库单是否多次关联销售订单不能为空!") + private Boolean outStockMultipleRelateSale; + + /** + * 销售退货单是否关联销售出库单 + */ + @ApiModelProperty(value = "销售退货单是否关联销售出库单", required = true) + @NotNull(message = "销售退货单是否关联销售出库单不能为空!") + private Boolean saleReturnRequireOutStock; + + /** + * 销售退货单是否多次关联销售出库单 + */ + @ApiModelProperty(value = "销售退货单是否多次关联销售出库单", required = true) + @NotNull(message = "销售退货单是否多次关联销售出库单不能为空!") + private Boolean saleReturnMultipleRelateOutStock; + + /** + * 销售出库单是否关联物流单 + */ + @ApiModelProperty(value = "销售出库单是否关联物流单", required = true) + @NotNull(message = "销售出库单是否关联物流单不能为空!") + private Boolean outStockRequireLogistics; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApprovePassSaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApprovePassSaleOutSheetVo.java new file mode 100644 index 0000000..7d597e5 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApprovePassSaleOutSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassSaleOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotBlank(message = "出库单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApproveRefuseSaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApproveRefuseSaleOutSheetVo.java new file mode 100644 index 0000000..067cff8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/ApproveRefuseSaleOutSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSaleOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotBlank(message = "出库单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApprovePassSaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApprovePassSaleOutSheetVo.java new file mode 100644 index 0000000..b9403a8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApprovePassSaleOutSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassSaleOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotEmpty(message = "出库单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApproveRefuseSaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApproveRefuseSaleOutSheetVo.java new file mode 100644 index 0000000..055e4fd --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/BatchApproveRefuseSaleOutSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseSaleOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotEmpty(message = "出库单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/CreateSaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/CreateSaleOutSheetVo.java new file mode 100644 index 0000000..ed49b25 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/CreateSaleOutSheetVo.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.entity.SaleOrderDetail; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.service.sale.SaleOrderDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateSaleOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotBlank(message = "客户ID不能为空!") + private String customerId; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private LocalDate paymentDate; + + /** + * 是否允许修改付款日期 + */ + @ApiModelProperty("是否允许修改付款日期") + private Boolean allowModifyPaymentDate = Boolean.FALSE; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 销售订单ID + */ + @ApiModelProperty("销售订单ID") + private String saleOrderId; + + /** + * 是否关联销售订单 + */ + @ApiModelProperty("是否关联销售订单") + private Boolean required; + + public void validate() { + + SaleConfigService saleConfigService = ApplicationUtil.getBean(SaleConfigService.class); + SaleConfig saleConfig = saleConfigService.get(); + + if (!saleConfig.getOutStockRequireSale().equals(this.required)) { + throw new DefaultClientException("系统参数发生改变,请刷新页面后重试!"); + } + + this.validate(saleConfig.getOutStockRequireSale()); + } + + protected void validate(boolean requireSale) { + + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + GetPaymentDateDto paymentDate = saleOutSheetService.getPaymentDate(this.getCustomerId()); + if (paymentDate.getAllowModify()) { + if (this.getPaymentDate() == null) { + throw new InputErrorException("付款日期不能为空!"); + } + } + + if (requireSale) { + if (StringUtil.isBlank(this.getSaleOrderId())) { + throw new InputErrorException("销售订单不能为空!"); + } + } + + SaleOrderDetailService saleOrderDetailService = ApplicationUtil.getBean( + SaleOrderDetailService.class); + + int orderNo = 1; + for (SaleOutProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getOrderNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品销售数量不能为空!"); + } + + if (product.getOrderNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品销售数量必须大于0!"); + } + + if (!requireSale) { + + if (product.getOriPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品参考销售价不能为空!"); + } + + if (product.getTaxPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品价格不能为空!"); + } + + if (product.getTaxPrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品价格不允许小于0!"); + } + + if (!NumberUtil.equal(product.getOriPrice(), 0D)) { + // 由 根据原价和折扣率校验现价 更改为 根据原价、现价计算折扣率,即:不以传入的折扣率为准 + BigDecimal discountRate = NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.div(product.getTaxPrice(), product.getOriPrice()), 100), 2); + product.setDiscountRate(discountRate); + } else { + //如果原价为0,折扣率固定为100 + product.setDiscountRate(BigDecimal.valueOf(100)); + } + } else { + if (StringUtil.isNotBlank(product.getSaleOrderDetailId())) { + SaleOrderDetail orderDetail = saleOrderDetailService.getById( + product.getSaleOrderDetailId()); + product.setTaxPrice(orderDetail.getTaxPrice()); + } else { + product.setTaxPrice(BigDecimal.ZERO); + } + } + + orderNo++; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetVo.java new file mode 100644 index 0000000..9694d4d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetVo.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.SaleOutSheetStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOutSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = SaleOutSheetStatus.class) + private Integer status; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 销售订单号 + */ + @ApiModelProperty("销售订单号") + private String saleOrderCode; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetWithReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetWithReturnVo.java new file mode 100644 index 0000000..350d546 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/QuerySaleOutSheetWithReturnVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleOutSheetWithReturnVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutProductVo.java new file mode 100644 index 0000000..5397041 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutProductVo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SaleOutProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal oriPrice; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + @ApiModelProperty("折扣(%)") + private BigDecimal discountRate; + + /** + * 出库数量 + */ + @ApiModelProperty("出库数量") + private Integer orderNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 销售订单明细ID + */ + @ApiModelProperty("销售订单明细ID") + private String saleOrderDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutSheetSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutSheetSelectorVo.java new file mode 100644 index 0000000..696e71b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/SaleOutSheetSelectorVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.SaleOutSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class SaleOutSheetSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = SaleOutSheetStatus.class) + private Integer status; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/UpdateSaleOutSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/UpdateSaleOutSheetVo.java new file mode 100644 index 0000000..0c9dad6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/out/UpdateSaleOutSheetVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.sc.vo.sale.out; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateSaleOutSheetVo extends CreateSaleOutSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 出库单ID + */ + @ApiModelProperty(value = "出库单ID", required = true) + @NotBlank(message = "出库单ID不能为空!") + private String id; + + @Override + public void validate() { + + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + SaleOutSheet saleOutSheet = saleOutSheetService.getById(this.getId()); + + this.validate(!StringUtil.isBlank(saleOutSheet.getSaleOrderId())); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApprovePassSaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApprovePassSaleReturnVo.java new file mode 100644 index 0000000..924d3ed --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApprovePassSaleReturnVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassSaleReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotBlank(message = "退单ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApproveRefuseSaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApproveRefuseSaleReturnVo.java new file mode 100644 index 0000000..42d75ea --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/ApproveRefuseSaleReturnVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSaleReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotBlank(message = "退单ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApprovePassSaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApprovePassSaleReturnVo.java new file mode 100644 index 0000000..9634685 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApprovePassSaleReturnVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassSaleReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotEmpty(message = "退单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApproveRefuseSaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApproveRefuseSaleReturnVo.java new file mode 100644 index 0000000..b429ce3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/BatchApproveRefuseSaleReturnVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseSaleReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotEmpty(message = "退单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/CreateSaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/CreateSaleReturnVo.java new file mode 100644 index 0000000..748376d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/CreateSaleReturnVo.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.dto.purchase.receive.GetPaymentDateDto; +import com.lframework.xingyun.sc.entity.SaleConfig; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetail; +import com.lframework.xingyun.sc.entity.SaleOutSheetDetailLot; +import com.lframework.xingyun.sc.service.sale.SaleConfigService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailLotService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetDetailService; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateSaleReturnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotBlank(message = "客户ID不能为空!") + private String customerId; + + /** + * 采购员ID + */ + @ApiModelProperty("采购员ID") + private String salerId; + + /** + * 付款日期 + */ + @ApiModelProperty("付款日期") + private LocalDate paymentDate; + + /** + * 收货单ID + */ + @ApiModelProperty("收货单ID") + private String outSheetId; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品不能为空!") + private List products; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否关联销售出库单 + */ + @ApiModelProperty("是否关联销售出库单") + private Boolean required; + + public void validate() { + + SaleConfigService saleConfigService = ApplicationUtil.getBean(SaleConfigService.class); + SaleConfig saleConfig = saleConfigService.get(); + + if (!saleConfig.getSaleReturnRequireOutStock().equals(this.required)) { + throw new DefaultClientException("系统参数发生改变,请刷新页面后重试!"); + } + + this.validate(saleConfig.getSaleReturnRequireOutStock()); + } + + protected void validate(boolean requireOut) { + + SaleOutSheetService saleOutSheetService = ApplicationUtil.getBean(SaleOutSheetService.class); + GetPaymentDateDto paymentDate = saleOutSheetService.getPaymentDate(this.getCustomerId()); + if (paymentDate.getAllowModify()) { + if (this.getPaymentDate() == null) { + throw new InputErrorException("付款日期不能为空!"); + } + } + + if (requireOut) { + if (StringUtil.isBlank(this.getOutSheetId())) { + throw new InputErrorException("销售出库单不能为空!"); + } + } + + SaleOutSheetDetailService saleOutSheetDetailService = ApplicationUtil.getBean( + SaleOutSheetDetailService.class); + SaleOutSheetDetailLotService saleOutSheetDetailLotService = ApplicationUtil.getBean( + SaleOutSheetDetailLotService.class); + + int orderNo = 1; + for (SaleReturnProductVo product : this.products) { + + if (StringUtil.isBlank(product.getProductId())) { + throw new InputErrorException("第" + orderNo + "行商品不能为空!"); + } + + if (product.getReturnNum() == null) { + throw new InputErrorException("第" + orderNo + "行商品退货数量不能为空!"); + } + + if (product.getReturnNum() <= 0) { + throw new InputErrorException("第" + orderNo + "行商品退货数量必须大于0!"); + } + + if (!requireOut) { + if (product.getOriPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品参考销售价不能为空!"); + } + + if (product.getTaxPrice() == null) { + throw new InputErrorException("第" + orderNo + "行商品价格不能为空!"); + } + + if (product.getTaxPrice().doubleValue() < 0D) { + throw new InputErrorException("第" + orderNo + "行商品价格不允许小于0!"); + } + + if (!NumberUtil.equal(product.getOriPrice(), 0D)) { + // 由 根据原价和折扣率校验现价 更改为 根据原价、现价计算折扣率,即:不以传入的折扣率为准 + BigDecimal discountRate = NumberUtil.getNumber( + NumberUtil.mul(NumberUtil.div(product.getTaxPrice(), product.getOriPrice()), 100), 2); + product.setDiscountRate(discountRate); + } else { + //如果原价为0,折扣率固定为100 + product.setDiscountRate(BigDecimal.valueOf(100)); + } + } else { + if (StringUtil.isNotBlank(product.getOutSheetDetailId())) { + SaleOutSheetDetailLot detailLot = saleOutSheetDetailLotService.getById( + product.getOutSheetDetailId()); + SaleOutSheetDetail outSheetDetail = saleOutSheetDetailService.getById( + detailLot.getDetailId()); + product.setTaxPrice(outSheetDetail.getTaxPrice()); + } else { + product.setTaxPrice(BigDecimal.ZERO); + } + } + + orderNo++; + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/QuerySaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/QuerySaleReturnVo.java new file mode 100644 index 0000000..028620a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/QuerySaleReturnVo.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.SaleReturnStatus; +import com.lframework.xingyun.sc.enums.SettleStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySaleReturnVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 操作人ID + */ + @ApiModelProperty("操作人ID") + private String createBy; + + /** + * 操作起始时间 + */ + @ApiModelProperty("操作起始时间") + private LocalDateTime createStartTime; + + /** + * 操作截止时间 + */ + @ApiModelProperty("操作截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人ID + */ + @ApiModelProperty("审核人ID") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式不正确!", enumClass = SaleReturnStatus.class) + private Integer status; + + /** + * 销售员ID + */ + @ApiModelProperty("销售员ID") + private String salerId; + + /** + * 出库单号 + */ + @ApiModelProperty("出库单号") + private String outSheetCode; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/SaleReturnProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/SaleReturnProductVo.java new file mode 100644 index 0000000..be035a2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/SaleReturnProductVo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SaleReturnProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty("商品ID") + private String productId; + + /** + * 原价 + */ + @ApiModelProperty("原价") + private BigDecimal oriPrice; + + /** + * 现价 + */ + @ApiModelProperty("现价") + private BigDecimal taxPrice; + + /** + * 折扣(%) + */ + @ApiModelProperty("折扣(%)") + private BigDecimal discountRate; + + /** + * 退货数量 + */ + @ApiModelProperty("退货数量") + private Integer returnNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 出库单明细ID + */ + @ApiModelProperty("出库单明细ID") + private String outSheetDetailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/UpdateSaleReturnVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/UpdateSaleReturnVo.java new file mode 100644 index 0000000..c785289 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/sale/returned/UpdateSaleReturnVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.vo.sale.returned; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.service.sale.SaleReturnService; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateSaleReturnVo extends CreateSaleReturnVo { + + private static final long serialVersionUID = 1L; + + /** + * 退单ID + */ + @ApiModelProperty(value = "退单ID", required = true) + @NotBlank(message = "退单ID不能为空!") + private String id; + + @Override + public void validate() { + + SaleReturnService saleReturnService = ApplicationUtil.getBean(SaleReturnService.class); + SaleReturn saleReturn = saleReturnService.getById(this.getId()); + + this.validate(!StringUtil.isBlank(saleReturn.getOutSheetId())); + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/AddProductStockVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/AddProductStockVo.java new file mode 100644 index 0000000..f393b85 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/AddProductStockVo.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.sc.vo.stock; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class AddProductStockVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 入库数量 + */ + @ApiModelProperty(value = "入库数量", required = true) + @NotNull(message = "入库数量不能为空!") + @Min(message = "入库数量必须大于0!", value = 1) + private Integer stockNum; + + /** + * 含税成本总金额,如果为null则代表不计算均价入库 + */ + @ApiModelProperty("含税成本价,如果为null则代表不计算均价入库") + @Min(message = "含税成本价不能小于0!", value = 0) + private BigDecimal taxPrice; + + /** + * 默认的含税成本价,如果不为null则代表:入库时商品没有库存(没有均价),按照此成本价入库 如果与taxPrice同时为null,那么当入库时没有库存就会报错 + */ + @ApiModelProperty("默认的含税成本价,如果不为null则代表:入库时商品没有库存(没有均价),按照此成本价入库 如果与taxPrice同时为null,那么当入库时没有库存就会报错") + @Min(message = "默认的含税成本价不能小于0!", value = 0) + private BigDecimal defaultTaxPrice; + + /** + * 入库时间 + */ + @ApiModelProperty("入库时间") + private LocalDateTime createTime = LocalDateTime.now(); + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型不正确!", enumClass = ProductStockBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/QueryProductStockVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/QueryProductStockVo.java new file mode 100644 index 0000000..eb198b9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/QueryProductStockVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.sc.vo.stock; + +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryProductStockVo extends SortPageVo { + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 商品类目ID + */ + @ApiModelProperty("商品类目ID") + private String categoryId; + + /** + * 商品品牌ID + */ + @ApiModelProperty("商品品牌ID") + private String brandId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/StockCostAdjustVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/StockCostAdjustVo.java new file mode 100644 index 0000000..e168bd1 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/StockCostAdjustVo.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.sc.vo.stock; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class StockCostAdjustVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 含税成本价 + */ + @ApiModelProperty(value = "含税成本价", required = true) + @NotNull(message = "含税成本价不能为空!") + @Min(message = "含税成本价不能小于0!", value = 0) + private BigDecimal taxPrice; + + /** + * 税率(%) + */ + @ApiModelProperty(value = "税率(%)", required = true) + @NotNull(message = "税率(%)不能为空!") + @Min(message = "税率(%)不能小于0!", value = 0) + private BigDecimal taxRate; + + /** + * 出库时间 + */ + @ApiModelProperty("出库时间") + private LocalDateTime createTime = LocalDateTime.now(); + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/SubProductStockVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/SubProductStockVo.java new file mode 100644 index 0000000..1adb1b7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/SubProductStockVo.java @@ -0,0 +1,80 @@ +package com.lframework.xingyun.sc.vo.stock; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class SubProductStockVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 出库数量 + */ + @ApiModelProperty(value = "出库数量", required = true) + @NotNull(message = "出库数量不能为空!") + @Min(message = "出库数量必须大于0!", value = 1) + private Integer stockNum; + + /** + * 含税成本总金额 + */ + @ApiModelProperty("含税成本总金额") + @Min(message = "含税成本总金额不能小于0!", value = 0) + private BigDecimal taxAmount; + + /** + * 出库时间 + */ + @ApiModelProperty("出库时间") + private LocalDateTime createTime = LocalDateTime.now(); + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型不正确!", enumClass = ProductStockBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApprovePassStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApprovePassStockCostAdjustSheetVo.java new file mode 100644 index 0000000..9db16fb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApprovePassStockCostAdjustSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassStockCostAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApproveRefuseStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApproveRefuseStockCostAdjustSheetVo.java new file mode 100644 index 0000000..72f3c11 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/ApproveRefuseStockCostAdjustSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseStockCostAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty("拒绝理由") + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApprovePassStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApprovePassStockCostAdjustSheetVo.java new file mode 100644 index 0000000..a8f0dbe --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApprovePassStockCostAdjustSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassStockCostAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 库存成本调整单ID + */ + @ApiModelProperty(value = "库存成本调整单ID", required = true) + @NotEmpty(message = "库存成本调整单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApproveRefuseStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApproveRefuseStockCostAdjustSheetVo.java new file mode 100644 index 0000000..80acfd7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/BatchApproveRefuseStockCostAdjustSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseStockCostAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 库存成本调整单ID + */ + @ApiModelProperty(value = "库存成本调整单ID", required = true) + @NotEmpty(message = "库存成本调整单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/CreateStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/CreateStockCostAdjustSheetVo.java new file mode 100644 index 0000000..daf1a07 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/CreateStockCostAdjustSheetVo.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateStockCostAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "请输入仓库ID!") + private String scId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "请录入商品!") + private List products; + + public void validate() { + + int orderNo = 1; + for (StockCostAdjustProductVo product : this.products) { + if (NumberUtil.lt(product.getPrice(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行商品的调整后成本价不允许小于0!"); + } + + if (!NumberUtil.isNumberPrecision(product.getPrice(), 2)) { + throw new DefaultClientException("第" + orderNo + "行商品的调整后成本价最多允许2位小数!"); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustProductVo.java new file mode 100644 index 0000000..b383d4b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryStockCostAdjustProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustSheetVo.java new file mode 100644 index 0000000..467570b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/QueryStockCostAdjustSheetVo.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.StockCostAdjustSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryStockCostAdjustSheetVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + @IsEnum(message = "状态格式有误!", enumClass = StockCostAdjustSheetStatus.class) + private Integer status; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 起始时间 + */ + @ApiModelProperty("审核时间 起始时间") + @TypeMismatch(message = "审核时间起始时间格式有误!") + private LocalDateTime approveTimeStart; + + /** + * 审核时间 截止时间 + */ + @ApiModelProperty("审核时间 截止时间") + @TypeMismatch(message = "审核时间截止时间格式有误!") + private LocalDateTime approveTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/StockCostAdjustProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/StockCostAdjustProductVo.java new file mode 100644 index 0000000..39afef2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/StockCostAdjustProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class StockCostAdjustProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 调整后成本价 + */ + @ApiModelProperty(value = "调整后成本价", required = true) + @NotNull(message = "调整后成本价不能为空!") + @TypeMismatch(message = "调整后成本价格式有误!") + private BigDecimal price; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/UpdateStockCostAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/UpdateStockCostAdjustSheetVo.java new file mode 100644 index 0000000..c7d5ee9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/cost/UpdateStockCostAdjustSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.cost; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateStockCostAdjustSheetVo extends CreateStockCostAdjustSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApprovePassStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApprovePassStockAdjustSheetVo.java new file mode 100644 index 0000000..46751e3 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApprovePassStockAdjustSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassStockAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApproveRefuseStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApproveRefuseStockAdjustSheetVo.java new file mode 100644 index 0000000..00977ef --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/ApproveRefuseStockAdjustSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseStockAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty("拒绝理由") + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApprovePassStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApprovePassStockAdjustSheetVo.java new file mode 100644 index 0000000..b19fcd0 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApprovePassStockAdjustSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassStockAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 库存调整单ID + */ + @ApiModelProperty(value = "库存调整单ID", required = true) + @NotEmpty(message = "库存调整单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApproveRefuseStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApproveRefuseStockAdjustSheetVo.java new file mode 100644 index 0000000..3d2264a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/BatchApproveRefuseStockAdjustSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseStockAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 库存调整单ID + */ + @ApiModelProperty(value = "库存调整单ID", required = true) + @NotEmpty(message = "库存调整单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/CreateStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/CreateStockAdjustSheetVo.java new file mode 100644 index 0000000..c168fad --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/CreateStockAdjustSheetVo.java @@ -0,0 +1,68 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.StockAdjustSheetBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateStockAdjustSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "请输入仓库ID!") + private String scId; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型格式错误!", enumClass = StockAdjustSheetBizType.class) + private Integer bizType; + + /** + * 调整原因ID + */ + @ApiModelProperty(value = "调整原因ID", required = true) + @NotBlank(message = "调整原因ID不能为空!") + private String reasonId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "请录入商品!") + private List products; + + public void validate() { + + int orderNo = 1; + for (StockAdjustProductVo product : this.products) { + if (NumberUtil.le(product.getStockNum(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行商品的调整库存数量必须大于0!"); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustProductVo.java new file mode 100644 index 0000000..fa15f4f --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryStockAdjustProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustSheetVo.java new file mode 100644 index 0000000..7213209 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/QueryStockAdjustSheetVo.java @@ -0,0 +1,90 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.StockCostAdjustSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryStockAdjustSheetVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + /** + * 调整原因ID + */ + @ApiModelProperty("调整原因ID") + private String reasonId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + @IsEnum(message = "状态格式有误!", enumClass = StockCostAdjustSheetStatus.class) + private Integer status; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 起始时间 + */ + @ApiModelProperty("审核时间 起始时间") + @TypeMismatch(message = "审核时间起始时间格式有误!") + private LocalDateTime approveTimeStart; + + /** + * 审核时间 截止时间 + */ + @ApiModelProperty("审核时间 截止时间") + @TypeMismatch(message = "审核时间截止时间格式有误!") + private LocalDateTime approveTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/StockAdjustProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/StockAdjustProductVo.java new file mode 100644 index 0000000..bdf3b57 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/StockAdjustProductVo.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class StockAdjustProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 调整库存数量 + */ + @ApiModelProperty(value = "调整库存数量", required = true) + @NotNull(message = "调整库存数量不能为空!") + @TypeMismatch(message = "调整库存数量格式有误!") + private Integer stockNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/UpdateStockAdjustSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/UpdateStockAdjustSheetVo.java new file mode 100644 index 0000000..284e34a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/UpdateStockAdjustSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateStockAdjustSheetVo extends CreateStockAdjustSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/CreateStockAdjustReasonVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/CreateStockAdjustReasonVo.java new file mode 100644 index 0000000..5e9c446 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/CreateStockAdjustReasonVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock.reason; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateStockAdjustReasonVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/QueryStockAdjustReasonVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/QueryStockAdjustReasonVo.java new file mode 100644 index 0000000..bef6167 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/QueryStockAdjustReasonVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock.reason; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryStockAdjustReasonVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/StockAdjustReasonSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/StockAdjustReasonSelectorVo.java new file mode 100644 index 0000000..c1b15e8 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/StockAdjustReasonSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock.reason; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class StockAdjustReasonSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/UpdateStockAdjustReasonVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/UpdateStockAdjustReasonVo.java new file mode 100644 index 0000000..0243aeb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/adjust/stock/reason/UpdateStockAdjustReasonVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.sc.vo.stock.adjust.stock.reason; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateStockAdjustReasonVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithAddStockVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithAddStockVo.java new file mode 100644 index 0000000..db554e2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithAddStockVo.java @@ -0,0 +1,122 @@ +package com.lframework.xingyun.sc.vo.stock.log; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class AddLogWithAddStockVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 入库数量 + */ + @ApiModelProperty(value = "入库数量", required = true) + @NotNull(message = "入库数量不能为空!") + @Min(message = "入库数量必须大于0!", value = 1) + private Integer stockNum; + + /** + * 含税成本总金额 + */ + @ApiModelProperty(value = "含税成本总金额", required = true) + @NotNull(message = "含税成本总金额不能为空!") + @Min(message = "含税成本总金额不能小于0!", value = 0) + private BigDecimal taxAmount; + + /** + * 原库存数量 + */ + @ApiModelProperty(value = "原库存数量", required = true) + @NotNull(message = "原库存数量不能为空!") + private Integer oriStockNum; + + /** + * 现库存数量 + */ + @ApiModelProperty(value = "现库存数量", required = true) + @NotNull(message = "现库存数量不能为空!") + private Integer curStockNum; + + /** + * 原含税成本价 + */ + @ApiModelProperty(value = "原含税成本价", required = true) + @NotNull(message = "原含税成本价不能为空!") + private BigDecimal oriTaxPrice; + + /** + * 现含税成本价 + */ + @ApiModelProperty(value = "现含税成本价", required = true) + @NotNull(message = "现含税成本价不能为空!") + private BigDecimal curTaxPrice; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createById; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 入库时间 + */ + @ApiModelProperty(value = "入库时间", required = true) + @NotNull(message = "入库时间不能为空!") + private LocalDateTime createTime; + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型不正确!", enumClass = ProductStockBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithStockCostAdjustVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithStockCostAdjustVo.java new file mode 100644 index 0000000..746abe9 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithStockCostAdjustVo.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.sc.vo.stock.log; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class AddLogWithStockCostAdjustVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 含税成本总金额 + */ + @ApiModelProperty(value = "含税成本总金额", required = true) + @NotNull(message = "含税成本总金额不能为空!") + @Min(message = "含税成本总金额不能小于0!", value = 0) + private BigDecimal taxAmount; + + /** + * 原库存数量 + */ + @ApiModelProperty(value = "原库存数量", required = true) + @NotNull(message = "原库存数量不能为空!") + private Integer oriStockNum; + + /** + * 原含税成本价 + */ + @ApiModelProperty(value = "原含税成本价", required = true) + @NotNull(message = "原含税成本价不能为空!") + private BigDecimal oriTaxPrice; + + /** + * 现含税成本价 + */ + @ApiModelProperty(value = "现含税成本价", required = true) + @NotNull(message = "现含税成本价不能为空!") + private BigDecimal curTaxPrice; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createById; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 出库时间 + */ + @ApiModelProperty(value = "出库时间", required = true) + @NotNull(message = "出库时间不能为空!") + private LocalDateTime createTime; + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithSubStockVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithSubStockVo.java new file mode 100644 index 0000000..2c03900 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/AddLogWithSubStockVo.java @@ -0,0 +1,122 @@ +package com.lframework.xingyun.sc.vo.stock.log; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class AddLogWithSubStockVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 出库数量 + */ + @ApiModelProperty(value = "出库数量", required = true) + @NotNull(message = "出库数量不能为空!") + @Min(message = "出库数量必须大于0!", value = 1) + private Integer stockNum; + + /** + * 含税成本总金额 + */ + @ApiModelProperty(value = "含税成本总金额", required = true) + @NotNull(message = "含税成本总金额不能为空!") + @Min(message = "含税成本总金额不能小于0!", value = 0) + private BigDecimal taxAmount; + + /** + * 原库存数量 + */ + @ApiModelProperty(value = "原库存数量", required = true) + @NotNull(message = "原库存数量不能为空!") + private Integer oriStockNum; + + /** + * 现库存数量 + */ + @ApiModelProperty(value = "现库存数量", required = true) + @NotNull(message = "现库存数量不能为空!") + private Integer curStockNum; + + /** + * 原含税成本价 + */ + @ApiModelProperty(value = "原含税成本价", required = true) + @NotNull(message = "原含税成本价不能为空!") + private BigDecimal oriTaxPrice; + + /** + * 现含税成本价 + */ + @ApiModelProperty(value = "现含税成本价", required = true) + @NotNull(message = "现含税成本价不能为空!") + private BigDecimal curTaxPrice; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createById; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 出库时间 + */ + @ApiModelProperty(value = "出库时间", required = true) + @NotNull(message = "出库时间不能为空!") + private LocalDateTime createTime; + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型不正确!", enumClass = ProductStockBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/QueryProductStockLogVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/QueryProductStockLogVo.java new file mode 100644 index 0000000..cbe25fc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/log/QueryProductStockLogVo.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.sc.vo.stock.log; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryProductStockLogVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 商品类目ID + */ + @ApiModelProperty("商品类目ID") + private String categoryId; + + /** + * 商品品牌ID + */ + @ApiModelProperty("商品品牌ID") + private String brandId; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @IsEnum(message = "业务类型不存在!", enumClass = ProductStockBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/AddProductLotStockVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/AddProductLotStockVo.java new file mode 100644 index 0000000..8363e4a --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/AddProductLotStockVo.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.sc.vo.stock.lot; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class AddProductLotStockVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 入库数量 + */ + @ApiModelProperty(value = "入库数量", required = true) + @NotNull(message = "入库数量不能为空!") + @Min(message = "入库数量必须大于0!", value = 1) + private Integer stockNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/CreateProductLotVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/CreateProductLotVo.java new file mode 100644 index 0000000..e0f029e --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/CreateProductLotVo.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.sc.vo.stock.lot; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.ProductStockBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateProductLotVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotBlank(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 税率(%) + */ + @ApiModelProperty(value = "税率(%)", required = true) + @NotNull(message = "税率(%)不能为空!") + @Min(message = "税率(%)不能小于0!", value = 0) + private BigDecimal taxRate; + + /** + * 入库时间 + */ + @ApiModelProperty("入库时间") + private LocalDateTime createTime = LocalDateTime.now(); + + /** + * 业务单据ID + */ + @ApiModelProperty("业务单据ID") + private String bizId; + + /** + * 业务单据明细ID + */ + @ApiModelProperty("业务单据明细ID") + private String bizDetailId; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型不正确!", enumClass = ProductStockBizType.class) + private Integer bizType; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/QueryProductLotVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/QueryProductLotVo.java new file mode 100644 index 0000000..60c25a2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/lot/QueryProductLotVo.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.sc.vo.stock.lot; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryProductLotVo extends PageVo { + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 商品编号 + */ + @ApiModelProperty("商品编号") + private String productCode; + + /** + * 商品名称 + */ + @ApiModelProperty("商品名称") + private String productName; + + /** + * 商品类目ID + */ + @ApiModelProperty("商品类目ID") + private String categoryId; + + /** + * 商品品牌ID + */ + @ApiModelProperty("商品品牌ID") + private String brandId; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 生成起始时间 + */ + @ApiModelProperty("生成起始时间") + private LocalDateTime createStartTime; + + /** + * 生成截止时间 + */ + @ApiModelProperty("生成截止时间") + private LocalDateTime createEndTime; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/config/UpdateTakeStockConfigVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/config/UpdateTakeStockConfigVo.java new file mode 100644 index 0000000..b70ae22 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/config/UpdateTakeStockConfigVo.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.sc.vo.stock.take.config; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateTakeStockConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据 + */ + @ApiModelProperty(value = "库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据", required = true) + @TypeMismatch(message = "库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据格式有误!") + @NotNull(message = "请选择库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据!") + private Boolean showProduct; + + /** + * 库存盘点单是否显示盘点任务创建时商品的系统库存数量 + */ + @ApiModelProperty(value = "库存盘点单是否显示盘点任务创建时商品的系统库存数量", required = true) + @TypeMismatch(message = "库存盘点单是否显示盘点任务创建时商品的系统库存数量格式有误!") + @NotNull(message = "请选择库存盘点单是否显示盘点任务创建时商品的系统库存数量!") + private Boolean showStock; + + /** + * 盘点差异生成时是否自动调整盘点任务中商品的系统库存数量 + */ + @ApiModelProperty(value = "盘点差异生成时是否自动调整盘点任务中商品的系统库存数量", required = true) + @TypeMismatch(message = "盘点差异生成时是否自动调整盘点任务中商品的系统库存数量格式有误!") + @NotNull(message = "请选择盘点差异生成时是否自动调整盘点任务中商品的系统库存数量!") + private Boolean autoChangeStock; + + /** + * 盘点差异单中的盘点数量是否允许手动修改 + */ + @ApiModelProperty(value = "盘点差异单中的盘点数量是否允许手动修改", required = true) + @TypeMismatch(message = "盘点差异单中的盘点数量是否允许手动修改格式有误!") + @NotNull(message = "请选择盘点差异单中的盘点数量是否允许手动修改!") + private Boolean allowChangeNum; + + /** + * 盘点任务创建后多少小时内未完成,则自动作废 + */ + @ApiModelProperty(value = "盘点任务创建后多少小时内未完成,则自动作废", required = true) + @TypeMismatch(message = "盘点任务自动作废时间格式有误!") + @NotNull(message = "请输入盘点任务自动作废时间!") + @Min(value = 1, message = "盘点任务自动作废时间必须大于0!") + private Integer cancelHours; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CancelTakeStockPlanVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CancelTakeStockPlanVo.java new file mode 100644 index 0000000..68efcf7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CancelTakeStockPlanVo.java @@ -0,0 +1,20 @@ +package com.lframework.xingyun.sc.vo.stock.take.plan; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CancelTakeStockPlanVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CreateTakeStockPlanVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CreateTakeStockPlanVo.java new file mode 100644 index 0000000..680c507 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/CreateTakeStockPlanVo.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.sc.vo.stock.take.plan; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateTakeStockPlanVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "请输入仓库ID!") + private String scId; + + + /** + * 盘点类别 + */ + @ApiModelProperty(value = "盘点类别", required = true) + @NotNull(message = "请选择盘点类别!") + @TypeMismatch(message = "盘点类别格式有误!") + @IsEnum(message = "盘点类别格式有误!", enumClass = TakeStockPlanType.class) + private Integer takeType; + + /** + * 业务ID + */ + @ApiModelProperty("业务ID") + private List bizIds; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + TakeStockPlanType takeType = EnumUtil.getByCode(TakeStockPlanType.class, this.takeType); + if (takeType == TakeStockPlanType.CATEGORY) { + if (CollectionUtil.isEmpty(this.bizIds)) { + throw new InputErrorException("请选择商品类目!"); + } + } else if (takeType == TakeStockPlanType.BRAND) { + if (CollectionUtil.isEmpty(this.bizIds)) { + throw new InputErrorException("请选择商品品牌!"); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/HandleTakeStockPlanVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/HandleTakeStockPlanVo.java new file mode 100644 index 0000000..f42b65b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/HandleTakeStockPlanVo.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.sc.vo.stock.take.plan; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class HandleTakeStockPlanVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "商品信息不能为空!") + private List products; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否允许修改数量 + */ + @ApiModelProperty("是否允许修改数量") + private Boolean allowChangeNum; + + /** + * 是否自动计算数量 + */ + @ApiModelProperty("是否自动计算数量") + private Boolean autoChangeStock; + + @Data + public static class ProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 修改后盘点数量 + */ + @ApiModelProperty(value = "修改后盘点数量") + private Integer takeNum; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String description; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/QueryTakeStockPlanVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/QueryTakeStockPlanVo.java new file mode 100644 index 0000000..f96d0cb --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/QueryTakeStockPlanVo.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.sc.vo.stock.take.plan; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryTakeStockPlanVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + @TypeMismatch(message = "盘点状态格式有误!") + @IsEnum(message = "盘点状态格式有误!", enumClass = TakeStockPlanStatus.class) + private Integer takeStatus; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/TakeStockPlanSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/TakeStockPlanSelectorVo.java new file mode 100644 index 0000000..116d191 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/TakeStockPlanSelectorVo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.sc.vo.stock.take.plan; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import com.lframework.xingyun.sc.enums.TakeStockPlanType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class TakeStockPlanSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 是否正在进行盘点 + */ + @ApiModelProperty("是否正在进行盘点") + @TypeMismatch(message = "是否正在进行盘点格式有误!") + private Boolean taking; + + /** + * 盘点类别 + */ + @ApiModelProperty("盘点类别") + @TypeMismatch(message = "盘点类别格式有误!") + @IsEnum(message = "盘点类别格式有误!", enumClass = TakeStockPlanType.class) + private Integer takeType; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + @TypeMismatch(message = "盘点状态格式有误!") + @IsEnum(message = "盘点状态格式有误!", enumClass = TakeStockPlanStatus.class) + private Integer takeStatus; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/UpdateTakeStockPlanVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/UpdateTakeStockPlanVo.java new file mode 100644 index 0000000..1648f15 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/plan/UpdateTakeStockPlanVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.sc.vo.stock.take.plan; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateTakeStockPlanVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "请输入仓库ID!") + private String scId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + @NotBlank(message = "请输入备注!") + private String description; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/CreatePreTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/CreatePreTakeStockSheetVo.java new file mode 100644 index 0000000..d62dab2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/CreatePreTakeStockSheetVo.java @@ -0,0 +1,85 @@ +package com.lframework.xingyun.sc.vo.stock.take.pre; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreatePreTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "请选择仓库!") + private String scId; + + /** + * 预先盘点状态 + */ + @ApiModelProperty(value = "预先盘点状态", required = true) + @NotNull(message = "请选择预先盘点状态!") + @IsEnum(message = "预先盘点状态格式错误!", enumClass = PreTakeStockSheetStatus.class) + @TypeMismatch(message = "预先盘点状态格式错误!") + private Integer takeStatus; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 商品 + */ + @ApiModelProperty(value = "商品", required = true) + @Valid + @NotEmpty(message = "请录入商品!") + private List products; + + public void validate() { + + Set checkSet = new HashSet<>(); + PreTakeStockSheetStatus takeStatus = EnumUtil.getByCode(PreTakeStockSheetStatus.class, + this.getTakeStatus()); + for (int i = 0; i < this.getProducts().size(); i++) { + PreTakeStockProductVo product = this.getProducts().get(i); + if (checkSet.contains(product.getProductId())) { + throw new InputErrorException("第" + (i + 1) + "行商品已存在列表中,请勿重复添加!"); + } + + checkSet.add(product.getProductId()); + + if (takeStatus == PreTakeStockSheetStatus.FIRST_TAKE) { + if (product.getFirstNum() == null) { + throw new InputErrorException("第" + (i + 1) + "行商品的初盘数量不允许为空!"); + } + } else if (takeStatus == PreTakeStockSheetStatus.SECOND_TAKE) { + if (product.getSecondNum() == null) { + throw new InputErrorException("第" + (i + 1) + "行商品的复盘数量不允许为空!"); + } + } else if (takeStatus == PreTakeStockSheetStatus.RAND_TAKE) { + if (product.getRandNum() == null) { + throw new InputErrorException("第" + (i + 1) + "行商品的抽盘数量不允许为空!"); + } + } else { + throw new InputErrorException("预先盘点状态格式错误!"); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockProductVo.java new file mode 100644 index 0000000..dbfe575 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockProductVo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.sc.vo.stock.take.pre; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class PreTakeStockProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 初盘数量 + */ + @ApiModelProperty("初盘数量") + private Integer firstNum; + + /** + * 复盘数量 + */ + @ApiModelProperty("复盘数量") + private Integer secondNum; + + /** + * 抽盘数量 + */ + @ApiModelProperty("抽盘数量") + private Integer randNum; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockSheetSelectorVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockSheetSelectorVo.java new file mode 100644 index 0000000..e3dca38 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/PreTakeStockSheetSelectorVo.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.sc.vo.stock.take.pre; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class PreTakeStockSheetSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + @TypeMismatch(message = "预先盘点状态格式有误!") + @IsEnum(message = "预先盘点状态格式有误!", enumClass = PreTakeStockSheetStatus.class) + private Integer takeStatus; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockProductVo.java new file mode 100644 index 0000000..f6ef478 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockProductVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.stock.take.pre; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryPreTakeStockProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockSheetVo.java new file mode 100644 index 0000000..8acfeab --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/QueryPreTakeStockSheetVo.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.sc.vo.stock.take.pre; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.PreTakeStockSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryPreTakeStockSheetVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + @TypeMismatch(message = "预先盘点状态格式有误!") + @IsEnum(message = "预先盘点状态格式有误!", enumClass = PreTakeStockSheetStatus.class) + private Integer takeStatus; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/UpdatePreTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/UpdatePreTakeStockSheetVo.java new file mode 100644 index 0000000..301c48c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/pre/UpdatePreTakeStockSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.sc.vo.stock.take.pre; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdatePreTakeStockSheetVo extends CreatePreTakeStockSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApprovePassTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApprovePassTakeStockSheetVo.java new file mode 100644 index 0000000..f9a4c69 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApprovePassTakeStockSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApproveRefuseTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApproveRefuseTakeStockSheetVo.java new file mode 100644 index 0000000..bf2c35d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/ApproveRefuseTakeStockSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApprovePassTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApprovePassTakeStockSheetVo.java new file mode 100644 index 0000000..5b19aa2 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApprovePassTakeStockSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotEmpty(message = "ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApproveRefuseTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApproveRefuseTakeStockSheetVo.java new file mode 100644 index 0000000..70779af --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/BatchApproveRefuseTakeStockSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotEmpty(message = "ID不能为空!") + private List ids; + + /** + * 拒绝原因 + */ + @ApiModelProperty(value = "拒绝原因", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/CreateTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/CreateTakeStockSheetVo.java new file mode 100644 index 0000000..e97f415 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/CreateTakeStockSheetVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 盘点任务ID + */ + @ApiModelProperty(value = "盘点任务ID", required = true) + @NotBlank(message = "请选择关联盘点任务!") + private String planId; + + /** + * 预先盘点单ID + */ + @ApiModelProperty("预先盘点单ID") + private String preSheetId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "请录入商品!") + private List products; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetProductVo.java new file mode 100644 index 0000000..096124d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryTakeStockSheetProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; + + /** + * 盘点任务ID + */ + @ApiModelProperty(value = "盘点任务ID", required = true) + @NotBlank(message = "盘点任务ID不能为空!") + private String planId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetVo.java new file mode 100644 index 0000000..4163bf6 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/QueryTakeStockSheetVo.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.TakeStockPlanStatus; +import com.lframework.xingyun.sc.enums.TakeStockSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryTakeStockSheetVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 盘点任务ID + */ + @ApiModelProperty("盘点任务ID") + private String planId; + + /** + * 预先盘点单ID + */ + @ApiModelProperty("预先盘点单ID") + private String preSheetId; + + /** + * 仓库ID + */ + @ApiModelProperty("仓库ID") + private String scId; + + /** + * 盘点状态 + */ + @ApiModelProperty("盘点状态") + @TypeMismatch(message = "盘点状态格式有误!") + @IsEnum(message = "盘点状态格式有误!", enumClass = TakeStockPlanStatus.class) + private Integer takeStatus; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + @IsEnum(message = "状态格式有误!", enumClass = TakeStockSheetStatus.class) + private Integer status; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 起始时间 + */ + @ApiModelProperty("审核时间 起始时间") + @TypeMismatch(message = "审核时间起始时间格式有误!") + private LocalDateTime approveTimeStart; + + /** + * 审核时间 截止时间 + */ + @ApiModelProperty("审核时间 截止时间") + @TypeMismatch(message = "审核时间截止时间格式有误!") + private LocalDateTime approveTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/TakeStockSheetProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/TakeStockSheetProductVo.java new file mode 100644 index 0000000..00b5e94 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/TakeStockSheetProductVo.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class TakeStockSheetProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 盘点数量 + */ + @ApiModelProperty(value = "盘点数量", required = true) + @NotNull(message = "盘点数量不能为空!") + @TypeMismatch(message = "盘点数量格式有误!") + private Integer takeNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/UpdateTakeStockSheetVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/UpdateTakeStockSheetVo.java new file mode 100644 index 0000000..9efd3bc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/take/sheet/UpdateTakeStockSheetVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.stock.take.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class UpdateTakeStockSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "请录入商品!") + private List products; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApprovePassScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApprovePassScTransferOrderVo.java new file mode 100644 index 0000000..906b04c --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApprovePassScTransferOrderVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApprovePassScTransferOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApproveRefuseScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApproveRefuseScTransferOrderVo.java new file mode 100644 index 0000000..3afacc7 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ApproveRefuseScTransferOrderVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseScTransferOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty("拒绝理由") + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApprovePassScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApprovePassScTransferOrderVo.java new file mode 100644 index 0000000..dd3bbbc --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApprovePassScTransferOrderVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApprovePassScTransferOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库调拨单ID + */ + @ApiModelProperty(value = "仓库调拨单ID", required = true) + @NotEmpty(message = "仓库调拨单ID不能为空!") + private List ids; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApproveRefuseScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApproveRefuseScTransferOrderVo.java new file mode 100644 index 0000000..0ef7367 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/BatchApproveRefuseScTransferOrderVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class BatchApproveRefuseScTransferOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 仓库调拨单ID + */ + @ApiModelProperty(value = "仓库调拨单ID", required = true) + @NotEmpty(message = "仓库调拨ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/CreateScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/CreateScTransferOrderVo.java new file mode 100644 index 0000000..3222000 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/CreateScTransferOrderVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateScTransferOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 转出仓库ID + */ + @ApiModelProperty(value = "转出仓库ID", required = true) + @NotBlank(message = "转出仓库ID不能为空!") + private String sourceScId; + + /** + * 转入仓库ID + */ + @ApiModelProperty(value = "转入仓库ID", required = true) + @NotBlank(message = "转入仓库ID不能为空!") + private String targetScId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "商品信息", required = true) + @Valid + @NotEmpty(message = "请录入商品!") + private List products; + + public void validate() { + + int orderNo = 1; + for (ScTransferProductVo product : this.products) { + if (NumberUtil.le(product.getTransferNum(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行商品的调拨数量必须大于0!"); + } + } + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderDetailReceiveVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderDetailReceiveVo.java new file mode 100644 index 0000000..17f3a55 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderDetailReceiveVo.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryScTransferOrderDetailReceiveVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "调拨单ID", required = true) + @NotBlank(message = "调拨单ID不能为空!") + private String orderId; + + @ApiModelProperty(value = "明细ID", required = true) + @NotBlank(message = "明细ID不能为空!") + private String detailId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderVo.java new file mode 100644 index 0000000..9bcba9b --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferOrderVo.java @@ -0,0 +1,84 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.ScTransferOrderStatus; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryScTransferOrderVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 转出仓库ID + */ + @ApiModelProperty("转出仓库ID") + private String sourceScId; + + /** + * 转入仓库ID + */ + @ApiModelProperty("转入仓库ID") + private String targetScId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @TypeMismatch(message = "状态格式有误!") + @IsEnum(message = "状态格式有误!", enumClass = ScTransferOrderStatus.class) + private Integer status; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 起始时间 + */ + @ApiModelProperty("修改时间 起始时间") + @TypeMismatch(message = "修改时间起始时间格式有误!") + private LocalDateTime updateTimeStart; + + /** + * 修改时间 截止时间 + */ + @ApiModelProperty("修改时间 截止时间") + @TypeMismatch(message = "修改时间截止时间格式有误!") + private LocalDateTime updateTimeEnd; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 起始时间 + */ + @ApiModelProperty("审核时间 起始时间") + @TypeMismatch(message = "审核时间起始时间格式有误!") + private LocalDateTime approveTimeStart; + + /** + * 审核时间 截止时间 + */ + @ApiModelProperty("审核时间 截止时间") + @TypeMismatch(message = "审核时间截止时间格式有误!") + private LocalDateTime approveTimeEnd; + +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferProductVo.java new file mode 100644 index 0000000..c14cc64 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/QueryScTransferProductVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QueryScTransferProductVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 仓库ID + */ + @ApiModelProperty(value = "仓库ID", required = true) + @NotBlank(message = "仓库ID不能为空!") + private String scId; + + /** + * 检索关键字 + */ + @ApiModelProperty("检索关键字") + private String condition; + + /** + * 类目ID + */ + @ApiModelProperty("类目ID") + private String categoryId; + + /** + * 品牌ID + */ + @ApiModelProperty("品牌ID") + private String brandId; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ReceiveScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ReceiveScTransferOrderVo.java new file mode 100644 index 0000000..478ddba --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ReceiveScTransferOrderVo.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ReceiveScTransferOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 商品信息 + */ + @ApiModelProperty(value = "收货商品", required = true) + @Valid + @NotEmpty(message = "收货商品不能为空!") + private List products; + + @Data + public static class ReceiveScTransferProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 收货数量 + */ + @ApiModelProperty(value = "收货数量", required = true) + @NotNull(message = "收货数量不能为空!") + @TypeMismatch(message = "收货数量格式有误!") + private Integer receiveNum; + } +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ScTransferProductVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ScTransferProductVo.java new file mode 100644 index 0000000..0e3605d --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/ScTransferProductVo.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ScTransferProductVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", required = true) + @NotBlank(message = "商品ID不能为空!") + private String productId; + + /** + * 调拨数量 + */ + @ApiModelProperty(value = "调拨数量", required = true) + @NotNull(message = "调拨数量不能为空!") + @TypeMismatch(message = "调拨数量格式有误!") + private Integer transferNum; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/UpdateScTransferOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/UpdateScTransferOrderVo.java new file mode 100644 index 0000000..75ad5ad --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/stock/transfer/UpdateScTransferOrderVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.sc.vo.stock.transfer; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class UpdateScTransferOrderVo extends CreateScTransferOrderVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; +} diff --git a/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/ydool/YdoolApproveOrderVo.java b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/ydool/YdoolApproveOrderVo.java new file mode 100644 index 0000000..8247321 --- /dev/null +++ b/xingyun-sc/src/main/java/com/lframework/xingyun/sc/vo/ydool/YdoolApproveOrderVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.sc.vo.ydool; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +@Data +public class YdoolApproveOrderVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + /** + * 订单ID 前端给的是order_id + */ + @ApiModelProperty(value = "订单ID", required = true,name = "order_id") + @NotBlank(message = "订单ID不能为空!") + @JsonProperty("order_id") // 映射前端字段名 + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String msg; + + /** + * 是否通过 + */ + @ApiModelProperty(value = "是否通过", required = true) + @NotBlank(message = "是否通过不能为空!") + private String status; +} diff --git a/xingyun-sc/src/main/java/lombok.config b/xingyun-sc/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-sc/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/mappers/logistics/LogisticsSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/logistics/LogisticsSheetMapper.xml new file mode 100644 index 0000000..6936f24 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/logistics/LogisticsSheetMapper.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + o.* + FROM tbl_logistics_sheet AS o + + + + SELECT + o.id, + o.code, + o.logistics_no, + o.logistics_company_id, + o.sender_name, + o.sender_telephone, + o.sender_province_id, + o.sender_city_id, + o.sender_district_id, + o.sender_address, + o.receiver_name, + o.receiver_telephone, + o.receiver_province_id, + o.receiver_city_id, + o.receiver_district_id, + o.receiver_address, + o.status, + o.description, + o.total_weight, + o.total_volume, + o.total_amount, + o.delivery_by, + o.delivery_time, + o.create_by, + o.create_time, + o.update_by, + o.update_time, + d.id AS detail_id, + d.sheet_id AS detail_sheet_id, + d.biz_id AS detail_biz_id, + d.biz_type AS detail_biz_type + FROM tbl_logistics_sheet AS o + LEFT JOIN tbl_logistics_sheet_detail AS d ON d.sheet_id = o.id + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderDetailMapper.xml new file mode 100644 index 0000000..c0e1168 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderDetailMapper.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + SELECT + d.id, + d.order_id, + d.product_id, + d.order_num, + d.tax_price, + d.is_gift, + d.tax_rate, + d.description, + d.order_no, + d.receive_num + FROM tbl_purchase_order_detail AS d + + + UPDATE tbl_purchase_order_detail + SET receive_num = receive_num + #{num} + WHERE id = #{id} + AND (order_num - receive_num) >= #{num} + + + UPDATE tbl_purchase_order_detail + SET receive_num = receive_num - #{num} + WHERE id = #{id} + AND receive_num >= #{num} + + + + diff --git a/xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderMapper.xml b/xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderMapper.xml new file mode 100644 index 0000000..9702abe --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/purchase/PurchaseOrderMapper.xml @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + o.id, + o.code, + o.sc_id, + o.supplier_id, + o.purchaser_id, + o.expect_arrive_date, + o.total_num, + o.total_gift_num, + o.total_amount, + o.description, + o.create_by, + o.create_time, + o.update_by, + o.update_time, + o.approve_by, + o.approve_time, + o.status, + o.refuse_reason + FROM tbl_purchase_order AS o + + + + SELECT + o.id, + o.code, + o.sc_id, + o.supplier_id, + o.purchaser_id, + o.expect_arrive_date, + o.total_num, + o.total_gift_num, + o.total_amount, + o.description, + o.create_by, + o.create_by_id, + o.create_time, + o.update_by, + o.update_time, + o.approve_by, + o.approve_time, + o.status, + o.refuse_reason, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.order_num AS detail_order_num, + d.tax_price AS detail_tax_price, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no + FROM tbl_purchase_order AS o + LEFT JOIN tbl_purchase_order_detail AS d ON d.order_id = o.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit, + purchase.price AS purchase_price, + g.tax_rate, + g.available + FROM base_data_product AS g + INNER JOIN base_data_product_purchase AS purchase ON purchase.id = g.id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/purchase/PurchaseReturnMapper.xml b/xingyun-sc/src/main/resources/mappers/purchase/PurchaseReturnMapper.xml new file mode 100644 index 0000000..97c6720 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/purchase/PurchaseReturnMapper.xml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + r.id, + r.code, + r.sc_id, + r.supplier_id, + r.purchaser_id, + r.payment_date, + r.receive_sheet_id, + r.total_num, + r.total_gift_num, + r.total_amount, + r.description, + r.create_by, + r.create_time, + r.approve_by, + r.approve_time, + r.status, + r.settle_status + FROM tbl_purchase_return AS r + LEFT JOIN tbl_receive_sheet AS s ON s.id = r.receive_sheet_id + + + + SELECT + r.id, + r.code, + r.sc_id, + r.supplier_id, + r.purchaser_id, + r.payment_date, + r.receive_sheet_id, + r.total_num, + r.total_gift_num, + r.total_amount, + r.description, + r.create_by, + r.create_time, + r.update_by, + r.update_time, + r.approve_by, + r.approve_time, + r.status, + r.refuse_reason, + r.settle_status, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.return_num AS detail_return_num, + d.tax_price AS detail_tax_price, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no, + d.receive_sheet_detail_id AS detail_receive_sheet_detail_id + FROM tbl_purchase_return AS r + LEFT JOIN tbl_purchase_return_detail AS d ON d.return_id = r.id + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetDetailMapper.xml new file mode 100644 index 0000000..27c4f04 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetDetailMapper.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + SELECT + d.id, + d.sheet_id, + d.product_id, + d.order_num, + d.tax_price, + d.is_gift, + d.tax_rate, + d.description, + d.order_no, + d.return_num + FROM tbl_receive_sheet_detail AS d + + + UPDATE tbl_receive_sheet_detail + SET return_num = return_num + #{num} + WHERE id = #{id} + AND (order_num - return_num) >= #{num} + + + UPDATE tbl_receive_sheet_detail + SET return_num = return_num - #{num} + WHERE id = #{id} + AND return_num >= #{num} + + + + diff --git a/xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetMapper.xml new file mode 100644 index 0000000..2fc62bb --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/purchase/ReceiveSheetMapper.xml @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + r.id, + r.code, + r.sc_id, + r.supplier_id, + r.purchaser_id, + r.payment_date, + r.receive_date, + r.purchase_order_id, + r.total_num, + r.total_gift_num, + r.total_amount, + r.description, + r.create_by, + r.create_time, + r.approve_by, + r.approve_time, + r.status, + r.settle_status + FROM tbl_receive_sheet AS r + LEFT JOIN tbl_purchase_order AS o ON o.id = r.purchase_order_id + + + + SELECT + r.id, + r.code, + r.sc_id, + r.supplier_id, + r.purchaser_id, + r.payment_date, + r.receive_date, + r.purchase_order_id, + r.total_num, + r.total_gift_num, + r.total_amount, + r.description, + r.create_by, + r.create_time, + r.update_by, + r.update_time, + r.approve_by, + r.approve_time, + r.status, + r.refuse_reason, + r.settle_status, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.order_num AS detail_order_num, + d.tax_price AS detail_tax_price, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no, + d.purchase_order_detail_id AS detail_purchase_order_detail_id + FROM tbl_receive_sheet AS r + LEFT JOIN tbl_receive_sheet_detail AS d ON d.sheet_id = r.id + + + + SELECT + s.id, + s.sc_id, + s.supplier_id, + s.purchaser_id, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.order_num AS detail_order_num, + d.tax_price AS detail_tax_price, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no, + d.return_num AS detail_return_num + FROM tbl_receive_sheet AS s + LEFT JOIN tbl_receive_sheet_detail AS d ON d.sheet_id = s.id + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailLotMapper.xml b/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailLotMapper.xml new file mode 100644 index 0000000..9f5d0e5 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailLotMapper.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + SELECT + d.id, + d.detail_id, + d.order_num, + d.return_num, + d.cost_tax_amount, + d.settle_status, + d.order_no + FROM tbl_retail_out_sheet_detail_lot AS d + + + UPDATE tbl_retail_out_sheet_detail_lot + SET return_num = return_num + #{num} + WHERE id = #{id} + AND (order_num - return_num) >= #{num} + + + UPDATE tbl_retail_out_sheet_detail_lot + SET return_num = return_num - #{num} + WHERE id = #{id} + AND return_num >= #{num} + + + diff --git a/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailMapper.xml new file mode 100644 index 0000000..69e54a3 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetDetailMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + SELECT + d.id, + d.sheet_id, + d.product_id, + d.order_num, + d.ori_price, + d.tax_price, + d.discount_rate, + d.is_gift, + d.tax_rate, + d.description, + d.order_no, + d.return_num + FROM tbl_retail_out_sheet_detail AS d + + + UPDATE tbl_retail_out_sheet_detail + SET return_num = return_num + #{num} + WHERE id = #{id} + AND (order_num - return_num) >= #{num} + + + UPDATE tbl_retail_out_sheet_detail + SET return_num = return_num - #{num} + WHERE id = #{id} + AND return_num >= #{num} + + + diff --git a/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetMapper.xml new file mode 100644 index 0000000..61a80fc --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/retail/RetailOutSheetMapper.xml @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + s.id, + s.code, + s.sc_id, + s.member_id, + s.saler_id, + s.payment_date, + s.total_num, + s.total_gift_num, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.approve_by, + s.approve_time, + s.status, + s.settle_status + FROM tbl_retail_out_sheet AS s + + + + SELECT + s.id, + s.code, + s.sc_id, + s.member_id, + s.saler_id, + s.payment_date, + s.total_num, + s.total_gift_num, + s.total_amount, + s.description, + s.create_by, + s.create_by_id, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + b.main_product_id AS detail_main_product_id, + d.product_id AS detail_product_id, + d.order_num AS detail_order_num, + d.ori_price AS detail_ori_price, + d.tax_price AS detail_tax_price, + d.discount_rate AS detail_discount_rate, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no, + d.settle_status AS detail_settle_status + FROM tbl_retail_out_sheet AS s + LEFT JOIN tbl_retail_out_sheet_detail AS d ON d.sheet_id = s.id + LEFT JOIN tbl_retail_out_sheet_detail_bundle AS b ON b.sheet_id = s.id AND b.product_detail_id = d.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit, + retail.price AS retail_price, + g.sale_tax_rate, + g.available + FROM base_data_product AS g + INNER JOIN base_data_product_retail AS retail ON retail.id = g.id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/retail/RetailReturnMapper.xml b/xingyun-sc/src/main/resources/mappers/retail/RetailReturnMapper.xml new file mode 100644 index 0000000..dc658d0 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/retail/RetailReturnMapper.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + r.id, + r.code, + r.sc_id, + r.member_id, + r.saler_id, + r.payment_date, + r.out_sheet_id, + r.total_num, + r.total_gift_num, + r.total_amount, + r.description, + r.create_by, + r.create_time, + r.approve_by, + r.approve_time, + r.status, + r.settle_status + FROM tbl_retail_return AS r + LEFT JOIN tbl_retail_out_sheet AS s ON s.id = r.out_sheet_id + + + + SELECT r.id, r.code, r.sc_id, r.member_id, r.saler_id, r.payment_date, r.out_sheet_id, r.total_num, r.total_gift_num, + r.total_amount, r.description, r.create_by, r.create_time, r.update_by, r.update_time, r.approve_by, r.approve_time, + r.status, r.refuse_reason, r.settle_status, d.id AS detail_id, d.product_id AS detail_product_id, + d.return_num AS detail_return_num, d.ori_price AS detail_ori_price, d.tax_price AS detail_tax_price, d.discount_rate AS detail_discount_rate, + d.is_gift AS detail_is_gift, d.tax_rate AS detail_tax_rate, d.description AS detail_description, d.order_no AS detail_order_no, + d.settle_status AS detail_settle_status, d.out_sheet_detail_id AS detail_out_sheet_detail_id + FROM tbl_retail_return AS r + LEFT JOIN tbl_retail_return_detail AS d ON d.return_id = r.id + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/sale/SaleOrderDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/sale/SaleOrderDetailMapper.xml new file mode 100644 index 0000000..d99e57a --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/sale/SaleOrderDetailMapper.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + SELECT + d.id, + d.order_id, + d.product_id, + d.order_num, + d.ori_price, + d.tax_price, + d.discount_rate, + d.is_gift, + d.tax_rate, + d.description, + d.order_no, + d.out_num + FROM tbl_sale_order_detail AS d + + + UPDATE tbl_sale_order_detail + SET out_num = out_num + #{num} + WHERE id = #{id} + AND (order_num - out_num) >= #{num} + + + UPDATE tbl_sale_order_detail + SET out_num = out_num - #{num} + WHERE id = #{id} + AND out_num >= #{num} + + + + diff --git a/xingyun-sc/src/main/resources/mappers/sale/SaleOrderMapper.xml b/xingyun-sc/src/main/resources/mappers/sale/SaleOrderMapper.xml new file mode 100644 index 0000000..8a06c63 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/sale/SaleOrderMapper.xml @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + o.id, + o.code, + o.sc_id, + o.customer_id, + o.saler_id, + o.total_num, + o.total_gift_num, + o.total_amount, + o.description, + o.create_by, + o.create_time, + o.update_by, + o.update_time, + o.approve_by, + o.approve_time, + o.status, + o.refuse_reason + FROM tbl_sale_order AS o + + + + SELECT + o.id, + o.code, + o.sc_id, + o.customer_id, + o.saler_id, + o.total_num, + o.total_gift_num, + o.total_amount, + o.description, + o.create_by, + o.create_by_id, + o.create_time, + o.update_by, + o.update_time, + o.approve_by, + o.approve_time, + o.status, + o.refuse_reason, + d.id AS detail_id, + b.main_product_id AS detail_main_product_id, + d.product_id AS detail_product_id, + d.order_num AS detail_order_num, + d.ori_price AS detail_ori_price, + d.tax_price AS detail_tax_price, + d.discount_rate AS detail_discount_rate, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no + FROM tbl_sale_order AS o + LEFT JOIN tbl_sale_order_detail AS d ON d.order_id = o.id + LEFT JOIN tbl_sale_order_detail_bundle AS b ON b.order_id = o.id AND b.product_detail_id = d.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit, + sale.price AS sale_price, + g.sale_tax_rate, + g.available + FROM base_data_product AS g + INNER JOIN base_data_product_sale AS sale ON sale.id = g.id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailLotMapper.xml b/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailLotMapper.xml new file mode 100644 index 0000000..359384a --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailLotMapper.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + SELECT + d.id, + d.detail_id, + d.order_num, + d.return_num, + d.cost_tax_amount, + d.settle_status, + d.order_no + FROM tbl_sale_out_sheet_detail_lot AS d + + + UPDATE tbl_sale_out_sheet_detail_lot + SET return_num = return_num + #{num} + WHERE id = #{id} + AND (order_num - return_num) >= #{num} + + + UPDATE tbl_sale_out_sheet_detail_lot + SET return_num = return_num - #{num} + WHERE id = #{id} + AND return_num >= #{num} + + + diff --git a/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailMapper.xml new file mode 100644 index 0000000..d21f766 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetDetailMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + SELECT + d.id, + d.sheet_id, + d.product_id, + d.order_num, + d.ori_price, + d.tax_price, + d.discount_rate, + d.is_gift, + d.tax_rate, + d.description, + d.order_no, + d.return_num + FROM tbl_sale_out_sheet_detail AS d + + + UPDATE tbl_sale_out_sheet_detail + SET return_num = return_num + #{num} + WHERE id = #{id} + AND (order_num - return_num) >= #{num} + + + UPDATE tbl_sale_out_sheet_detail + SET return_num = return_num - #{num} + WHERE id = #{id} + AND return_num >= #{num} + + + diff --git a/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetMapper.xml new file mode 100644 index 0000000..c7cc5ef --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/sale/SaleOutSheetMapper.xml @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + s.id, + s.code, + s.sc_id, + s.customer_id, + s.saler_id, + s.payment_date, + s.sale_order_id, + s.total_num, + s.total_gift_num, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.approve_by, + s.approve_time, + s.status, + s.settle_status + FROM tbl_sale_out_sheet AS s + LEFT JOIN tbl_sale_order AS o ON o.id = s.sale_order_id + + + + SELECT + s.id, + s.code, + s.sc_id, + s.customer_id, + s.saler_id, + s.payment_date, + s.sale_order_id, + s.total_num, + s.total_gift_num, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + b.main_product_id AS detail_main_product_id, + d.product_id AS detail_product_id, + d.order_num AS detail_order_num, + d.ori_price AS detail_ori_price, + d.tax_price AS detail_tax_price, + d.discount_rate AS detail_discount_rate, + d.is_gift AS detail_is_gift, + d.tax_rate AS detail_tax_rate, + d.description AS detail_description, + d.order_no AS detail_order_no, + d.settle_status AS detail_settle_status, + d.sale_order_detail_id AS detail_sale_order_detail_id + FROM tbl_sale_out_sheet AS s + LEFT JOIN tbl_sale_out_sheet_detail AS d ON d.sheet_id = s.id + LEFT JOIN tbl_sale_out_sheet_detail_bundle AS b ON b.sheet_id = s.id AND b.product_detail_id = d.id + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/sale/SaleReturnMapper.xml b/xingyun-sc/src/main/resources/mappers/sale/SaleReturnMapper.xml new file mode 100644 index 0000000..b7c3fc1 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/sale/SaleReturnMapper.xml @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + r.id, + r.code, + r.sc_id, + r.customer_id, + r.saler_id, + r.payment_date, + r.out_sheet_id, + r.total_num, + r.total_gift_num, + r.total_amount, + r.description, + r.create_by, + r.create_time, + r.approve_by, + r.approve_time, + r.status, + r.settle_status + FROM tbl_sale_return AS r + LEFT JOIN tbl_sale_out_sheet AS s ON s.id = r.out_sheet_id + + + + SELECT r.id, r.code, r.sc_id, r.customer_id, r.saler_id, r.payment_date, r.out_sheet_id, r.total_num, r.total_gift_num, + r.total_amount, r.description, r.create_by, r.create_time, r.update_by, r.update_time, r.approve_by, r.approve_time, + r.status, r.refuse_reason, r.settle_status, d.id AS detail_id, d.product_id AS detail_product_id, + d.return_num AS detail_return_num, d.ori_price AS detail_ori_price, d.tax_price AS detail_tax_price, d.discount_rate AS detail_discount_rate, + d.is_gift AS detail_is_gift, d.tax_rate AS detail_tax_rate, d.description AS detail_description, d.order_no AS detail_order_no, + d.settle_status AS detail_settle_status, d.out_sheet_detail_id AS detail_out_sheet_detail_id + FROM tbl_sale_return AS r + LEFT JOIN tbl_sale_return_detail AS d ON d.return_id = r.id + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/ProductStockLogMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/ProductStockLogMapper.xml new file mode 100644 index 0000000..fec1db1 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/ProductStockLogMapper.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + SELECT + gsl.id, + gsl.product_id, + gsl.sc_id, + gsl.ori_stock_num, + gsl.cur_stock_num, + gsl.ori_tax_price, + gsl.cur_tax_price, + gsl.stock_num, + gsl.tax_amount, + gsl.create_by, + gsl.create_time, + gsl.biz_id, + gsl.biz_code, + gsl.biz_detail_id, + gsl.biz_type + FROM tbl_product_stock_log AS gsl + INNER JOIN base_data_product AS g ON g.id = gsl.product_id AND g.product_type = 1 + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/ProductStockMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/ProductStockMapper.xml new file mode 100644 index 0000000..ce64730 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/ProductStockMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + SELECT + gs.id, + gs.product_id, + gs.sc_id, + gs.stock_num, + gs.tax_price, + gs.tax_amount + FROM tbl_product_stock AS gs + INNER JOIN base_data_product AS g ON g.id = gs.product_id AND g.product_type = 1 + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + + + + UPDATE tbl_product_stock + SET stock_num = stock_num + #{stockNum}, tax_amount = tax_amount + #{taxAmount} + ,tax_price = CASE WHEN stock_num = 0 THEN 0 ELSE tax_amount / stock_num END + WHERE product_id = #{productId} + AND sc_id = #{scId} + AND stock_num = #{oriStockNum} + AND tax_amount = #{oriTaxAmount} + + + UPDATE tbl_product_stock + SET stock_num = stock_num - #{stockNum}, tax_amount = tax_amount - #{taxAmount} + ,tax_price = CASE WHEN stock_num = 0 THEN tax_price ELSE tax_amount / stock_num END + WHERE product_id = #{productId} + AND sc_id = #{scId} + AND stock_num = #{oriStockNum} + AND tax_amount = #{oriTaxAmount} + AND stock_num >= #{stockNum} + + + UPDATE tbl_product_stock + SET tax_price = #{taxPrice}, tax_amount = tax_price * stock_num + WHERE product_id = #{productId} + AND sc_id = #{scId} + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustReasonMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustReasonMapper.xml new file mode 100644 index 0000000..b8a1626 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustReasonMapper.xml @@ -0,0 +1,44 @@ + + + + + + SELECT + tb.* + FROM tbl_stock_adjust_reason AS tb + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustSheetMapper.xml new file mode 100644 index 0000000..63b5e7b --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/adjust/StockAdjustSheetMapper.xml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.* + FROM tbl_stock_adjust_sheet AS tb + + + + SELECT + tb.id, + tb.code, + tb.sc_id, + tb.biz_type, + tb.reason_id, + tb.status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.approve_by, + tb.approve_time, + tb.refuse_reason, + tb.create_by_id, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.stock_num AS detail_stock_num, + d.description AS detail_description + FROM tbl_stock_adjust_sheet AS tb + LEFT JOIN tbl_stock_adjust_sheet_detail AS d ON d.sheet_id = tb.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit + FROM base_data_product AS g + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/adjust/StockCostAdjustSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/adjust/StockCostAdjustSheetMapper.xml new file mode 100644 index 0000000..d924b78 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/adjust/StockCostAdjustSheetMapper.xml @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.sc_id, + tb.product_num, + tb.diff_amount, + tb.status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.approve_by, + tb.approve_time, + tb.refuse_reason + FROM tbl_stock_cost_adjust_sheet AS tb + + + + SELECT + tb.id, + tb.code, + tb.sc_id, + tb.product_num, + tb.diff_amount, + tb.status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.approve_by, + tb.approve_time, + tb.refuse_reason, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.purchase_price AS detail_purchase_price, + d.stock_num AS detail_stock_num, + d.ori_price AS detail_ori_price, + d.price AS detail_price, + d.diff_amount AS detail_diff_amount, + d.description AS detail_description + FROM tbl_stock_cost_adjust_sheet AS tb + LEFT JOIN tbl_stock_cost_adjust_sheet_detail AS d ON d.sheet_id = tb.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit, + purchase.price AS purchase_price, + s.tax_price AS ori_price, + s.stock_num + FROM tbl_product_stock AS s + INNER JOIN base_data_product AS g ON g.id = s.product_id AND g.product_type = 1 + INNER JOIN base_data_product_purchase AS purchase ON purchase.id = g.id + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/take/PreTaskStockSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/take/PreTaskStockSheetMapper.xml new file mode 100644 index 0000000..e5172ca --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/take/PreTaskStockSheetMapper.xml @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.* + FROM tbl_pre_take_stock_sheet AS tb + + + + SELECT + tb.id, + tb.code, + tb.sc_id, + tb.take_status, + tb.description, + tb.update_by, + tb.update_time, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.first_num AS detail_first_num, + d.second_num AS detail_second_num, + d.rand_num AS detail_rand_num + FROM tbl_pre_take_stock_sheet AS tb + LEFT JOIN tbl_pre_take_stock_sheet_detail AS d ON d.sheet_id = tb.id + + + + SELECT + tb.id, + tb.code, + tb.sc_id, + tb.take_status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM tbl_pre_take_stock_sheet AS tb + + + + SELECT + tb.product_id, + tb.first_num, + tb.second_num, + tb.rand_num, + sh.take_status + FROM tbl_pre_take_stock_sheet_detail AS tb + LEFT JOIN tbl_pre_take_stock_sheet AS sh ON sh.id = tb.sheet_id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit + FROM base_data_product AS g + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockConfigMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockConfigMapper.xml new file mode 100644 index 0000000..8b73d9e --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockConfigMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanDetailMapper.xml new file mode 100644 index 0000000..991cb9d --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanDetailMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.product_id, + tb.stock_num + FROM tbl_take_stock_plan_detail AS tb + + + + SELECT + tb.id, + tb.product_id, + tb.stock_num, + tb.take_num, + tb.total_out_num, + tb.total_in_num, + tb.description, + tb.order_no + FROM tbl_take_stock_plan_detail AS tb + + + UPDATE tbl_take_stock_plan_detail SET total_in_num = total_in_num + #{num} + WHERE plan_id IN (SELECT id from tbl_take_stock_plan WHERE sc_id = #{scId} AND take_status = 0) AND product_id = #{productId} + + + UPDATE tbl_take_stock_plan_detail SET total_out_num = total_out_num + #{num} + WHERE plan_id IN (SELECT id from tbl_take_stock_plan WHERE sc_id = #{scId} AND take_status = 0) AND product_id = #{productId} + + + UPDATE tbl_take_stock_plan_detail set ori_take_num = IFNULL(ori_take_num, 0) + #{num} + WHERE plan_id = #{planId} AND product_id = #{productId} + + + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanMapper.xml new file mode 100644 index 0000000..79a96e9 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockPlanMapper.xml @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.* + FROM tbl_take_stock_plan AS tb + + + + SELECT + tb.product_id, + tb.stock_num, + tb.total_out_num, + tb.total_in_num + FROM tbl_take_stock_plan_detail AS tb + + + + SELECT + tb.id, + tb.code, + tb.sc_id, + tb.take_type, + tb.take_status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM tbl_take_stock_plan AS tb + + + + SELECT + tb.id, + tb.product_id, + tb.ori_take_num, + tb.take_num, + tb.stock_num, + tb.total_in_num, + tb.total_out_num, + tb.description + FROM tbl_take_stock_plan_detail AS tb + WHERE tb.plan_id = #{id} + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockSheetMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockSheetMapper.xml new file mode 100644 index 0000000..865efc0 --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/take/TakeStockSheetMapper.xml @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.plan_id, + tb.pre_sheet_id, + tb.sc_id, + tb.status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.approve_by, + tb.approve_time + FROM tbl_take_stock_sheet AS tb + LEFT JOIN tbl_take_stock_plan AS plan ON plan.id = tb.plan_id + + + + SELECT + tb.id, + tb.code, + tb.plan_id, + tb.pre_sheet_id, + tb.sc_id, + tb.status, + tb.description, + tb.refuse_reason, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.approve_by, + tb.approve_time, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.take_num AS detail_take_num, + d.description AS detail_description + FROM tbl_take_stock_sheet AS tb + LEFT JOIN tbl_take_stock_sheet_detail AS d ON d.sheet_id = tb.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit + FROM base_data_product AS g + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderDetailMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderDetailMapper.xml new file mode 100644 index 0000000..867239b --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderDetailMapper.xml @@ -0,0 +1,16 @@ + + + + + UPDATE tbl_sc_transfer_order_detail SET receive_num = receive_num + #{receiveNum} + WHERE order_id = #{orderId} + AND product_id = #{productId} + AND transfer_num - receive_num >= #{receiveNum} + + + + diff --git a/xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderMapper.xml b/xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderMapper.xml new file mode 100644 index 0000000..acd5c4b --- /dev/null +++ b/xingyun-sc/src/main/resources/mappers/stock/transfer/ScTransferOrderMapper.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.* + FROM tbl_sc_transfer_order AS tb + + + + SELECT + tb.id, + tb.code, + tb.source_sc_id, + tb.target_sc_id, + tb.total_num, + tb.total_amount, + tb.status, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.approve_by, + tb.approve_time, + tb.refuse_reason, + d.id AS detail_id, + d.product_id AS detail_product_id, + d.transfer_num AS detail_transfer_num, + d.receive_num AS detail_receive_num, + d.description AS detail_description + FROM tbl_sc_transfer_order AS tb + LEFT JOIN tbl_sc_transfer_order_detail AS d ON d.order_id = tb.id + + + + SELECT + g.id, + g.code, + g.name, + c.id AS category_id, + c.name AS category_name, + b.id AS brand_id, + b.name AS brand_name, + g.sku_code, + g.external_code, + g.spec, + g.unit + FROM tbl_product_stock AS ps + INNER JOIN base_data_product AS g ON g.id = ps.product_id AND g.product_type = 1 + LEFT JOIN base_data_product_category AS c ON c.id = g.category_id + LEFT JOIN base_data_product_brand AS b ON b.id = g.brand_id + LEFT JOIN recursion_mapping AS rm ON rm.node_id = c.id and rm.node_type = 2 + + + + + + + + + diff --git a/xingyun-sc/src/main/resources/print/purchase-order.ftl b/xingyun-sc/src/main/resources/print/purchase-order.ftl new file mode 100644 index 0000000..7258bd8 --- /dev/null +++ b/xingyun-sc/src/main/resources/print/purchase-order.ftl @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
采购订单
+
+
+
+ 供应商: +
+
+ ${supplierName!''} +
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 币种: +
+
+ R M B +
+
+
+
+ 类型: +
+
+ 采购 +
+
+
+
+
+
+ 采购员: +
+
+ ${purchaserName!''} +
+
+
+ + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 采购价 + + 采购数量 + + 采购金额 + + 仓库 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''}${detail.purchasePrice!''} + ${detail.purchaseNum!''} + ${detail.purchaseAmount!''} + ${scName!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 收货人签名: +
+
+ __________ +
+
+
+
+ 供应商签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/purchase-return.ftl b/xingyun-sc/src/main/resources/print/purchase-return.ftl new file mode 100644 index 0000000..30b5864 --- /dev/null +++ b/xingyun-sc/src/main/resources/print/purchase-return.ftl @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
采购退货单
+
+
+
+ 供应商: +
+
+ ${supplierName!''} +
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 仓库编号: +
+
+ ${scCode!''} +
+
+
+
+ 类型: +
+
+ 退货单 +
+
+
+
+
+
+ 收货单编号: +
+
+ ${receiveSheetCode!''} +
+
+
+
+ 采购员: +
+
+ ${purchaserName!''} +
+
+
+
+ 付款日期: +
+
+ ${paymentDate!''} +
+
+
+ + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 采购价 + + 退货数量 + + 退货金额 + + 仓库 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''}${detail.purchasePrice!''}${detail.returnNum!''}${detail.returnAmount!''}${scName!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 签收人签名: +
+
+ __________ +
+
+
+
+ 供应商签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/receive-sheet.ftl b/xingyun-sc/src/main/resources/print/receive-sheet.ftl new file mode 100644 index 0000000..d660db7 --- /dev/null +++ b/xingyun-sc/src/main/resources/print/receive-sheet.ftl @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
采购收货单
+
+
+
+ 供应商: +
+
+ ${supplierName!''} +
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 仓库编号: +
+
+ ${scCode!''} +
+
+
+
+ 类型: +
+
+ 收货单 +
+
+
+
+
+
+ 收货单编号: +
+
+ ${purchaseOrderCode!''} +
+
+
+
+ 采购员: +
+
+ ${purchaserName!''} +
+
+
+
+ 付款日期: +
+
+ ${paymentDate!''} +
+
+
+ + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 采购价 + + 收货数量 + + 收货金额 + + 仓库 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''}${detail.purchasePrice!''}${detail.receiveNum!''}${detail.receiveAmount!''}${scName!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 收货人签名: +
+
+ __________ +
+
+
+
+ 供应商签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/retail-out-sheet.ftl b/xingyun-sc/src/main/resources/print/retail-out-sheet.ftl new file mode 100644 index 0000000..dea44fa --- /dev/null +++ b/xingyun-sc/src/main/resources/print/retail-out-sheet.ftl @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
零售出库单
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 币种: +
+
+ R M B +
+
+
+
+ 类型: +
+
+ 出库单 +
+
+
+
+ +
+
+ 销售员: +
+
+ ${salerName!''} +
+
+
+
+ 付款日期: +
+
+ ${paymentDate!''} +
+
+
+ + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 价格 + + 出库数量 + + 出库金额 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''}${detail.taxPrice!''}${detail.outNum!''}${detail.outAmount!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 客户签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/retail-return.ftl b/xingyun-sc/src/main/resources/print/retail-return.ftl new file mode 100644 index 0000000..841a53d --- /dev/null +++ b/xingyun-sc/src/main/resources/print/retail-return.ftl @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
零售退货单
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 币种: +
+
+ R M B +
+
+
+
+ 类型: +
+
+ 退货单 +
+
+
+
+ +
+
+ 销售员: +
+
+ ${salerName!''} +
+
+
+
+ 付款日期: +
+
+ ${paymentDate!''} +
+
+
+ + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 供应商 + + 价格 + + 退货数量 + + 退货金额 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''} + ${detail.supplierName!''}${detail.taxPrice!''}${detail.returnNum!''}${detail.returnAmount!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 签收人签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/sale-order.ftl b/xingyun-sc/src/main/resources/print/sale-order.ftl new file mode 100644 index 0000000..6118a1d --- /dev/null +++ b/xingyun-sc/src/main/resources/print/sale-order.ftl @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
销售订单
+
+
+
+ 客户: +
+
+ ${customerName!''} +
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 币种: +
+
+ R M B +
+
+
+
+ 类型: +
+
+ 销售 +
+
+
+
+
+
+ 销售人: +
+
+ ${salerName!''} +
+
+
+ + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 价格 + + 销售数量 + + 销售金额 + + 仓库 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''}${detail.taxPrice!''}${detail.orderNum!''}${detail.orderAmount!''}${scName!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 发货人签名: +
+
+ __________ +
+
+
+
+ 客户签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/sale-out-sheet.ftl b/xingyun-sc/src/main/resources/print/sale-out-sheet.ftl new file mode 100644 index 0000000..e1a1409 --- /dev/null +++ b/xingyun-sc/src/main/resources/print/sale-out-sheet.ftl @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
销售出库单
+
+
+
+ 客户: +
+
+ ${customerName!''} +
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 币种: +
+
+ R M B +
+
+
+
+ 类型: +
+
+ 出库单 +
+
+
+
+
+
+ 销售订单号: +
+
+ ${saleOrderCode!''} +
+
+
+
+ 销售员: +
+
+ ${salerName!''} +
+
+
+
+ 付款日期: +
+
+ ${paymentDate!''} +
+
+
+ + + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 价格 + + 出库数量 + + 出库金额 + + 仓库 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''}${detail.taxPrice!''}${detail.outNum!''}${detail.outAmount!''}${scName!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 出库人签名: +
+
+ __________ +
+
+
+
+ 客户签名: +
+
+ __________ +
+
+
+ + + \ No newline at end of file diff --git a/xingyun-sc/src/main/resources/print/sale-return.ftl b/xingyun-sc/src/main/resources/print/sale-return.ftl new file mode 100644 index 0000000..c836e69 --- /dev/null +++ b/xingyun-sc/src/main/resources/print/sale-return.ftl @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + +
算窗
+
销售退货单
+
+
+
+ 客户: +
+
+ ${customerName!''} +
+
+
+
+ 单据日期: +
+
+ ${createTime!''} +
+
+
+
+ 单据编号: +
+
+ ${code!''} +
+
+
+
+ 币种: +
+
+ R M B +
+
+
+
+ 类型: +
+
+ 退货单 +
+
+
+
+
+
+ 销售员: +
+
+ ${salerName!''} +
+
+
+
+ 付款日期: +
+
+ ${paymentDate!''} +
+
+
+ + + + + + + + + + + + <#if details??> + <#list details as detail> + + + + + + + + + + + + + + + + + + + + + + + + +
+ 商品编号 + + 商品名称 + + 商品SKU编号 + + 商品外部编号 + + 供应商 + + 价格 + + 退货数量 + + 退货金额 + + 仓库 +
+ ${detail.productCode!''} + ${detail.productName!''} + ${detail.skuCode!''} + ${detail.externalCode!''} + ${detail.supplierName!''}${detail.taxPrice!''}${detail.returnNum!''}${detail.returnAmount!''}${scName!''}
+ 合计数量 + ${totalNum!''} + 合计金额 + ${totalAmount!''}
+ 合计 大写金额: ${bigTotalAmount!''} +
+
+
+
+ 备注: +
+
+ ${description!''} +
+
+
+
+
+
+ 制单人: +
+
+ ${createBy!''} +
+
+
+
+ 签收人签名: +
+
+ __________ +
+
+ +
+ + + \ No newline at end of file diff --git a/xingyun-settle/pom.xml b/xingyun-settle/pom.xml new file mode 100644 index 0000000..44e5562 --- /dev/null +++ b/xingyun-settle/pom.xml @@ -0,0 +1,26 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-settle + 【${project.artifactId}】结算服务层 + + + + com.lframework + xingyun-core + + + + com.lframework + xingyun-sc + + + diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/GetSettleCheckSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/GetSettleCheckSheetBo.java new file mode 100644 index 0000000..73df52b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/GetSettleCheckSheetBo.java @@ -0,0 +1,277 @@ +package com.lframework.xingyun.settle.bo.check; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.dto.check.SettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.SettleCheckSheetFullDto; +import com.lframework.xingyun.settle.service.SettleCheckSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSettleCheckSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付金额 + */ + @ApiModelProperty("未付金额") + private BigDecimal totalUnPayAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetSettleCheckSheetBo() { + + } + + public GetSettleCheckSheetBo(SettleCheckSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleCheckSheetFullDto dto) { + + return super.convert(dto, GetSettleCheckSheetBo::getStatus, GetSettleCheckSheetBo::getDetails); + } + + @Override + protected void afterInit(SettleCheckSheetFullDto dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + + this.totalUnPayAmount = NumberUtil.sub(dto.getTotalPayAmount(), dto.getTotalPayedAmount(), + dto.getTotalDiscountAmount()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(SheetDetailBo::new).collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String bizId; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + /** + * 计算类型 + */ + @ApiModelProperty("计算类型") + private Integer calcType; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 单据金额 + */ + @ApiModelProperty("单据金额") + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal payAmount; + + /** + * 单据备注 + */ + @ApiModelProperty("单据备注") + private String description; + + public SheetDetailBo() { + + } + + public SheetDetailBo(SettleCheckSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + public
BaseBo convert(SettleCheckSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto, SettleCheckSheetFullDto.SheetDetailDto::getBizType, + SettleCheckSheetFullDto.SheetDetailDto::getCalcType); + } + + @Override + protected void afterInit(SettleCheckSheetFullDto.SheetDetailDto dto) { + + SettleCheckSheetService settleCheckSheetService = ApplicationUtil.getBean( + SettleCheckSheetService.class); + SettleCheckBizItemDto item = settleCheckSheetService.getBizItem(dto.getBizId(), dto.getBizType()); + this.bizCode = item.getCode(); + this.approveTime = item.getApproveTime(); + this.bizType = dto.getBizType().getCode(); + this.totalAmount = item.getTotalAmount(); + this.calcType = dto.getCalcType().getCode(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/QuerySettleCheckSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/QuerySettleCheckSheetBo.java new file mode 100644 index 0000000..95fffd8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/QuerySettleCheckSheetBo.java @@ -0,0 +1,178 @@ +package com.lframework.xingyun.settle.bo.check; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleCheckSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付金额 + */ + @ApiModelProperty("未付金额") + private BigDecimal totalUnPayAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QuerySettleCheckSheetBo() { + + } + + public QuerySettleCheckSheetBo(SettleCheckSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleCheckSheet dto) { + + return super.convert(dto, QuerySettleCheckSheetBo::getStatus, QuerySettleCheckSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(SettleCheckSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalUnPayAmount = NumberUtil.sub(dto.getTotalPayAmount(), dto.getTotalPayedAmount(), + dto.getTotalDiscountAmount()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/SettleCheckBizItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/SettleCheckBizItemBo.java new file mode 100644 index 0000000..461315b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/SettleCheckBizItemBo.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.settle.bo.check; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.dto.check.SettleCheckBizItemDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class SettleCheckBizItemBo extends BaseBo { + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String code; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + /** + * 计算类型 + */ + @ApiModelProperty("计算类型") + private Integer calcType; + + /** + * 对账金额 + */ + @ApiModelProperty("对账金额") + private BigDecimal totalAmount; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public SettleCheckBizItemBo() { + + } + + public SettleCheckBizItemBo(SettleCheckBizItemDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleCheckBizItemDto dto) { + + return super.convert(dto, SettleCheckBizItemBo::getBizType, SettleCheckBizItemBo::getCalcType); + } + + @Override + protected void afterInit(SettleCheckBizItemDto dto) { + + this.bizType = dto.getBizType().getCode(); + this.calcType = dto.getCalcType().getCode(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/CustomerSettleCheckBizItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/CustomerSettleCheckBizItemBo.java new file mode 100644 index 0000000..7085896 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/CustomerSettleCheckBizItemBo.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.settle.bo.check.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckBizItemDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class CustomerSettleCheckBizItemBo extends BaseBo { + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String code; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + /** + * 计算类型 + */ + @ApiModelProperty("计算类型") + private Integer calcType; + + /** + * 对账金额 + */ + @ApiModelProperty("对账金额") + private BigDecimal totalAmount; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public CustomerSettleCheckBizItemBo() { + + } + + public CustomerSettleCheckBizItemBo(CustomerSettleCheckBizItemDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleCheckBizItemDto dto) { + + return super.convert(dto, CustomerSettleCheckBizItemBo::getBizType, + CustomerSettleCheckBizItemBo::getCalcType); + } + + @Override + protected void afterInit(CustomerSettleCheckBizItemDto dto) { + + this.bizType = dto.getBizType().getCode(); + this.calcType = dto.getCalcType().getCode(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/GetCustomerSettleCheckSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/GetCustomerSettleCheckSheetBo.java new file mode 100644 index 0000000..1db0c5e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/GetCustomerSettleCheckSheetBo.java @@ -0,0 +1,282 @@ +package com.lframework.xingyun.settle.bo.check.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckSheetFullDto; +import com.lframework.xingyun.settle.service.CustomerSettleCheckSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetCustomerSettleCheckSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付金额 + */ + @ApiModelProperty("未付金额") + private BigDecimal totalUnPayAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetCustomerSettleCheckSheetBo() { + + } + + public GetCustomerSettleCheckSheetBo(CustomerSettleCheckSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleCheckSheetFullDto dto) { + + return super.convert(dto, GetCustomerSettleCheckSheetBo::getStatus, + GetCustomerSettleCheckSheetBo::getDetails); + } + + @Override + protected void afterInit(CustomerSettleCheckSheetFullDto dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.status = dto.getStatus().getCode(); + + this.totalUnPayAmount = NumberUtil.sub(dto.getTotalPayAmount(), dto.getTotalPayedAmount(), + dto.getTotalDiscountAmount()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(SheetDetailBo::new) + .collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends + BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String bizId; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String bizCode; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + private Integer bizType; + + /** + * 计算类型 + */ + @ApiModelProperty("计算类型") + private Integer calcType; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 单据金额 + */ + @ApiModelProperty("单据金额") + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal payAmount; + + /** + * 单据备注 + */ + @ApiModelProperty("单据备注") + private String description; + + public SheetDetailBo() { + + } + + public SheetDetailBo(CustomerSettleCheckSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + CustomerSettleCheckSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto, CustomerSettleCheckSheetFullDto.SheetDetailDto::getBizType, + CustomerSettleCheckSheetFullDto.SheetDetailDto::getCalcType); + } + + @Override + protected void afterInit(CustomerSettleCheckSheetFullDto.SheetDetailDto dto) { + + CustomerSettleCheckSheetService settleCheckSheetService = ApplicationUtil.getBean( + CustomerSettleCheckSheetService.class); + CustomerSettleCheckBizItemDto item = settleCheckSheetService.getBizItem(dto.getBizId(), + dto.getBizType()); + this.bizCode = item.getCode(); + this.approveTime = item.getApproveTime(); + this.bizType = dto.getBizType().getCode(); + this.totalAmount = item.getTotalAmount(); + this.calcType = dto.getCalcType().getCode(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/QueryCustomerSettleCheckSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/QueryCustomerSettleCheckSheetBo.java new file mode 100644 index 0000000..99cbc8d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/check/customer/QueryCustomerSettleCheckSheetBo.java @@ -0,0 +1,179 @@ +package com.lframework.xingyun.settle.bo.check.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettleCheckSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付金额 + */ + @ApiModelProperty("未付金额") + private BigDecimal totalUnPayAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryCustomerSettleCheckSheetBo() { + + } + + public QueryCustomerSettleCheckSheetBo(CustomerSettleCheckSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleCheckSheet dto) { + + return super.convert(dto, QueryCustomerSettleCheckSheetBo::getStatus, + QueryCustomerSettleCheckSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(CustomerSettleCheckSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + this.totalUnPayAmount = NumberUtil.sub(dto.getTotalPayAmount(), dto.getTotalPayedAmount(), + dto.getTotalDiscountAmount()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/GetSettleFeeSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/GetSettleFeeSheetBo.java new file mode 100644 index 0000000..541d16e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/GetSettleFeeSheetBo.java @@ -0,0 +1,209 @@ +package com.lframework.xingyun.settle.bo.fee; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.dto.fee.SettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.enums.SettleFeeSheetType; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSettleFeeSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 单据类型 + */ + @ApiModelProperty("单据类型") + private Integer sheetType; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + private List details; + + public GetSettleFeeSheetBo() { + + } + + public GetSettleFeeSheetBo(SettleFeeSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleFeeSheetFullDto dto) { + + return super.convert(dto, GetSettleFeeSheetBo::getSheetType, GetSettleFeeSheetBo::getStatus, + GetSettleFeeSheetBo::getDetails); + } + + @Override + protected void afterInit(SettleFeeSheetFullDto dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.sheetType = dto.getSheetType().getCode(); + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new SheetDetailBo(t, dto.getSheetType())) + .collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String itemId; + + /** + * 项目名称 + */ + @ApiModelProperty("项目名称") + private String itemName; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; + + @JsonIgnore + private SettleFeeSheetType sheetType; + + public SheetDetailBo(SettleFeeSheetFullDto.SheetDetailDto dto, SettleFeeSheetType sheetType) { + + this.sheetType = sheetType; + + this.init(dto); + } + + @Override + protected void afterInit(SettleFeeSheetFullDto.SheetDetailDto dto) { + + if (this.sheetType == SettleFeeSheetType.RECEIVE) { + SettleInItemService settleInItemService = ApplicationUtil.getBean( + SettleInItemService.class); + SettleInItem item = settleInItemService.findById(dto.getItemId()); + this.itemName = item.getName(); + } else { + SettleOutItemService settleOutItemService = ApplicationUtil.getBean( + SettleOutItemService.class); + SettleOutItem item = settleOutItemService.findById(dto.getItemId()); + this.itemName = item.getName(); + } + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/QuerySettleFeeSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/QuerySettleFeeSheetBo.java new file mode 100644 index 0000000..c8e8ebc --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/QuerySettleFeeSheetBo.java @@ -0,0 +1,140 @@ +package com.lframework.xingyun.settle.bo.fee; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleFeeSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 单据类型 + */ + @ApiModelProperty("单据类型") + private Integer sheetType; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QuerySettleFeeSheetBo() { + + } + + public QuerySettleFeeSheetBo(SettleFeeSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleFeeSheet dto) { + + return super.convert(dto, QuerySettleFeeSheetBo::getSheetType, QuerySettleFeeSheetBo::getStatus, + QuerySettleFeeSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(SettleFeeSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.sheetType = dto.getSheetType().getCode(); + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/GetCustomerSettleFeeSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/GetCustomerSettleFeeSheetBo.java new file mode 100644 index 0000000..ded7d00 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/GetCustomerSettleFeeSheetBo.java @@ -0,0 +1,212 @@ +package com.lframework.xingyun.settle.bo.fee.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.dto.fee.customer.CustomerSettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetType; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetCustomerSettleFeeSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 单据类型 + */ + @ApiModelProperty("单据类型") + private Integer sheetType; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetCustomerSettleFeeSheetBo() { + + } + + public GetCustomerSettleFeeSheetBo(CustomerSettleFeeSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleFeeSheetFullDto dto) { + + return super.convert(dto, GetCustomerSettleFeeSheetBo::getSheetType, + GetCustomerSettleFeeSheetBo::getStatus, + GetCustomerSettleFeeSheetBo::getDetails); + } + + @Override + protected void afterInit(CustomerSettleFeeSheetFullDto dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.sheetType = dto.getSheetType().getCode(); + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(t -> new SheetDetailBo(t, dto.getSheetType())) + .collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String itemId; + + /** + * 项目名称 + */ + @ApiModelProperty("项目名称") + private String itemName; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; + + @JsonIgnore + private CustomerSettleFeeSheetType sheetType; + + public SheetDetailBo(CustomerSettleFeeSheetFullDto.SheetDetailDto dto, + CustomerSettleFeeSheetType sheetType) { + + this.sheetType = sheetType; + + this.init(dto); + } + + @Override + protected void afterInit(CustomerSettleFeeSheetFullDto.SheetDetailDto dto) { + + if (this.sheetType == CustomerSettleFeeSheetType.RECEIVE) { + SettleInItemService settleInItemService = ApplicationUtil.getBean( + SettleInItemService.class); + SettleInItem item = settleInItemService.findById(dto.getItemId()); + this.itemName = item.getName(); + } else { + SettleOutItemService settleOutItemService = ApplicationUtil.getBean( + SettleOutItemService.class); + SettleOutItem item = settleOutItemService.findById(dto.getItemId()); + this.itemName = item.getName(); + } + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/QueryCustomerSettleFeeSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/QueryCustomerSettleFeeSheetBo.java new file mode 100644 index 0000000..4aba376 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/fee/customer/QueryCustomerSettleFeeSheetBo.java @@ -0,0 +1,141 @@ +package com.lframework.xingyun.settle.bo.fee.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettleFeeSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 单据类型 + */ + @ApiModelProperty("单据类型") + private Integer sheetType; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryCustomerSettleFeeSheetBo() { + + } + + public QueryCustomerSettleFeeSheetBo(CustomerSettleFeeSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleFeeSheet dto) { + + return super.convert(dto, QueryCustomerSettleFeeSheetBo::getSheetType, + QueryCustomerSettleFeeSheetBo::getStatus, + QueryCustomerSettleFeeSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(CustomerSettleFeeSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.sheetType = dto.getSheetType().getCode(); + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/GetSettleInItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/GetSettleInItemBo.java new file mode 100644 index 0000000..919c9a5 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/GetSettleInItemBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.bo.item.in; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.entity.SettleInItem; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSettleInItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSettleInItemBo() { + + } + + public GetSettleInItemBo(SettleInItem dto) { + + super(dto); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/QuerySettleInItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/QuerySettleInItemBo.java new file mode 100644 index 0000000..2a03b0b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/QuerySettleInItemBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.settle.bo.item.in; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.entity.SettleInItem; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleInItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySettleInItemBo() { + + } + + public QuerySettleInItemBo(SettleInItem dto) { + + super(dto); + } + + @Override + protected void afterInit(SettleInItem dto) { + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/SettleInItemSelectorBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/SettleInItemSelectorBo.java new file mode 100644 index 0000000..144e2de --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/in/SettleInItemSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.settle.bo.item.in; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.entity.SettleInItem; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SettleInItemSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SettleInItemSelectorBo() { + + } + + public SettleInItemSelectorBo(SettleInItem dto) { + + super(dto); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/GetSettleOutItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/GetSettleOutItemBo.java new file mode 100644 index 0000000..403be51 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/GetSettleOutItemBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.bo.item.out; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSettleOutItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSettleOutItemBo() { + + } + + public GetSettleOutItemBo(SettleOutItem dto) { + + super(dto); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/QuerySettleOutItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/QuerySettleOutItemBo.java new file mode 100644 index 0000000..1811fd7 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/QuerySettleOutItemBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.settle.bo.item.out; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleOutItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySettleOutItemBo() { + + } + + public QuerySettleOutItemBo(SettleOutItem dto) { + + super(dto); + } + + @Override + protected void afterInit(SettleOutItem dto) { + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/SettleOutItemSelectorBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/SettleOutItemSelectorBo.java new file mode 100644 index 0000000..21219bf --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/item/out/SettleOutItemSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.settle.bo.item.out; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SettleOutItemSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SettleOutItemSelectorBo() { + + } + + public SettleOutItemSelectorBo(SettleOutItem dto) { + + super(dto); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/GetSettlePreSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/GetSettlePreSheetBo.java new file mode 100644 index 0000000..d73e3a9 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/GetSettlePreSheetBo.java @@ -0,0 +1,189 @@ +package com.lframework.xingyun.settle.bo.pre; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.dto.pre.SettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSettlePreSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetSettlePreSheetBo() { + + } + + public GetSettlePreSheetBo(SettlePreSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettlePreSheetFullDto dto) { + + return super.convert(dto, GetSettlePreSheetBo::getStatus, GetSettlePreSheetBo::getDetails); + } + + @Override + protected void afterInit(SettlePreSheetFullDto dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(SheetDetailBo::new).collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String itemId; + + /** + * 项目名称 + */ + @ApiModelProperty("项目名称") + private String itemName; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; + + public SheetDetailBo() { + + } + + public SheetDetailBo(SettlePreSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + protected void afterInit(SettlePreSheetFullDto.SheetDetailDto dto) { + + SettleOutItemService settleOutItemService = ApplicationUtil.getBean( + SettleOutItemService.class); + SettleOutItem item = settleOutItemService.findById(dto.getItemId()); + this.itemName = item.getName(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/QuerySettlePreSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/QuerySettlePreSheetBo.java new file mode 100644 index 0000000..e598720 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/QuerySettlePreSheetBo.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.settle.bo.pre; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettlePreSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QuerySettlePreSheetBo() { + + } + + public QuerySettlePreSheetBo(SettlePreSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettlePreSheet dto) { + + return super.convert(dto, QuerySettlePreSheetBo::getStatus, QuerySettlePreSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(SettlePreSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/GetCustomerSettlePreSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/GetCustomerSettlePreSheetBo.java new file mode 100644 index 0000000..7b630a9 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/GetCustomerSettlePreSheetBo.java @@ -0,0 +1,191 @@ +package com.lframework.xingyun.settle.bo.pre.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.dto.pre.customer.CustomerSettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.service.SettleInItemService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetCustomerSettlePreSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetCustomerSettlePreSheetBo() { + + } + + public GetCustomerSettlePreSheetBo(CustomerSettlePreSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettlePreSheetFullDto dto) { + + return super.convert(dto, GetCustomerSettlePreSheetBo::getStatus, + GetCustomerSettlePreSheetBo::getDetails); + } + + @Override + protected void afterInit(CustomerSettlePreSheetFullDto dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(SheetDetailBo::new) + .collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String itemId; + + /** + * 项目名称 + */ + @ApiModelProperty("项目名称") + private String itemName; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; + + public SheetDetailBo() { + + } + + public SheetDetailBo(CustomerSettlePreSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + protected void afterInit(CustomerSettlePreSheetFullDto.SheetDetailDto dto) { + + SettleInItemService settleInItemService = ApplicationUtil.getBean( + SettleInItemService.class); + SettleInItem item = settleInItemService.findById(dto.getItemId()); + this.itemName = item.getName(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/QueryCustomerSettlePreSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/QueryCustomerSettlePreSheetBo.java new file mode 100644 index 0000000..b7db261 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/pre/customer/QueryCustomerSettlePreSheetBo.java @@ -0,0 +1,133 @@ +package com.lframework.xingyun.settle.bo.pre.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettlePreSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + private Integer settleStatus; + + public QueryCustomerSettlePreSheetBo() { + + } + + public QueryCustomerSettlePreSheetBo(CustomerSettlePreSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettlePreSheet dto) { + + return super.convert(dto, QueryCustomerSettlePreSheetBo::getStatus, + QueryCustomerSettlePreSheetBo::getSettleStatus); + } + + @Override + protected void afterInit(CustomerSettlePreSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.status = dto.getStatus().getCode(); + this.settleStatus = dto.getSettleStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/GetSettleSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/GetSettleSheetBo.java new file mode 100644 index 0000000..f5aaaf4 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/GetSettleSheetBo.java @@ -0,0 +1,266 @@ +package com.lframework.xingyun.settle.bo.sheet; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.dto.sheet.SettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.SettleSheetFullDto; +import com.lframework.xingyun.settle.service.SettleSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSettleSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetSettleSheetBo() { + + } + + public GetSettleSheetBo(SettleSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleSheetFullDto dto) { + + return super.convert(dto, GetSettleSheetBo::getStatus, GetSettleSheetBo::getDetails); + } + + @Override + protected void afterInit(SettleSheetFullDto dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(SheetDetailBo::new).collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String bizId; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String bizCode; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + @ApiModelProperty("已优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付金额 + */ + @ApiModelProperty("未付金额") + private BigDecimal totalUnPayAmount; + + /** + * 实付金额 + */ + @ApiModelProperty("实付金额") + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal discountAmount; + + /** + * 单据备注 + */ + @ApiModelProperty("单据备注") + private String description; + + public SheetDetailBo() { + + } + + public SheetDetailBo(SettleSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SettleSheetFullDto.SheetDetailDto dto) { + + SettleSheetService settleSheetService = ApplicationUtil.getBean(SettleSheetService.class); + SettleBizItemDto item = settleSheetService.getBizItem(dto.getBizId()); + this.bizCode = item.getCode(); + this.approveTime = item.getApproveTime(); + this.totalPayAmount = item.getTotalPayAmount(); + this.totalPayedAmount = item.getTotalPayedAmount(); + this.totalDiscountAmount = item.getTotalDiscountAmount(); + this.totalUnPayAmount = item.getTotalUnPayAmount(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/QuerySettleSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/QuerySettleSheetBo.java new file mode 100644 index 0000000..86758c4 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/QuerySettleSheetBo.java @@ -0,0 +1,149 @@ +package com.lframework.xingyun.settle.bo.sheet; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.entity.SettleSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 供应商编号 + */ + @ApiModelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ApiModelProperty("供应商名称") + private String supplierName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + public QuerySettleSheetBo() { + + } + + public QuerySettleSheetBo(SettleSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleSheet dto) { + + return super.convert(dto, QuerySettleSheetBo::getStatus); + } + + @Override + protected void afterInit(SettleSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + this.supplierCode = supplier.getCode(); + this.supplierName = supplier.getName(); + + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/SettleBizItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/SettleBizItemBo.java new file mode 100644 index 0000000..699384f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/SettleBizItemBo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.bo.sheet; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.dto.sheet.SettleBizItemDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class SettleBizItemBo extends BaseBo { + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String code; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + @ApiModelProperty("已优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付款金额 + */ + @ApiModelProperty("未付款金额") + private BigDecimal totalUnPayAmount; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public SettleBizItemBo() { + + } + + public SettleBizItemBo(SettleBizItemDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleBizItemDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(SettleBizItemDto dto) { + + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/CustomerSettleBizItemBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/CustomerSettleBizItemBo.java new file mode 100644 index 0000000..ff43257 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/CustomerSettleBizItemBo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.bo.sheet.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleBizItemDto; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class CustomerSettleBizItemBo extends BaseBo { + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String code; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + @ApiModelProperty("已优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付款金额 + */ + @ApiModelProperty("未付款金额") + private BigDecimal totalUnPayAmount; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + public CustomerSettleBizItemBo() { + + } + + public CustomerSettleBizItemBo(CustomerSettleBizItemDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleBizItemDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(CustomerSettleBizItemDto dto) { + + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/GetCustomerSettleSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/GetCustomerSettleSheetBo.java new file mode 100644 index 0000000..7928ebe --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/GetCustomerSettleSheetBo.java @@ -0,0 +1,270 @@ +package com.lframework.xingyun.settle.bo.sheet.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleSheetFullDto; +import com.lframework.xingyun.settle.service.CustomerSettleSheetService; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetCustomerSettleSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + /** + * 拒绝原因 + */ + @ApiModelProperty("拒绝原因") + private String refuseReason; + + @ApiModelProperty("明细") + private List details; + + public GetCustomerSettleSheetBo() { + + } + + public GetCustomerSettleSheetBo(CustomerSettleSheetFullDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleSheetFullDto dto) { + + return super.convert(dto, GetCustomerSettleSheetBo::getStatus, + GetCustomerSettleSheetBo::getDetails); + } + + @Override + protected void afterInit(CustomerSettleSheetFullDto dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + + if (!CollectionUtil.isEmpty(dto.getDetails())) { + this.details = dto.getDetails().stream().map(SheetDetailBo::new) + .collect(Collectors.toList()); + } + } + + @Data + public static class SheetDetailBo extends BaseBo { + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private String id; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String bizId; + + /** + * 单据号 + */ + @ApiModelProperty("单据号") + private String bizCode; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + @ApiModelProperty("已付金额") + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + @ApiModelProperty("已优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付金额 + */ + @ApiModelProperty("未付金额") + private BigDecimal totalUnPayAmount; + + /** + * 实付金额 + */ + @ApiModelProperty("实付金额") + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal discountAmount; + + /** + * 单据备注 + */ + @ApiModelProperty("单据备注") + private String description; + + public SheetDetailBo() { + + } + + public SheetDetailBo(CustomerSettleSheetFullDto.SheetDetailDto dto) { + + super(dto); + } + + @Override + public BaseBo convert( + CustomerSettleSheetFullDto.SheetDetailDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(CustomerSettleSheetFullDto.SheetDetailDto dto) { + + CustomerSettleSheetService settleSheetService = ApplicationUtil.getBean( + CustomerSettleSheetService.class); + CustomerSettleBizItemDto item = settleSheetService.getBizItem(dto.getBizId()); + this.bizCode = item.getCode(); + this.approveTime = item.getApproveTime(); + this.totalPayAmount = item.getTotalPayAmount(); + this.totalPayedAmount = item.getTotalPayedAmount(); + this.totalDiscountAmount = item.getTotalDiscountAmount(); + this.totalUnPayAmount = item.getTotalUnPayAmount(); + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/QueryCustomerSettleSheetBo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/QueryCustomerSettleSheetBo.java new file mode 100644 index 0000000..85d56d8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/bo/sheet/customer/QueryCustomerSettleSheetBo.java @@ -0,0 +1,149 @@ +package com.lframework.xingyun.settle.bo.sheet.customer; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.entity.CustomerSettleSheet; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettleSheetBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 单号 + */ + @ApiModelProperty("单号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime startTime; + + /** + * 截止时间 + */ + @ApiModelProperty("截止时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime endTime; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核时间 + */ + @ApiModelProperty("审核时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime approveTime; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Integer status; + + public QueryCustomerSettleSheetBo() { + + } + + public QueryCustomerSettleSheetBo(CustomerSettleSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleSheet dto) { + + return super.convert(dto, QueryCustomerSettleSheetBo::getStatus); + } + + @Override + protected void afterInit(CustomerSettleSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + this.customerCode = customer.getCode(); + this.customerName = customer.getName(); + + this.status = dto.getStatus().getCode(); + + UserService userService = ApplicationUtil.getBean(UserService.class); + + if (!StringUtil.isBlank(dto.getApproveBy())) { + this.approveBy = userService.findById(dto.getApproveBy()).getName(); + } + + this.startTime = DateUtil.toLocalDateTime(dto.getStartDate()); + this.endTime = DateUtil.toLocalDateTimeMax(dto.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/components/code/GenerateCodeTypePool.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/components/code/GenerateCodeTypePool.java new file mode 100644 index 0000000..5fd6003 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/components/code/GenerateCodeTypePool.java @@ -0,0 +1,46 @@ +package com.lframework.xingyun.settle.components.code; + +import com.lframework.starter.web.components.code.GenerateCodeType; + +public interface GenerateCodeTypePool { + + /** + * 对账单 + */ + GenerateCodeType SETTLE_CHECK_SHEET = GenerateCodeType.FLOW; + + /** + * 费用单 + */ + GenerateCodeType SETTLE_FEE_SHEET = GenerateCodeType.FLOW; + + /** + * 预付款单 + */ + GenerateCodeType SETTLE_PRE_SHEET = GenerateCodeType.FLOW; + + /** + * 结算单 + */ + GenerateCodeType SETTLE_SHEET = GenerateCodeType.FLOW; + + /** + * 客户对账单 + */ + GenerateCodeType CUSTOMER_SETTLE_CHECK_SHEET = GenerateCodeType.FLOW; + + /** + * 客户费用单 + */ + GenerateCodeType CUSTOMER_SETTLE_FEE_SHEET = GenerateCodeType.FLOW; + + /** + * 客户预付款单 + */ + GenerateCodeType CUSTOMER_SETTLE_PRE_SHEET = GenerateCodeType.FLOW; + + /** + * 客户结算单 + */ + GenerateCodeType CUSTOMER_SETTLE_SHEET = GenerateCodeType.FLOW; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleCheckSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleCheckSheetController.java new file mode 100644 index 0000000..1934555 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleCheckSheetController.java @@ -0,0 +1,281 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.check.customer.CustomerSettleCheckBizItemBo; +import com.lframework.xingyun.settle.bo.check.customer.GetCustomerSettleCheckSheetBo; +import com.lframework.xingyun.settle.bo.check.customer.QueryCustomerSettleCheckSheetBo; +import com.lframework.xingyun.settle.excel.check.customer.CustomerSettleCheckSheetExportModel; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import com.lframework.xingyun.settle.service.CustomerSettleCheckSheetService; +import com.lframework.xingyun.settle.vo.check.customer.ApprovePassCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.ApproveRefuseCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.BatchApprovePassCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.BatchApproveRefuseCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.CreateCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerUnCheckBizItemVo; +import com.lframework.xingyun.settle.vo.check.customer.UpdateCustomerSettleCheckSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 客户对账单 + * + * @author zmj + */ +@Api(tags = "客户对账单") +@Validated +@RestController +@RequestMapping("/customer/settle/checksheet") +public class CustomerSettleCheckSheetController extends DefaultBaseController { + + @Autowired + private CustomerSettleCheckSheetService customerSettleCheckSheetService; + + /** + * 客户对账单列表 + */ + @ApiOperation("客户对账单列表") + @HasPermission({"customer-settle:check-sheet:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryCustomerSettleCheckSheetVo vo) { + + PageResult pageResult = customerSettleCheckSheetService.query( + getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryCustomerSettleCheckSheetBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"customer-settle:check-sheet:export"}) + @PostMapping("/export") + public void export(@Valid QueryCustomerSettleCheckSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("客户对账单信息", + CustomerSettleCheckSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = customerSettleCheckSheetService.query( + pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(CustomerSettleCheckSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:check-sheet:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "客户对账单ID不能为空!") String id) { + + CustomerSettleCheckSheetFullDto data = customerSettleCheckSheetService.getDetail(id); + + GetCustomerSettleCheckSheetBo result = new GetCustomerSettleCheckSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建客户对账单 + */ + @ApiOperation("创建客户对账单") + @HasPermission({"customer-settle:check-sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateCustomerSettleCheckSheetVo vo) { + + vo.validate(); + + String id = customerSettleCheckSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改客户对账单 + */ + @ApiOperation("修改客户对账单") + @HasPermission({"customer-settle:check-sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateCustomerSettleCheckSheetVo vo) { + + vo.validate(); + + customerSettleCheckSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过客户对账单 + */ + @ApiOperation("审核通过客户对账单") + @HasPermission({"customer-settle:check-sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass( + @RequestBody @Valid ApprovePassCustomerSettleCheckSheetVo vo) { + + customerSettleCheckSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过客户对账单 + */ + @ApiOperation("批量审核通过客户对账单") + @HasPermission({"customer-settle:check-sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassCustomerSettleCheckSheetVo vo) { + + customerSettleCheckSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过客户对账单 + */ + @ApiOperation("直接审核通过客户对账单") + @HasPermission({"customer-settle:check-sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass( + @RequestBody @Valid CreateCustomerSettleCheckSheetVo vo) { + + customerSettleCheckSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝客户对账单 + */ + @ApiOperation("审核拒绝客户对账单") + @HasPermission({"customer-settle:check-sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseCustomerSettleCheckSheetVo vo) { + + customerSettleCheckSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝客户对账单 + */ + @ApiOperation("批量审核拒绝客户对账单") + @HasPermission({"customer-settle:check-sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseCustomerSettleCheckSheetVo vo) { + + customerSettleCheckSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除客户对账单 + */ + @ApiOperation("删除客户对账单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:check-sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "客户对账单ID不能为空!") String id) { + + customerSettleCheckSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除客户对账单 + */ + @ApiOperation("批量删除客户对账单") + @HasPermission({"customer-settle:check-sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的客户对账单!") List ids) { + + customerSettleCheckSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 查询未对账的业务单据 + */ + @ApiOperation("查询未对账的业务单据") + @HasPermission({"customer-settle:check-sheet:add", "customer-settle:check-sheet:modify"}) + @GetMapping("/uncheck-items") + public InvokeResult> getUnCheckItems( + @Valid QueryCustomerUnCheckBizItemVo vo) { + + List results = customerSettleCheckSheetService.getUnCheckBizItems( + vo); + List datas = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(results)) { + datas = results.stream().map(CustomerSettleCheckBizItemBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(datas); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleFeeSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleFeeSheetController.java new file mode 100644 index 0000000..dbfa204 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleFeeSheetController.java @@ -0,0 +1,258 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.fee.customer.GetCustomerSettleFeeSheetBo; +import com.lframework.xingyun.settle.bo.fee.customer.QueryCustomerSettleFeeSheetBo; +import com.lframework.xingyun.settle.excel.fee.customer.CustomerSettleFeeSheetExportModel; +import com.lframework.xingyun.settle.dto.fee.customer.CustomerSettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import com.lframework.xingyun.settle.service.CustomerSettleFeeSheetService; +import com.lframework.xingyun.settle.vo.fee.customer.ApprovePassCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.ApproveRefuseCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.BatchApprovePassCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.BatchApproveRefuseCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.CreateCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.QueryCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.UpdateCustomerSettleFeeSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 客户费用单 + * + * @author zmj + */ +@Api(tags = "客户费用单") +@Validated +@RestController +@RequestMapping("/customer/settle/feesheet") +public class CustomerSettleFeeSheetController extends DefaultBaseController { + + @Autowired + private CustomerSettleFeeSheetService customerSettleFeeSheetService; + + /** + * 客户费用单列表 + */ + @ApiOperation("客户费用单列表") + @HasPermission({"customer-settle:fee-sheet:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryCustomerSettleFeeSheetVo vo) { + + PageResult pageResult = customerSettleFeeSheetService.query( + getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryCustomerSettleFeeSheetBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"customer-settle:fee-sheet:export"}) + @PostMapping("/export") + public void export(@Valid QueryCustomerSettleFeeSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("客户费用单信息", + CustomerSettleFeeSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = customerSettleFeeSheetService.query( + pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(CustomerSettleFeeSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:fee-sheet:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "客户费用单ID不能为空!") String id) { + + CustomerSettleFeeSheetFullDto data = customerSettleFeeSheetService.getDetail(id); + + GetCustomerSettleFeeSheetBo result = new GetCustomerSettleFeeSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建客户费用单 + */ + @ApiOperation("创建客户费用单") + @HasPermission({"customer-settle:fee-sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateCustomerSettleFeeSheetVo vo) { + + vo.validate(); + + String id = customerSettleFeeSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改客户费用单 + */ + @ApiOperation("修改客户费用单") + @HasPermission({"customer-settle:fee-sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateCustomerSettleFeeSheetVo vo) { + + vo.validate(); + + customerSettleFeeSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过客户费用单 + */ + @ApiOperation("审核通过客户费用单") + @HasPermission({"customer-settle:fee-sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass( + @RequestBody @Valid ApprovePassCustomerSettleFeeSheetVo vo) { + + customerSettleFeeSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过客户费用单 + */ + @ApiOperation("批量审核通过客户费用单") + @HasPermission({"customer-settle:fee-sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassCustomerSettleFeeSheetVo vo) { + + customerSettleFeeSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过客户费用单 + */ + @ApiOperation("直接审核通过客户费用单") + @HasPermission({"customer-settle:fee-sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass( + @RequestBody @Valid CreateCustomerSettleFeeSheetVo vo) { + + customerSettleFeeSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝客户费用单 + */ + @ApiOperation("审核拒绝客户费用单") + @HasPermission({"customer-settle:fee-sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseCustomerSettleFeeSheetVo vo) { + + customerSettleFeeSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝客户费用单 + */ + @ApiOperation("批量审核拒绝客户费用单") + @HasPermission({"customer-settle:fee-sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseCustomerSettleFeeSheetVo vo) { + + customerSettleFeeSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除客户费用单 + */ + @ApiOperation("删除客户费用单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:fee-sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "客户费用单ID不能为空!") String id) { + + customerSettleFeeSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除客户费用单 + */ + @ApiOperation("批量删除客户费用单") + @HasPermission({"customer-settle:fee-sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的客户费用单!") List ids) { + + customerSettleFeeSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettlePreSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettlePreSheetController.java new file mode 100644 index 0000000..dad1111 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettlePreSheetController.java @@ -0,0 +1,258 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.pre.customer.GetCustomerSettlePreSheetBo; +import com.lframework.xingyun.settle.bo.pre.customer.QueryCustomerSettlePreSheetBo; +import com.lframework.xingyun.settle.excel.pre.customer.CustomerSettlePreSheetExportModel; +import com.lframework.xingyun.settle.dto.pre.customer.CustomerSettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import com.lframework.xingyun.settle.service.CustomerSettlePreSheetService; +import com.lframework.xingyun.settle.vo.pre.customer.ApprovePassCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.ApproveRefuseCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.BatchApprovePassCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.BatchApproveRefuseCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.CreateCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.QueryCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.UpdateCustomerSettlePreSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 客户预付款单 + * + * @author zmj + */ +@Api(tags = "客户预付款单") +@Validated +@RestController +@RequestMapping("/customer/settle/presheet") +public class CustomerSettlePreSheetController extends DefaultBaseController { + + @Autowired + private CustomerSettlePreSheetService settlePreSheetService; + + /** + * 客户预付款单列表 + */ + @ApiOperation("客户预付款单列表") + @HasPermission({"customer-settle:pre-sheet:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryCustomerSettlePreSheetVo vo) { + + PageResult pageResult = settlePreSheetService.query( + getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryCustomerSettlePreSheetBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"customer-settle:pre-sheet:export"}) + @PostMapping("/export") + public void export(@Valid QueryCustomerSettlePreSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("客户预付款单信息", + CustomerSettlePreSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settlePreSheetService.query( + pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(CustomerSettlePreSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:pre-sheet:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "客户预付款单ID不能为空!") String id) { + + CustomerSettlePreSheetFullDto data = settlePreSheetService.getDetail(id); + + GetCustomerSettlePreSheetBo result = new GetCustomerSettlePreSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建客户预付款单 + */ + @ApiOperation("创建客户预付款单") + @HasPermission({"customer-settle:pre-sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateCustomerSettlePreSheetVo vo) { + + vo.validate(); + + String id = settlePreSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改客户预付款单 + */ + @ApiOperation("修改客户预付款单") + @HasPermission({"customer-settle:pre-sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateCustomerSettlePreSheetVo vo) { + + vo.validate(); + + settlePreSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过客户预付款单 + */ + @ApiOperation("审核通过客户预付款单") + @HasPermission({"customer-settle:pre-sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass( + @RequestBody @Valid ApprovePassCustomerSettlePreSheetVo vo) { + + settlePreSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过客户预付款单 + */ + @ApiOperation("批量审核通过客户预付款单") + @HasPermission({"customer-settle:pre-sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassCustomerSettlePreSheetVo vo) { + + settlePreSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过客户预付款单 + */ + @ApiOperation("直接审核通过客户预付款单") + @HasPermission({"customer-settle:pre-sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass( + @RequestBody @Valid CreateCustomerSettlePreSheetVo vo) { + + settlePreSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝客户预付款单 + */ + @ApiOperation("审核拒绝客户预付款单") + @HasPermission({"customer-settle:pre-sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseCustomerSettlePreSheetVo vo) { + + settlePreSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝客户预付款单 + */ + @ApiOperation("批量审核拒绝客户预付款单") + @HasPermission({"customer-settle:pre-sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseCustomerSettlePreSheetVo vo) { + + settlePreSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除客户预付款单 + */ + @ApiOperation("删除客户预付款单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:pre-sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "客户预付款单ID不能为空!") String id) { + + settlePreSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除客户预付款单 + */ + @ApiOperation("批量删除客户预付款单") + @HasPermission({"customer-settle:pre-sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的客户预付款单!") List ids) { + + settlePreSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleSheetController.java new file mode 100644 index 0000000..6b0fe61 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/CustomerSettleSheetController.java @@ -0,0 +1,278 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.sheet.customer.CustomerSettleBizItemBo; +import com.lframework.xingyun.settle.bo.sheet.customer.GetCustomerSettleSheetBo; +import com.lframework.xingyun.settle.bo.sheet.customer.QueryCustomerSettleSheetBo; +import com.lframework.xingyun.settle.excel.sheet.customer.CustomerSettleSheetExportModel; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleSheet; +import com.lframework.xingyun.settle.service.CustomerSettleSheetService; +import com.lframework.xingyun.settle.vo.sheet.customer.ApprovePassCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.ApproveRefuseCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.BatchApprovePassCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.BatchApproveRefuseCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.CreateCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerUnSettleBizItemVo; +import com.lframework.xingyun.settle.vo.sheet.customer.UpdateCustomerSettleSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 客户结算单 + * + * @author zmj + */ +@Api(tags = "客户结算单") +@Validated +@RestController +@RequestMapping("/customer/settle/sheet") +public class CustomerSettleSheetController extends DefaultBaseController { + + @Autowired + private CustomerSettleSheetService customerSettleSheetService; + + /** + * 客户结算单列表 + */ + @ApiOperation("客户结算单列表") + @HasPermission({"customer-settle:sheet:query"}) + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryCustomerSettleSheetVo vo) { + + PageResult pageResult = customerSettleSheetService.query( + getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryCustomerSettleSheetBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"customer-settle:sheet:export"}) + @PostMapping("/export") + public void export(@Valid QueryCustomerSettleSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("客户结算单信息", + CustomerSettleSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = customerSettleSheetService.query( + pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream() + .map(CustomerSettleSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:sheet:query"}) + @GetMapping + public InvokeResult findById( + @NotBlank(message = "客户结算单ID不能为空!") String id) { + + CustomerSettleSheetFullDto data = customerSettleSheetService.getDetail(id); + + GetCustomerSettleSheetBo result = new GetCustomerSettleSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建客户结算单 + */ + @ApiOperation("创建客户结算单") + @HasPermission({"customer-settle:sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateCustomerSettleSheetVo vo) { + + vo.validate(); + + String id = customerSettleSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改客户结算单 + */ + @ApiOperation("修改客户结算单") + @HasPermission({"customer-settle:sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateCustomerSettleSheetVo vo) { + + vo.validate(); + + customerSettleSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过客户结算单 + */ + @ApiOperation("审核通过客户结算单") + @HasPermission({"customer-settle:sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassCustomerSettleSheetVo vo) { + + customerSettleSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过客户结算单 + */ + @ApiOperation("批量审核通过客户结算单") + @HasPermission({"customer-settle:sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass( + @RequestBody @Valid BatchApprovePassCustomerSettleSheetVo vo) { + + customerSettleSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过客户结算单 + */ + @ApiOperation("直接审核通过客户结算单") + @HasPermission({"customer-settle:sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass( + @RequestBody @Valid CreateCustomerSettleSheetVo vo) { + + customerSettleSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝客户结算单 + */ + @ApiOperation("审核拒绝客户结算单") + @HasPermission({"customer-settle:sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse( + @RequestBody @Valid ApproveRefuseCustomerSettleSheetVo vo) { + + customerSettleSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝客户结算单 + */ + @ApiOperation("批量审核拒绝客户结算单") + @HasPermission({"customer-settle:sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse( + @RequestBody @Valid BatchApproveRefuseCustomerSettleSheetVo vo) { + + customerSettleSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除客户结算单 + */ + @ApiOperation("删除客户结算单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"customer-settle:sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "客户结算单ID不能为空!") String id) { + + customerSettleSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除客户结算单 + */ + @ApiOperation("批量删除客户结算单") + @HasPermission({"customer-settle:sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的客户结算单!") List ids) { + + customerSettleSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 查询未结算的业务单据 + */ + @ApiOperation("查询未结算的业务单据") + @HasPermission({"customer-settle:sheet:add", "customer-settle:sheet:modify"}) + @GetMapping("/unsettle-items") + public InvokeResult> getUnSettleItems( + @Valid QueryCustomerUnSettleBizItemVo vo) { + + List results = customerSettleSheetService.getUnSettleBizItems(vo); + List datas = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(results)) { + datas = results.stream().map(CustomerSettleBizItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(datas); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleCheckSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleCheckSheetController.java new file mode 100644 index 0000000..02140e2 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleCheckSheetController.java @@ -0,0 +1,267 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.check.GetSettleCheckSheetBo; +import com.lframework.xingyun.settle.bo.check.QuerySettleCheckSheetBo; +import com.lframework.xingyun.settle.bo.check.SettleCheckBizItemBo; +import com.lframework.xingyun.settle.excel.check.SettleCheckSheetExportModel; +import com.lframework.xingyun.settle.dto.check.SettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.SettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import com.lframework.xingyun.settle.service.SettleCheckSheetService; +import com.lframework.xingyun.settle.vo.check.ApprovePassSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.ApproveRefuseSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.BatchApprovePassSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.BatchApproveRefuseSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.CreateSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.QuerySettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.QueryUnCheckBizItemVo; +import com.lframework.xingyun.settle.vo.check.UpdateSettleCheckSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 供应商对账单 + * + * @author zmj + */ +@Api(tags = "供应商对账单") +@Validated +@RestController +@RequestMapping("/settle/checksheet") +public class SettleCheckSheetController extends DefaultBaseController { + + @Autowired + private SettleCheckSheetService settleCheckSheetService; + + /** + * 供应商对账单列表 + */ + @ApiOperation("供应商对账单列表") + @HasPermission({"settle:check-sheet:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySettleCheckSheetVo vo) { + + PageResult pageResult = settleCheckSheetService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySettleCheckSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"settle:check-sheet:export"}) + @PostMapping("/export") + public void export(@Valid QuerySettleCheckSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("供应商对账单信息", + SettleCheckSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settleCheckSheetService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SettleCheckSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:check-sheet:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "供应商对账单ID不能为空!") String id) { + + SettleCheckSheetFullDto data = settleCheckSheetService.getDetail(id); + + GetSettleCheckSheetBo result = new GetSettleCheckSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建供应商对账单 + */ + @ApiOperation("创建供应商对账单") + @HasPermission({"settle:check-sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSettleCheckSheetVo vo) { + + vo.validate(); + + String id = settleCheckSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改供应商对账单 + */ + @ApiOperation("修改供应商对账单") + @HasPermission({"settle:check-sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSettleCheckSheetVo vo) { + + vo.validate(); + + settleCheckSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过供应商对账单 + */ + @ApiOperation("审核通过供应商对账单") + @HasPermission({"settle:check-sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSettleCheckSheetVo vo) { + + settleCheckSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过供应商对账单 + */ + @ApiOperation("批量审核通过供应商对账单") + @HasPermission({"settle:check-sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass(@RequestBody @Valid BatchApprovePassSettleCheckSheetVo vo) { + + settleCheckSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过供应商对账单 + */ + @ApiOperation("直接审核通过供应商对账单") + @HasPermission({"settle:check-sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSettleCheckSheetVo vo) { + + settleCheckSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝供应商对账单 + */ + @ApiOperation("审核拒绝供应商对账单") + @HasPermission({"settle:check-sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSettleCheckSheetVo vo) { + + settleCheckSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝供应商对账单 + */ + @ApiOperation("批量审核拒绝供应商对账单") + @HasPermission({"settle:check-sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse(@RequestBody @Valid BatchApproveRefuseSettleCheckSheetVo vo) { + + settleCheckSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除供应商对账单 + */ + @ApiOperation("删除供应商对账单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:check-sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "供应商对账单ID不能为空!") String id) { + + settleCheckSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除供应商对账单 + */ + @ApiOperation("批量删除供应商对账单") + @HasPermission({"settle:check-sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的供应商对账单!") List ids) { + + settleCheckSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 查询未对账的业务单据 + */ + @ApiOperation("查询未对账的业务单据") + @HasPermission({"settle:check-sheet:add", "settle:check-sheet:modify"}) + @GetMapping("/uncheck-items") + public InvokeResult> getUnCheckItems(@Valid QueryUnCheckBizItemVo vo) { + + List results = settleCheckSheetService.getUnCheckBizItems(vo); + List datas = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(results)) { + datas = results.stream().map(SettleCheckBizItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(datas); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleFeeSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleFeeSheetController.java new file mode 100644 index 0000000..1db988c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleFeeSheetController.java @@ -0,0 +1,247 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.fee.GetSettleFeeSheetBo; +import com.lframework.xingyun.settle.bo.fee.QuerySettleFeeSheetBo; +import com.lframework.xingyun.settle.excel.fee.SettleFeeSheetExportModel; +import com.lframework.xingyun.settle.dto.fee.SettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import com.lframework.xingyun.settle.service.SettleFeeSheetService; +import com.lframework.xingyun.settle.vo.fee.ApprovePassSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.ApproveRefuseSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.BatchApprovePassSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.BatchApproveRefuseSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.CreateSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.QuerySettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.UpdateSettleFeeSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 供应商费用单 + * + * @author zmj + */ +@Api(tags = "供应商费用单") +@Validated +@RestController +@RequestMapping("/settle/feesheet") +public class SettleFeeSheetController extends DefaultBaseController { + + @Autowired + private SettleFeeSheetService settleFeeSheetService; + + /** + * 供应商费用单列表 + */ + @ApiOperation("供应商费用单列表") + @HasPermission({"settle:fee-sheet:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySettleFeeSheetVo vo) { + + PageResult pageResult = settleFeeSheetService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySettleFeeSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"settle:fee-sheet:export"}) + @PostMapping("/export") + public void export(@Valid QuerySettleFeeSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("供应商费用单信息", + SettleFeeSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settleFeeSheetService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SettleFeeSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:fee-sheet:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "供应商费用单ID不能为空!") String id) { + + SettleFeeSheetFullDto data = settleFeeSheetService.getDetail(id); + + GetSettleFeeSheetBo result = new GetSettleFeeSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建供应商费用单 + */ + @ApiOperation("创建供应商费用单") + @HasPermission({"settle:fee-sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSettleFeeSheetVo vo) { + + vo.validate(); + + String id = settleFeeSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改供应商费用单 + */ + @ApiOperation("修改供应商费用单") + @HasPermission({"settle:fee-sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSettleFeeSheetVo vo) { + + vo.validate(); + + settleFeeSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过供应商费用单 + */ + @ApiOperation("审核通过供应商费用单") + @HasPermission({"settle:fee-sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSettleFeeSheetVo vo) { + + settleFeeSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过供应商费用单 + */ + @ApiOperation("批量审核通过供应商费用单") + @HasPermission({"settle:fee-sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass(@RequestBody @Valid BatchApprovePassSettleFeeSheetVo vo) { + + settleFeeSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过供应商费用单 + */ + @ApiOperation("直接审核通过供应商费用单") + @HasPermission({"settle:fee-sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSettleFeeSheetVo vo) { + + settleFeeSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝供应商费用单 + */ + @ApiOperation("审核拒绝供应商费用单") + @HasPermission({"settle:fee-sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSettleFeeSheetVo vo) { + + settleFeeSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝供应商费用单 + */ + @ApiOperation("批量审核拒绝供应商费用单") + @HasPermission({"settle:fee-sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse(@RequestBody @Valid BatchApproveRefuseSettleFeeSheetVo vo) { + + settleFeeSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除供应商费用单 + */ + @ApiOperation("删除供应商费用单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:fee-sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "供应商费用单ID不能为空!") String id) { + + settleFeeSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除供应商费用单 + */ + @ApiOperation("批量删除供应商费用单") + @HasPermission({"settle:fee-sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的供应商费用单!") List ids) { + + settleFeeSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleInItemController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleInItemController.java new file mode 100644 index 0000000..0829e87 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleInItemController.java @@ -0,0 +1,186 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.item.in.GetSettleInItemBo; +import com.lframework.xingyun.settle.bo.item.in.QuerySettleInItemBo; +import com.lframework.xingyun.settle.excel.item.in.SettleInItemExportModel; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.vo.item.in.CreateSettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.QuerySettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.UpdateSettleInItemVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 收入项目 + * + * @author zmj + */ +@Api(tags = "收入项目") +@Validated +@RestController +@RequestMapping("/settle/item/in") +public class SettleInItemController extends DefaultBaseController { + + @Autowired + private SettleInItemService settleInItemService; + + /** + * 收入项目列表 + */ + @ApiOperation("收入项目列表") + @HasPermission({"settle:in-item:query","settle:in-item:add","settle:in-item:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySettleInItemVo vo) { + + PageResult pageResult = settleInItemService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySettleInItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询收入项目 + */ + @ApiOperation("查询收入项目") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:in-item:query","settle:in-item:add","settle:in-item:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SettleInItem data = settleInItemService.findById(id); + if (data == null) { + throw new DefaultClientException("收入项目不存在!"); + } + + GetSettleInItemBo result = new GetSettleInItemBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 导出收入项目 + */ + @ApiOperation("导出收入项目") + @HasPermission({"settle:in-item:export"}) + @PostMapping("/export") + public void export(@Valid QuerySettleInItemVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("收入项目信息", + SettleInItemExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settleInItemService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SettleInItemExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 批量停用收入项目 + */ + @ApiOperation("批量停用收入项目") + @HasPermission({"settle:in-item:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的收入项目!") @RequestBody List ids) { + + settleInItemService.batchUnable(ids); + + for (String id : ids) { + settleInItemService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用收入项目 + */ + @ApiOperation("批量启用收入项目") + @HasPermission({"settle:in-item:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的收入项目!") @RequestBody List ids) { + + settleInItemService.batchEnable(ids); + + for (String id : ids) { + settleInItemService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增收入项目 + */ + @ApiOperation("新增收入项目") + @HasPermission({"settle:in-item:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSettleInItemVo vo) { + + settleInItemService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改收入项目 + */ + @ApiOperation("修改收入项目") + @HasPermission({"settle:in-item:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSettleInItemVo vo) { + + settleInItemService.update(vo); + + settleInItemService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleOutItemController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleOutItemController.java new file mode 100644 index 0000000..1d9a28f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleOutItemController.java @@ -0,0 +1,186 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.item.out.GetSettleOutItemBo; +import com.lframework.xingyun.settle.bo.item.out.QuerySettleOutItemBo; +import com.lframework.xingyun.settle.excel.item.out.SettleOutItemExportModel; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import com.lframework.xingyun.settle.vo.item.out.CreateSettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.QuerySettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.UpdateSettleOutItemVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 支出项目 + * + * @author zmj + */ +@Api(tags = "支出项目") +@Validated +@RestController +@RequestMapping("/settle/item/out") +public class SettleOutItemController extends DefaultBaseController { + + @Autowired + private SettleOutItemService settleOutItemService; + + /** + * 支出项目列表 + */ + @ApiOperation("支出项目列表") + @HasPermission({"settle:out-item:query","settle:out-item:add","settle:out-item:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySettleOutItemVo vo) { + + PageResult pageResult = settleOutItemService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySettleOutItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询支出项目 + */ + @ApiOperation("查询支出项目") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:out-item:query","settle:out-item:add","settle:out-item:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SettleOutItem data = settleOutItemService.findById(id); + if (data == null) { + throw new DefaultClientException("支出项目不存在!"); + } + + GetSettleOutItemBo result = new GetSettleOutItemBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 导出支出项目 + */ + @ApiOperation("导出支出项目") + @HasPermission({"settle:out-item:export"}) + @PostMapping("/export") + public void export(@Valid QuerySettleOutItemVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("支出项目信息", + SettleOutItemExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settleOutItemService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SettleOutItemExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 批量停用支出项目 + */ + @ApiOperation("批量停用支出项目") + @HasPermission({"settle:out-item:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要停用的支出项目!") @RequestBody List ids) { + + settleOutItemService.batchUnable(ids); + + for (String id : ids) { + settleOutItemService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用支出项目 + */ + @ApiOperation("批量启用支出项目") + @HasPermission({"settle:out-item:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @NotEmpty(message = "请选择需要启用的支出项目!") @RequestBody List ids) { + + settleOutItemService.batchEnable(ids); + + for (String id : ids) { + settleOutItemService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增支出项目 + */ + @ApiOperation("新增支出项目") + @HasPermission({"settle:out-item:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSettleOutItemVo vo) { + + settleOutItemService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改支出项目 + */ + @ApiOperation("修改支出项目") + @HasPermission({"settle:out-item:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSettleOutItemVo vo) { + + settleOutItemService.update(vo); + + settleOutItemService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettlePreSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettlePreSheetController.java new file mode 100644 index 0000000..c4866bf --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettlePreSheetController.java @@ -0,0 +1,247 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.pre.GetSettlePreSheetBo; +import com.lframework.xingyun.settle.bo.pre.QuerySettlePreSheetBo; +import com.lframework.xingyun.settle.excel.pre.SettlePreSheetExportModel; +import com.lframework.xingyun.settle.dto.pre.SettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import com.lframework.xingyun.settle.service.SettlePreSheetService; +import com.lframework.xingyun.settle.vo.pre.ApprovePassSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.ApproveRefuseSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.BatchApprovePassSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.BatchApproveRefuseSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.CreateSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.QuerySettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.UpdateSettlePreSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 供应商预付款单 + * + * @author zmj + */ +@Api(tags = "供应商预付款单") +@Validated +@RestController +@RequestMapping("/settle/presheet") +public class SettlePreSheetController extends DefaultBaseController { + + @Autowired + private SettlePreSheetService settlePreSheetService; + + /** + * 供应商预付款单列表 + */ + @ApiOperation("供应商预付款单列表") + @HasPermission({"settle:pre-sheet:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySettlePreSheetVo vo) { + + PageResult pageResult = settlePreSheetService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySettlePreSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"settle:pre-sheet:export"}) + @PostMapping("/export") + public void export(@Valid QuerySettlePreSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("供应商预付款单信息", + SettlePreSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settlePreSheetService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SettlePreSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:pre-sheet:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "供应商预付款单ID不能为空!") String id) { + + SettlePreSheetFullDto data = settlePreSheetService.getDetail(id); + + GetSettlePreSheetBo result = new GetSettlePreSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建供应商预付款单 + */ + @ApiOperation("创建供应商预付款单") + @HasPermission({"settle:pre-sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSettlePreSheetVo vo) { + + vo.validate(); + + String id = settlePreSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改供应商预付款单 + */ + @ApiOperation("修改供应商预付款单") + @HasPermission({"settle:pre-sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSettlePreSheetVo vo) { + + vo.validate(); + + settlePreSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过供应商预付款单 + */ + @ApiOperation("审核通过供应商预付款单") + @HasPermission({"settle:pre-sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSettlePreSheetVo vo) { + + settlePreSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过供应商预付款单 + */ + @ApiOperation("批量审核通过供应商预付款单") + @HasPermission({"settle:pre-sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass(@RequestBody @Valid BatchApprovePassSettlePreSheetVo vo) { + + settlePreSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过供应商预付款单 + */ + @ApiOperation("直接审核通过供应商预付款单") + @HasPermission({"settle:pre-sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSettlePreSheetVo vo) { + + settlePreSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝供应商预付款单 + */ + @ApiOperation("审核拒绝供应商预付款单") + @HasPermission({"settle:pre-sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSettlePreSheetVo vo) { + + settlePreSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝供应商预付款单 + */ + @ApiOperation("批量审核拒绝供应商预付款单") + @HasPermission({"settle:pre-sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse(@RequestBody @Valid BatchApproveRefuseSettlePreSheetVo vo) { + + settlePreSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除供应商预付款单 + */ + @ApiOperation("删除供应商预付款单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:pre-sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "供应商预付款单ID不能为空!") String id) { + + settlePreSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除供应商预付款单 + */ + @ApiOperation("批量删除供应商预付款单") + @HasPermission({"settle:pre-sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的供应商预付款单!") List ids) { + + settlePreSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSelectorController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSelectorController.java new file mode 100644 index 0000000..d345eb3 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSelectorController.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.settle.bo.item.in.SettleInItemSelectorBo; +import com.lframework.xingyun.settle.bo.item.out.SettleOutItemSelectorBo; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import com.lframework.xingyun.settle.vo.item.in.SettleInItemSelectorVo; +import com.lframework.xingyun.settle.vo.item.out.SettleOutItemSelectorVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据选择器 + * + * @author zmj + */ +@Api(tags = "数据选择器") +@Validated +@RestController +@RequestMapping("/selector") +public class SettleSelectorController extends DefaultBaseController { + + @Autowired + private SettleInItemService settleInItemService; + + @Autowired + private SettleOutItemService settleOutItemService; + + /** + * 收入项目 + */ + @ApiOperation("收入项目") + @GetMapping("/settle/item/in") + public InvokeResult> selector( + @Valid SettleInItemSelectorVo vo) { + + PageResult pageResult = settleInItemService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + + results = datas.stream().map(SettleInItemSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载收入项目 + */ + @ApiOperation("加载收入项目") + @PostMapping("/settle/item/in/load") + public InvokeResult> loadSettleInItem( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> settleInItemService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SettleInItemSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + /** + * 支出项目 + */ + @ApiOperation("支出项目") + @GetMapping("/settle/item/out") + public InvokeResult> selector( + @Valid SettleOutItemSelectorVo vo) { + + PageResult pageResult = settleOutItemService.selector(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SettleOutItemSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载支出项目 + */ + @ApiOperation("加载支出项目") + @PostMapping("/settle/item/out/load") + public InvokeResult> loadSettleOutItem( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> settleOutItemService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SettleOutItemSelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSheetController.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSheetController.java new file mode 100644 index 0000000..1aa7e32 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/controller/SettleSheetController.java @@ -0,0 +1,267 @@ +package com.lframework.xingyun.settle.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.components.excel.ExcelMultipartWriterSheetBuilder; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.ExcelUtil; +import com.lframework.xingyun.settle.bo.sheet.GetSettleSheetBo; +import com.lframework.xingyun.settle.bo.sheet.QuerySettleSheetBo; +import com.lframework.xingyun.settle.bo.sheet.SettleBizItemBo; +import com.lframework.xingyun.settle.excel.sheet.SettleSheetExportModel; +import com.lframework.xingyun.settle.dto.sheet.SettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.SettleSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleSheet; +import com.lframework.xingyun.settle.service.SettleSheetService; +import com.lframework.xingyun.settle.vo.sheet.ApprovePassSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.ApproveRefuseSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.BatchApprovePassSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.BatchApproveRefuseSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.CreateSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.QuerySettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.QueryUnSettleBizItemVo; +import com.lframework.xingyun.settle.vo.sheet.UpdateSettleSheetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 供应商结算单 + * + * @author zmj + */ +@Api(tags = "供应商结算单") +@Validated +@RestController +@RequestMapping("/settle/sheet") +public class SettleSheetController extends DefaultBaseController { + + @Autowired + private SettleSheetService settleSheetService; + + /** + * 供应商结算单列表 + */ + @ApiOperation("供应商结算单列表") + @HasPermission({"settle:sheet:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySettleSheetVo vo) { + + PageResult pageResult = settleSheetService.query(getPageIndex(vo), getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySettleSheetBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 导出 + */ + @ApiOperation("导出") + @HasPermission({"settle:sheet:export"}) + @PostMapping("/export") + public void export(@Valid QuerySettleSheetVo vo) { + + ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("供应商结算单信息", + SettleSheetExportModel.class); + + try { + int pageIndex = 1; + while (true) { + PageResult pageResult = settleSheetService.query(pageIndex, getExportSize(), vo); + List datas = pageResult.getDatas(); + List models = datas.stream().map(SettleSheetExportModel::new) + .collect(Collectors.toList()); + builder.doWrite(models); + + if (!pageResult.isHasNext()) { + break; + } + pageIndex++; + } + } finally { + builder.finish(); + } + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:sheet:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "供应商结算单ID不能为空!") String id) { + + SettleSheetFullDto data = settleSheetService.getDetail(id); + + GetSettleSheetBo result = new GetSettleSheetBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 创建供应商结算单 + */ + @ApiOperation("创建供应商结算单") + @HasPermission({"settle:sheet:add"}) + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateSettleSheetVo vo) { + + vo.validate(); + + String id = settleSheetService.create(vo); + + return InvokeResultBuilder.success(id); + } + + /** + * 修改供应商结算单 + */ + @ApiOperation("修改供应商结算单") + @HasPermission({"settle:sheet:modify"}) + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateSettleSheetVo vo) { + + vo.validate(); + + settleSheetService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核通过供应商结算单 + */ + @ApiOperation("审核通过供应商结算单") + @HasPermission({"settle:sheet:approve"}) + @PatchMapping("/approve/pass") + public InvokeResult approvePass(@RequestBody @Valid ApprovePassSettleSheetVo vo) { + + settleSheetService.approvePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核通过供应商结算单 + */ + @ApiOperation("批量审核通过供应商结算单") + @HasPermission({"settle:sheet:approve"}) + @PatchMapping("/approve/pass/batch") + public InvokeResult batchApprovePass(@RequestBody @Valid BatchApprovePassSettleSheetVo vo) { + + settleSheetService.batchApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 直接审核通过供应商结算单 + */ + @ApiOperation("直接审核通过供应商结算单") + @HasPermission({"settle:sheet:approve"}) + @PostMapping("/approve/pass/direct") + public InvokeResult directApprovePass(@RequestBody @Valid CreateSettleSheetVo vo) { + + settleSheetService.directApprovePass(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 审核拒绝供应商结算单 + */ + @ApiOperation("审核拒绝供应商结算单") + @HasPermission({"settle:sheet:approve"}) + @PatchMapping("/approve/refuse") + public InvokeResult approveRefuse(@RequestBody @Valid ApproveRefuseSettleSheetVo vo) { + + settleSheetService.approveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 批量审核拒绝供应商结算单 + */ + @ApiOperation("批量审核拒绝供应商结算单") + @HasPermission({"settle:sheet:approve"}) + @PatchMapping("/approve/refuse/batch") + public InvokeResult batchApproveRefuse(@RequestBody @Valid BatchApproveRefuseSettleSheetVo vo) { + + settleSheetService.batchApproveRefuse(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 删除供应商结算单 + */ + @ApiOperation("删除供应商结算单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"settle:sheet:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotBlank(message = "供应商结算单ID不能为空!") String id) { + + settleSheetService.deleteById(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量删除供应商结算单 + */ + @ApiOperation("批量删除供应商结算单") + @HasPermission({"settle:sheet:delete"}) + @DeleteMapping("/batch") + public InvokeResult deleteByIds( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "请选择需要删除的供应商结算单!") List ids) { + + settleSheetService.deleteByIds(ids); + + return InvokeResultBuilder.success(); + } + + /** + * 查询未结算的业务单据 + */ + @ApiOperation("查询未结算的业务单据") + @HasPermission({"settle:sheet:add", "settle:sheet:modify"}) + @GetMapping("/unsettle-items") + public InvokeResult> getUnCheckItems(@Valid QueryUnSettleBizItemVo vo) { + + List results = settleSheetService.getUnSettleBizItems(vo); + List datas = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(results)) { + datas = results.stream().map(SettleBizItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(datas); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckBizItemDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckBizItemDto.java new file mode 100644 index 0000000..a963b6e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckBizItemDto.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.settle.dto.check; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.SettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.SettleCheckSheetCalcType; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class SettleCheckBizItemDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + private String id; + + /** + * 单据号 + */ + private String code; + + /** + * 业务类型 + */ + private SettleCheckSheetBizType bizType; + + /** + * 计算类型 + */ + private SettleCheckSheetCalcType calcType; + + /** + * 对账金额 + */ + private BigDecimal totalAmount; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckSheetFullDto.java new file mode 100644 index 0000000..fc1b810 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/SettleCheckSheetFullDto.java @@ -0,0 +1,155 @@ +package com.lframework.xingyun.settle.dto.check; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.SettleCheckSheetCalcType; +import com.lframework.xingyun.settle.enums.SettleCheckSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SettleCheckSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始日期 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleCheckSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 单据ID + */ + private String bizId; + + /** + * 业务类型 + */ + private SettleCheckSheetBizType bizType; + + /** + * 计算类型 + */ + private SettleCheckSheetCalcType calcType; + + /** + * 应付金额 + */ + private BigDecimal payAmount; + + /** + * 备注 + */ + private String description; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckBizItemDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckBizItemDto.java new file mode 100644 index 0000000..37765c0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckBizItemDto.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.settle.dto.check.customer; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetCalcType; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class CustomerSettleCheckBizItemDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + private String id; + + /** + * 单据号 + */ + private String code; + + /** + * 业务类型 + */ + private CustomerSettleCheckSheetBizType bizType; + + /** + * 计算类型 + */ + private CustomerSettleCheckSheetCalcType calcType; + + /** + * 对账金额 + */ + private BigDecimal totalAmount; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckSheetFullDto.java new file mode 100644 index 0000000..d59f035 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/check/customer/CustomerSettleCheckSheetFullDto.java @@ -0,0 +1,155 @@ +package com.lframework.xingyun.settle.dto.check.customer; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetCalcType; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class CustomerSettleCheckSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始日期 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettleCheckSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 单据ID + */ + private String bizId; + + /** + * 业务类型 + */ + private CustomerSettleCheckSheetBizType bizType; + + /** + * 计算类型 + */ + private CustomerSettleCheckSheetCalcType calcType; + + /** + * 应付金额 + */ + private BigDecimal payAmount; + + /** + * 备注 + */ + private String description; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/SettleFeeSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/SettleFeeSheetFullDto.java new file mode 100644 index 0000000..d10393a --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/SettleFeeSheetFullDto.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.settle.dto.fee; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetType; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SettleFeeSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 单据类型 + */ + private SettleFeeSheetType sheetType; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleFeeSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/customer/CustomerSettleFeeSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/customer/CustomerSettleFeeSheetFullDto.java new file mode 100644 index 0000000..e772a88 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/fee/customer/CustomerSettleFeeSheetFullDto.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.settle.dto.fee.customer; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetType; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class CustomerSettleFeeSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 单据类型 + */ + private CustomerSettleFeeSheetType sheetType; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettleFeeSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/SettlePreSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/SettlePreSheetFullDto.java new file mode 100644 index 0000000..4be15ab --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/SettlePreSheetFullDto.java @@ -0,0 +1,112 @@ +package com.lframework.xingyun.settle.dto.pre; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettlePreSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SettlePreSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettlePreSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/customer/CustomerSettlePreSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/customer/CustomerSettlePreSheetFullDto.java new file mode 100644 index 0000000..fc6fad5 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/pre/customer/CustomerSettlePreSheetFullDto.java @@ -0,0 +1,112 @@ +package com.lframework.xingyun.settle.dto.pre.customer; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettlePreSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class CustomerSettlePreSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettlePreSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleBizItemDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleBizItemDto.java new file mode 100644 index 0000000..c5a02fe --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleBizItemDto.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.settle.dto.sheet; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class SettleBizItemDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + private String id; + + /** + * 单据号 + */ + private String code; + + /** + * 应付金额 + */ + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 未付款金额 + */ + private BigDecimal totalUnPayAmount; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleSheetFullDto.java new file mode 100644 index 0000000..e671d4a --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/SettleSheetFullDto.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.settle.dto.sheet; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.SettleSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class SettleSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始日期 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 单据ID + */ + private String bizId; + + /** + * 实付金额 + */ + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 备注 + */ + private String description; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleBizItemDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleBizItemDto.java new file mode 100644 index 0000000..3784042 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleBizItemDto.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.settle.dto.sheet.customer; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class CustomerSettleBizItemDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + private String id; + + /** + * 单据号 + */ + private String code; + + /** + * 应付金额 + */ + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 未付款金额 + */ + private BigDecimal totalUnPayAmount; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleSheetFullDto.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleSheetFullDto.java new file mode 100644 index 0000000..21fb87b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/dto/sheet/customer/CustomerSettleSheetFullDto.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.settle.dto.sheet.customer; + +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.SettleSheetStatus; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +@Data +public class CustomerSettleSheetFullDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始日期 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 修改人ID + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 明细 + */ + private List details; + + @Data + public static class SheetDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 明细ID + */ + private String id; + + /** + * 单据ID + */ + private String bizId; + + /** + * 实付金额 + */ + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 备注 + */ + private String description; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheet.java new file mode 100644 index 0000000..27c3bbd --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheet.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("customer_settle_check_sheet") +public class CustomerSettleCheckSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettleCheckSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheetDetail.java new file mode 100644 index 0000000..3d6caf9 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleCheckSheetDetail.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetCalcType; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("customer_settle_check_sheet_detail") +public class CustomerSettleCheckSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 对账单ID + */ + private String sheetId; + + /** + * 单据ID + */ + private String bizId; + + /** + * 业务类型 + */ + private CustomerSettleCheckSheetBizType bizType; + + /** + * 计算方式 + */ + private CustomerSettleCheckSheetCalcType calcType; + + /** + * 应付金额 + */ + private BigDecimal payAmount; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheet.java new file mode 100644 index 0000000..99bcfa1 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheet.java @@ -0,0 +1,119 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetType; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-30 + */ +@Data +@TableName("customer_settle_fee_sheet") +public class CustomerSettleFeeSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 单据类型 + */ + private CustomerSettleFeeSheetType sheetType; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettleFeeSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheetDetail.java new file mode 100644 index 0000000..710a277 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleFeeSheetDetail.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-30 + */ +@Data +@TableName("customer_settle_fee_sheet_detail") +public class CustomerSettleFeeSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 费用单ID + */ + private String sheetId; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheet.java new file mode 100644 index 0000000..7e1fd49 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheet.java @@ -0,0 +1,112 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettlePreSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("customer_settle_pre_sheet") +public class CustomerSettlePreSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettlePreSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheetDetail.java new file mode 100644 index 0000000..abdf41c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettlePreSheetDetail.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("customer_settle_pre_sheet_detail") +public class CustomerSettlePreSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 预付款单ID + */ + private String sheetId; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheet.java new file mode 100644 index 0000000..3f6bdf6 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheet.java @@ -0,0 +1,123 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.CustomerSettleSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-05 + */ +@Data +@TableName("customer_settle_sheet") +public class CustomerSettleSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 客户ID + */ + private String customerId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private CustomerSettleSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheetDetail.java new file mode 100644 index 0000000..2be6847 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/CustomerSettleSheetDetail.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-05 + */ +@Data +@TableName("customer_settle_sheet_detail") +public class CustomerSettleSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 结算单ID + */ + private String sheetId; + + /** + * 单据ID + */ + private String bizId; + + /** + * 实付金额 + */ + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheet.java new file mode 100644 index 0000000..95b5f16 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheet.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettleCheckSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("settle_check_sheet") +public class SettleCheckSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 应付金额 + */ + private BigDecimal totalPayAmount; + + /** + * 已付金额 + */ + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleCheckSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheetDetail.java new file mode 100644 index 0000000..1f40734 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleCheckSheetDetail.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.SettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.SettleCheckSheetCalcType; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("settle_check_sheet_detail") +public class SettleCheckSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 对账单ID + */ + private String sheetId; + + /** + * 单据ID + */ + private String bizId; + + /** + * 业务类型 + */ + private SettleCheckSheetBizType bizType; + + /** + * 计算方式 + */ + private SettleCheckSheetCalcType calcType; + + /** + * 应付金额 + */ + private BigDecimal payAmount; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheet.java new file mode 100644 index 0000000..22bfa07 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheet.java @@ -0,0 +1,119 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetType; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-30 + */ +@Data +@TableName("settle_fee_sheet") +public class SettleFeeSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 单据类型 + */ + private SettleFeeSheetType sheetType; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleFeeSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheetDetail.java new file mode 100644 index 0000000..334c67c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleFeeSheetDetail.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-30 + */ +@Data +@TableName("settle_fee_sheet_detail") +public class SettleFeeSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 费用单ID + */ + private String sheetId; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleInItem.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleInItem.java new file mode 100644 index 0000000..1033115 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleInItem.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-28 + */ +@Data +@TableName("settle_in_item") +public class SettleInItem extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SettleInItem"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleOutItem.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleOutItem.java new file mode 100644 index 0000000..8389547 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleOutItem.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-11-28 + */ +@Data +@TableName("settle_out_item") +public class SettleOutItem extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SettleOutItem"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheet.java new file mode 100644 index 0000000..898da61 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheet.java @@ -0,0 +1,112 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettlePreSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("settle_pre_sheet") +public class SettlePreSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettlePreSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; + + /** + * 结算状态 + */ + private SettleStatus settleStatus; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheetDetail.java new file mode 100644 index 0000000..3d8f427 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettlePreSheetDetail.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-02 + */ +@Data +@TableName("settle_pre_sheet_detail") +public class SettlePreSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 预付款单ID + */ + private String sheetId; + + /** + * 项目ID + */ + private String itemId; + + /** + * 金额 + */ + private BigDecimal amount; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheet.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheet.java new file mode 100644 index 0000000..f47b517 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheet.java @@ -0,0 +1,123 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.settle.enums.SettleSheetStatus; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-05 + */ +@Data +@TableName("settle_sheet") +public class SettleSheet extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单号 + */ + private String code; + + /** + * 供应商ID + */ + private String supplierId; + + /** + * 总金额 + */ + private BigDecimal totalAmount; + + /** + * 已优惠金额 + */ + private BigDecimal totalDiscountAmount; + + /** + * 起始时间 + */ + private LocalDate startDate; + + /** + * 截止日期 + */ + private LocalDate endDate; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 审核人 + */ + private String approveBy; + + /** + * 审核时间 + */ + private LocalDateTime approveTime; + + /** + * 状态 + */ + private SettleSheetStatus status; + + /** + * 拒绝原因 + */ + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheetDetail.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheetDetail.java new file mode 100644 index 0000000..43a485d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/entity/SettleSheetDetail.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.settle.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.math.BigDecimal; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-05 + */ +@Data +@TableName("settle_sheet_detail") +public class SettleSheetDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 结算单ID + */ + private String sheetId; + + /** + * 单据ID + */ + private String bizId; + + /** + * 实付金额 + */ + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 备注 + */ + private String description; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetBizType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetBizType.java new file mode 100644 index 0000000..3c9ab05 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetBizType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettleCheckSheetBizType implements BaseEnum { + OUT_SHEET(1, "销售出库单"), SALE_RETURN(2, "销售退单"), SETTLE_FEE_SHEET(3, "客户费用单"), SETTLE_PRE_SHEET(4, + "客户预收款单"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettleCheckSheetBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetCalcType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetCalcType.java new file mode 100644 index 0000000..f8f9b72 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetCalcType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettleCheckSheetCalcType implements BaseEnum { + ADD(1, "加"), SUB(2, "减"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettleCheckSheetCalcType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetStatus.java new file mode 100644 index 0000000..c472394 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleCheckSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettleCheckSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettleCheckSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetStatus.java new file mode 100644 index 0000000..bb4cf0c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettleFeeSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettleFeeSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetType.java new file mode 100644 index 0000000..c4cd96d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleFeeSheetType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettleFeeSheetType implements BaseEnum { + RECEIVE(1, "应收款"), PAY(2, "应付款"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettleFeeSheetType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettlePreSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettlePreSheetStatus.java new file mode 100644 index 0000000..c8295c0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettlePreSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettlePreSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettlePreSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleSheetStatus.java new file mode 100644 index 0000000..f39af1d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/CustomerSettleSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum CustomerSettleSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + CustomerSettleSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetBizType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetBizType.java new file mode 100644 index 0000000..804c14d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetBizType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleCheckSheetBizType implements BaseEnum { + RECEIVE_SHEET(1, "采购收货单"), PURCHASE_RETURN(2, "采购退单"), SETTLE_FEE_SHEET(3, "供应商费用单"), SETTLE_PRE_SHEET(4, + "供应商预付款单"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleCheckSheetBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetCalcType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetCalcType.java new file mode 100644 index 0000000..0c2ce1f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetCalcType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleCheckSheetCalcType implements BaseEnum { + ADD(1, "加"), SUB(2, "减"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleCheckSheetCalcType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetStatus.java new file mode 100644 index 0000000..12616fa --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleCheckSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleCheckSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleCheckSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetStatus.java new file mode 100644 index 0000000..ffb73ae --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleFeeSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleFeeSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetType.java new file mode 100644 index 0000000..e8eb25d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleFeeSheetType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleFeeSheetType implements BaseEnum { + RECEIVE(1, "应收款"), PAY(2, "应付款"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleFeeSheetType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleOpLogType.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleOpLogType.java new file mode 100644 index 0000000..5b05b7a --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleOpLogType.java @@ -0,0 +1,7 @@ +package com.lframework.xingyun.settle.enums; + +public interface SettleOpLogType { + + // 结算业务 + int SETTLE = 3000; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettlePreSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettlePreSheetStatus.java new file mode 100644 index 0000000..bd09760 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettlePreSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettlePreSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettlePreSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleSheetStatus.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleSheetStatus.java new file mode 100644 index 0000000..1b72626 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/enums/SettleSheetStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SettleSheetStatus implements BaseEnum { + CREATED(0, "待审核"), APPROVE_PASS(3, "审核通过"), APPROVE_REFUSE(6, "审核拒绝"); + + @EnumValue + private final Integer code; + + private final String desc; + + SettleSheetStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/SettleCheckSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/SettleCheckSheetExportModel.java new file mode 100644 index 0000000..24d89b6 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/SettleCheckSheetExportModel.java @@ -0,0 +1,167 @@ +package com.lframework.xingyun.settle.excel.check; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import com.lframework.xingyun.settle.enums.SettleCheckSheetStatus; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class SettleCheckSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 供应商编号 + */ + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 单据金额 + */ + @ExcelProperty("单据金额") + private BigDecimal totalAmount; + + /** + * 应付总金额 + */ + @ExcelProperty("应付总金额") + private BigDecimal totalPayAmount; + + /** + * 已付款金额 + */ + @ExcelProperty("已付款金额") + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + @ExcelProperty("已优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付款金额 + */ + @ExcelProperty("未付款金额") + private BigDecimal totalUnPayAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public SettleCheckSheetExportModel() { + + } + + public SettleCheckSheetExportModel(SettleCheckSheet dto) { + + super(dto); + } + + @Override + public
BaseBo convert(SettleCheckSheet dto) { + + return this; + } + + @Override + protected void afterInit(SettleCheckSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setSupplierCode(supplier.getCode()); + this.setSupplierName(supplier.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setTotalPayAmount(dto.getTotalPayAmount()); + this.setTotalPayedAmount(dto.getTotalPayedAmount()); + this.setTotalDiscountAmount(dto.getTotalDiscountAmount()); + this.setTotalUnPayAmount( + NumberUtil.sub(dto.getTotalPayAmount(), dto.getTotalPayedAmount(), dto.getTotalDiscountAmount())); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(SettleCheckSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setSettleStatus(EnumUtil.getDesc(SettleStatus.class, dto.getSettleStatus())); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/customer/CustomerSettleCheckSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/customer/CustomerSettleCheckSheetExportModel.java new file mode 100644 index 0000000..5393bab --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/check/customer/CustomerSettleCheckSheetExportModel.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.settle.excel.check.customer; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class CustomerSettleCheckSheetExportModel extends BaseBo implements + ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 单据金额 + */ + @ExcelProperty("单据金额") + private BigDecimal totalAmount; + + /** + * 应付总金额 + */ + @ExcelProperty("应付总金额") + private BigDecimal totalPayAmount; + + /** + * 已付款金额 + */ + @ExcelProperty("已付款金额") + private BigDecimal totalPayedAmount; + + /** + * 已优惠金额 + */ + @ExcelProperty("已优惠金额") + private BigDecimal totalDiscountAmount; + + /** + * 未付款金额 + */ + @ExcelProperty("未付款金额") + private BigDecimal totalUnPayAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public CustomerSettleCheckSheetExportModel() { + + } + + public CustomerSettleCheckSheetExportModel(CustomerSettleCheckSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleCheckSheet dto) { + + return this; + } + + @Override + protected void afterInit(CustomerSettleCheckSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setTotalPayAmount(dto.getTotalPayAmount()); + this.setTotalPayedAmount(dto.getTotalPayedAmount()); + this.setTotalDiscountAmount(dto.getTotalDiscountAmount()); + this.setTotalUnPayAmount( + NumberUtil.sub(dto.getTotalPayAmount(), dto.getTotalPayedAmount(), + dto.getTotalDiscountAmount())); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(CustomerSettleCheckSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setSettleStatus(EnumUtil.getDesc(SettleStatus.class, dto.getSettleStatus())); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/SettleFeeSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/SettleFeeSheetExportModel.java new file mode 100644 index 0000000..5866a86 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/SettleFeeSheetExportModel.java @@ -0,0 +1,137 @@ +package com.lframework.xingyun.settle.excel.fee; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import com.lframework.xingyun.settle.enums.SettleFeeSheetStatus; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class SettleFeeSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 供应商编号 + */ + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public SettleFeeSheetExportModel() { + + } + + public SettleFeeSheetExportModel(SettleFeeSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleFeeSheet dto) { + + return this; + } + + @Override + protected void afterInit(SettleFeeSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setSupplierCode(supplier.getCode()); + this.setSupplierName(supplier.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(SettleFeeSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setSettleStatus(EnumUtil.getDesc(SettleStatus.class, dto.getSettleStatus())); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/customer/CustomerSettleFeeSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/customer/CustomerSettleFeeSheetExportModel.java new file mode 100644 index 0000000..d6c9106 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/fee/customer/CustomerSettleFeeSheetExportModel.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.settle.excel.fee.customer; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class CustomerSettleFeeSheetExportModel extends BaseBo implements + ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public CustomerSettleFeeSheetExportModel() { + + } + + public CustomerSettleFeeSheetExportModel(CustomerSettleFeeSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleFeeSheet dto) { + + return this; + } + + @Override + protected void afterInit(CustomerSettleFeeSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(CustomerSettleFeeSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setSettleStatus(EnumUtil.getDesc(SettleStatus.class, dto.getSettleStatus())); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/in/SettleInItemExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/in/SettleInItemExportModel.java new file mode 100644 index 0000000..bbadeb8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/in/SettleInItemExportModel.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.settle.excel.item.in; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.settle.entity.SettleInItem; +import lombok.Data; + +@Data +public class SettleInItemExportModel extends BaseBo implements ExcelModel { + + @ExcelProperty("编号") + private String code; + + @ExcelProperty("名称") + private String name; + + @ExcelProperty("备注") + private String description; + + public SettleInItemExportModel() { + + } + + public SettleInItemExportModel(SettleInItem dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleInItem dto) { + + return this; + } + + @Override + protected void afterInit(SettleInItem dto) { + + this.setCode(dto.getCode()); + this.setName(dto.getName()); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/out/SettleOutItemExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/out/SettleOutItemExportModel.java new file mode 100644 index 0000000..2ed281f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/item/out/SettleOutItemExportModel.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.settle.excel.item.out; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import lombok.Data; + +@Data +public class SettleOutItemExportModel extends BaseBo implements ExcelModel { + + @ExcelProperty("编号") + private String code; + + @ExcelProperty("名称") + private String name; + + @ExcelProperty("备注") + private String description; + + public SettleOutItemExportModel() { + + } + + public SettleOutItemExportModel(SettleOutItem dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleOutItem dto) { + + return this; + } + + @Override + protected void afterInit(SettleOutItem dto) { + + this.setCode(dto.getCode()); + this.setName(dto.getName()); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/SettlePreSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/SettlePreSheetExportModel.java new file mode 100644 index 0000000..e27cc9b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/SettlePreSheetExportModel.java @@ -0,0 +1,137 @@ +package com.lframework.xingyun.settle.excel.pre; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import com.lframework.xingyun.settle.enums.SettlePreSheetStatus; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class SettlePreSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 供应商编号 + */ + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public SettlePreSheetExportModel() { + + } + + public SettlePreSheetExportModel(SettlePreSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettlePreSheet dto) { + + return this; + } + + @Override + protected void afterInit(SettlePreSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setSupplierCode(supplier.getCode()); + this.setSupplierName(supplier.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(SettlePreSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setSettleStatus(EnumUtil.getDesc(SettleStatus.class, dto.getSettleStatus())); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/customer/CustomerSettlePreSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/customer/CustomerSettlePreSheetExportModel.java new file mode 100644 index 0000000..ccaec83 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/pre/customer/CustomerSettlePreSheetExportModel.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.settle.excel.pre.customer; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import com.lframework.xingyun.settle.enums.CustomerSettlePreSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class CustomerSettlePreSheetExportModel extends BaseBo implements + ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 单据总金额 + */ + @ExcelProperty("单据总金额") + private BigDecimal totalAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 结算状态 + */ + @ExcelProperty("结算状态") + private String settleStatus; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public CustomerSettlePreSheetExportModel() { + + } + + public CustomerSettlePreSheetExportModel(CustomerSettlePreSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettlePreSheet dto) { + + return this; + } + + @Override + protected void afterInit(CustomerSettlePreSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(CustomerSettlePreSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setSettleStatus(EnumUtil.getDesc(SettleStatus.class, dto.getSettleStatus())); + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/SettleSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/SettleSheetExportModel.java new file mode 100644 index 0000000..0ba7fa4 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/SettleSheetExportModel.java @@ -0,0 +1,136 @@ +package com.lframework.xingyun.settle.excel.sheet; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Supplier; +import com.lframework.xingyun.basedata.service.supplier.SupplierService; +import com.lframework.xingyun.settle.entity.SettleSheet; +import com.lframework.xingyun.settle.enums.SettleSheetStatus; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class SettleSheetExportModel extends BaseBo implements ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 供应商编号 + */ + @ExcelProperty("供应商编号") + private String supplierCode; + + /** + * 供应商名称 + */ + @ExcelProperty("供应商名称") + private String supplierName; + + /** + * 实付总金额 + */ + @ExcelProperty("实付总金额") + private BigDecimal totalAmount; + + /** + * 优惠总金额 + */ + @ExcelProperty("优惠总金额") + private BigDecimal totalDiscountAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public SettleSheetExportModel() { + + } + + public SettleSheetExportModel(SettleSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(SettleSheet dto) { + + return this; + } + + @Override + protected void afterInit(SettleSheet dto) { + + SupplierService supplierService = ApplicationUtil.getBean(SupplierService.class); + Supplier supplier = supplierService.findById(dto.getSupplierId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setSupplierCode(supplier.getCode()); + this.setSupplierName(supplier.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setTotalDiscountAmount(dto.getTotalDiscountAmount()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(SettleSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/customer/CustomerSettleSheetExportModel.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/customer/CustomerSettleSheetExportModel.java new file mode 100644 index 0000000..b192681 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/excel/sheet/customer/CustomerSettleSheetExportModel.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.settle.excel.sheet.customer; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.excel.ExcelModel; +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.basedata.entity.Customer; +import com.lframework.xingyun.basedata.service.customer.CustomerService; +import com.lframework.xingyun.settle.entity.CustomerSettleSheet; +import com.lframework.xingyun.settle.enums.CustomerSettleSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +@Data +public class CustomerSettleSheetExportModel extends BaseBo implements + ExcelModel { + + /** + * 业务单据号 + */ + @ExcelProperty("业务单据号") + private String code; + + /** + * 客户编号 + */ + @ApiModelProperty("客户编号") + private String customerCode; + + /** + * 客户名称 + */ + @ApiModelProperty("客户名称") + private String customerName; + + /** + * 实付总金额 + */ + @ExcelProperty("实付总金额") + private BigDecimal totalAmount; + + /** + * 优惠总金额 + */ + @ExcelProperty("优惠总金额") + private BigDecimal totalDiscountAmount; + + /** + * 操作时间 + */ + @ExcelProperty("操作时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date createTime; + + /** + * 操作人 + */ + @ExcelProperty("操作人") + private String createBy; + + /** + * 审核状态 + */ + @ExcelProperty("审核状态") + private String status; + + /** + * 审核时间 + */ + @ExcelProperty("审核时间") + @DateTimeFormat(StringPool.DATE_TIME_PATTERN) + private Date approveTime; + + /** + * 审核人 + */ + @ExcelProperty("审核人") + private String approveBy; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String description; + + public CustomerSettleSheetExportModel() { + + } + + public CustomerSettleSheetExportModel(CustomerSettleSheet dto) { + + super(dto); + } + + @Override + public BaseBo convert(CustomerSettleSheet dto) { + + return this; + } + + @Override + protected void afterInit(CustomerSettleSheet dto) { + + CustomerService customerService = ApplicationUtil.getBean(CustomerService.class); + Customer customer = customerService.findById(dto.getCustomerId()); + + UserService userService = ApplicationUtil.getBean(UserService.class); + UserDto approveBy = null; + if (!StringUtil.isBlank(dto.getApproveBy())) { + approveBy = userService.findById(dto.getApproveBy()); + } + + this.setCode(dto.getCode()); + this.setCustomerCode(customer.getCode()); + this.setCustomerName(customer.getName()); + this.setTotalAmount(dto.getTotalAmount()); + this.setTotalDiscountAmount(dto.getTotalDiscountAmount()); + this.setCreateTime(DateUtil.toDate(dto.getCreateTime())); + this.setStatus(EnumUtil.getDesc(CustomerSettleSheetStatus.class, dto.getStatus())); + if (approveBy != null) { + this.setApproveBy(approveBy.getName()); + } + + if (dto.getApproveTime() != null) { + this.setApproveTime(DateUtil.toDate(dto.getApproveTime())); + } + this.setDescription(dto.getDescription()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetDetailServiceImpl.java new file mode 100644 index 0000000..78b0521 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetDetailServiceImpl.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheetDetail; +import com.lframework.xingyun.settle.mappers.CustomerSettleCheckSheetDetailMapper; +import com.lframework.xingyun.settle.service.CustomerSettleCheckSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class CustomerSettleCheckSheetDetailServiceImpl + extends + BaseMpServiceImpl + implements CustomerSettleCheckSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetServiceImpl.java new file mode 100644 index 0000000..9ddaaa8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleCheckSheetServiceImpl.java @@ -0,0 +1,856 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.entity.SaleOutSheet; +import com.lframework.xingyun.sc.entity.SaleReturn; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.service.sale.SaleOutSheetService; +import com.lframework.xingyun.sc.service.sale.SaleReturnService; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheetDetail; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetCalcType; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetType; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.CustomerSettleCheckSheetMapper; +import com.lframework.xingyun.settle.service.CustomerSettleCheckSheetDetailService; +import com.lframework.xingyun.settle.service.CustomerSettleCheckSheetService; +import com.lframework.xingyun.settle.service.CustomerSettleFeeSheetService; +import com.lframework.xingyun.settle.service.CustomerSettlePreSheetService; +import com.lframework.xingyun.settle.vo.check.customer.ApprovePassCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.ApproveRefuseCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.BatchApprovePassCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.BatchApproveRefuseCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.CreateCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.CustomerSettleCheckSheetItemVo; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerUnCheckBizItemVo; +import com.lframework.xingyun.settle.vo.check.customer.UpdateCustomerSettleCheckSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CustomerSettleCheckSheetServiceImpl extends + BaseMpServiceImpl + implements CustomerSettleCheckSheetService { + + @Autowired + private CustomerSettleCheckSheetDetailService customerSettleCheckSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private SaleOutSheetService saleOutSheetService; + + @Autowired + private SaleReturnService saleReturnService; + + @Autowired + private CustomerSettleFeeSheetService customerSettleFeeSheetService; + + @Autowired + private CustomerSettlePreSheetService customerSettlePreSheetService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettleCheckSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryCustomerSettleCheckSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public CustomerSettleCheckSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建客户对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建对账单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheet sheet = new CustomerSettleCheckSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode( + generateCodeService.generate(GenerateCodeTypePool.CUSTOMER_SETTLE_CHECK_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettleCheckSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改客户对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改对账单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户对账单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleCheckSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleCheckSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户对账单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("客户对账单无法修改!"); + } + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleCheckSheetDetail.class) + .eq(CustomerSettleCheckSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(CustomerSettleCheckSheetDetail::getOrderNo); + List sheetDetails = customerSettleCheckSheetDetailService.list( + queryDetailWrapper); + for (CustomerSettleCheckSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId(), sheetDetail.getBizType()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleCheckSheetDetail.class) + .eq(CustomerSettleCheckSheetDetail::getSheetId, sheet.getId()); + customerSettleCheckSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettleCheckSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleCheckSheetStatus.CREATED); + statusList.add(CustomerSettleCheckSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .set(CustomerSettleCheckSheet::getApproveBy, null) + .set(CustomerSettleCheckSheet::getApproveTime, null) + .set(CustomerSettleCheckSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(CustomerSettleCheckSheet::getId, sheet.getId()) + .in(CustomerSettleCheckSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户对账单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过客户对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户对账单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleCheckSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleCheckSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户对账单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("客户对账单无法审核通过!"); + } + + sheet.setStatus(CustomerSettleCheckSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleCheckSheetStatus.CREATED); + statusList.add(CustomerSettleCheckSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .eq(CustomerSettleCheckSheet::getId, sheet.getId()) + .in(CustomerSettleCheckSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户对账单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassCustomerSettleCheckSheetVo approveVo = new ApprovePassCustomerSettleCheckSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝客户对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户对账单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleCheckSheetStatus.CREATED) { + if (sheet.getStatus() == CustomerSettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户对账单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == CustomerSettleCheckSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("客户对账单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("客户对账单无法审核拒绝!"); + } + + sheet.setStatus(CustomerSettleCheckSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleCheckSheetStatus.CREATED); + statusList.add(CustomerSettleCheckSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .eq(CustomerSettleCheckSheet::getId, sheet.getId()) + .in(CustomerSettleCheckSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户对账单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassCustomerSettleCheckSheetVo approveVo = new ApprovePassCustomerSettleCheckSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户对账单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseCustomerSettleCheckSheetVo vo) { + + CustomerSettleCheckSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseCustomerSettleCheckSheetVo approveVo = new ApproveRefuseCustomerSettleCheckSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户对账单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除客户对账单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + CustomerSettleCheckSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("客户对账单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleCheckSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleCheckSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == CustomerSettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的客户对账单不允许执行删除操作!"); + } + + throw new DefaultClientException("客户对账单无法删除!"); + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleCheckSheetDetail.class) + .eq(CustomerSettleCheckSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(CustomerSettleCheckSheetDetail::getOrderNo); + List sheetDetails = customerSettleCheckSheetDetailService.list( + queryDetailWrapper); + for (CustomerSettleCheckSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId(), sheetDetail.getBizType()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleCheckSheetDetail.class) + .eq(CustomerSettleCheckSheetDetail::getSheetId, sheet.getId()); + customerSettleCheckSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + CustomerSettleCheckSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个客户对账单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Override + public CustomerSettleCheckBizItemDto getBizItem(String id, + CustomerSettleCheckSheetBizType bizType) { + + CustomerSettleCheckBizItemDto result = new CustomerSettleCheckBizItemDto(); + + switch (bizType) { + case OUT_SHEET: { + SaleOutSheet outSheet = saleOutSheetService.getById(id); + + result.setId(outSheet.getId()); + result.setCode(outSheet.getCode()); + result.setTotalAmount(outSheet.getTotalAmount()); + result.setApproveTime(outSheet.getApproveTime()); + result.setCalcType(CustomerSettleCheckSheetCalcType.ADD); + break; + } + case SALE_RETURN: { + SaleReturn saleReturn = saleReturnService.getById(id); + + result.setId(saleReturn.getId()); + result.setCode(saleReturn.getCode()); + result.setTotalAmount(saleReturn.getTotalAmount()); + result.setApproveTime(saleReturn.getApproveTime()); + result.setCalcType(CustomerSettleCheckSheetCalcType.SUB); + break; + } + case SETTLE_FEE_SHEET: { + CustomerSettleFeeSheet feeSheet = customerSettleFeeSheetService.getById(id); + + result.setId(feeSheet.getId()); + result.setCode(feeSheet.getCode()); + result.setTotalAmount(feeSheet.getTotalAmount()); + result.setApproveTime(feeSheet.getApproveTime()); + result.setCalcType(feeSheet.getSheetType() == CustomerSettleFeeSheetType.RECEIVE ? + CustomerSettleCheckSheetCalcType.ADD : + CustomerSettleCheckSheetCalcType.SUB); + break; + } + case SETTLE_PRE_SHEET: { + CustomerSettlePreSheet preSheet = customerSettlePreSheetService.getById(id); + + result.setId(preSheet.getId()); + result.setCode(preSheet.getCode()); + result.setTotalAmount(preSheet.getTotalAmount()); + result.setApproveTime(preSheet.getApproveTime()); + result.setCalcType(CustomerSettleCheckSheetCalcType.SUB); + break; + } + default: { + throw new DefaultSysException("未知的CustomerSettleCheckSheetBizType"); + } + } + + result.setBizType(bizType); + if (result.getCalcType() == CustomerSettleCheckSheetCalcType.SUB) { + result.setTotalAmount(result.getTotalAmount().negate()); + } + + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemUnSettle(String id, CustomerSettleCheckSheetBizType bizType) { + + CustomerSettleCheckBizItemDto item = this.getBizItem(id, bizType); + + switch (bizType) { + case OUT_SHEET: { + int count = saleOutSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SALE_RETURN: { + int count = saleReturnService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_FEE_SHEET: { + int count = customerSettleFeeSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_PRE_SHEET: { + int count = customerSettlePreSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + default: { + throw new DefaultSysException("未知的CustomerSettleCheckSheetBizType"); + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemPartSettle(String id, CustomerSettleCheckSheetBizType bizType) { + + CustomerSettleCheckBizItemDto item = this.getBizItem(id, bizType); + + switch (bizType) { + case OUT_SHEET: { + int count = saleOutSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SALE_RETURN: { + int count = saleReturnService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_FEE_SHEET: { + int count = customerSettleFeeSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_PRE_SHEET: { + int count = customerSettlePreSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + default: { + throw new DefaultSysException("未知的CustomerSettleCheckSheetBizType"); + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemSettled(String id, CustomerSettleCheckSheetBizType bizType) { + + CustomerSettleCheckBizItemDto item = this.getBizItem(id, bizType); + + switch (bizType) { + case OUT_SHEET: { + int count = saleOutSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + case SALE_RETURN: { + int count = saleReturnService.setSettled(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + case SETTLE_FEE_SHEET: { + int count = customerSettleFeeSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + case SETTLE_PRE_SHEET: { + int count = customerSettlePreSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException( + "单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + default: { + throw new DefaultSysException("未知的CustomerSettleCheckSheetBizType"); + } + } + } + + @Override + public List getUnCheckBizItems( + QueryCustomerUnCheckBizItemVo vo) { + + List results = new ArrayList<>(); + + List outSheetList = saleOutSheetService.getApprovedList(vo.getCustomerId(), + vo.getStartTime(), + vo.getEndTime(), SettleStatus.UN_SETTLE); + + List saleReturnList = saleReturnService.getApprovedList(vo.getCustomerId(), + vo.getStartTime(), vo.getEndTime(), SettleStatus.UN_SETTLE); + + List feeSheetList = customerSettleFeeSheetService.getApprovedList( + vo.getCustomerId(), vo.getStartTime(), + vo.getEndTime(), SettleStatus.UN_SETTLE); + + List preSheetList = customerSettlePreSheetService.getApprovedList( + vo.getCustomerId(), vo.getStartTime(), + vo.getEndTime(), SettleStatus.UN_SETTLE); + + if (!CollectionUtil.isEmpty(outSheetList)) { + for (SaleOutSheet item : outSheetList) { + CustomerSettleCheckBizItemDto result = new CustomerSettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(CustomerSettleCheckSheetBizType.OUT_SHEET); + result.setCalcType(CustomerSettleCheckSheetCalcType.ADD); + + results.add(result); + } + } + + if (!CollectionUtil.isEmpty(saleReturnList)) { + for (SaleReturn item : saleReturnList) { + CustomerSettleCheckBizItemDto result = new CustomerSettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(CustomerSettleCheckSheetBizType.SALE_RETURN); + result.setCalcType(CustomerSettleCheckSheetCalcType.SUB); + + results.add(result); + } + } + + if (!CollectionUtil.isEmpty(feeSheetList)) { + for (CustomerSettleFeeSheet item : feeSheetList) { + CustomerSettleCheckBizItemDto result = new CustomerSettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(CustomerSettleCheckSheetBizType.SETTLE_FEE_SHEET); + result.setCalcType(item.getSheetType() == CustomerSettleFeeSheetType.RECEIVE ? + CustomerSettleCheckSheetCalcType.ADD : + CustomerSettleCheckSheetCalcType.SUB); + + results.add(result); + } + } + + if (!CollectionUtil.isEmpty(preSheetList)) { + for (CustomerSettlePreSheet item : preSheetList) { + CustomerSettleCheckBizItemDto result = new CustomerSettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(CustomerSettleCheckSheetBizType.SETTLE_PRE_SHEET); + result.setCalcType(CustomerSettleCheckSheetCalcType.SUB); + + results.add(result); + } + } + + results.stream().filter(t -> t.getCalcType() == CustomerSettleCheckSheetCalcType.SUB) + .forEach(t -> t.setTotalAmount(t.getTotalAmount().negate())); + + return results; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .set(CustomerSettleCheckSheet::getSettleStatus, SettleStatus.UN_SETTLE) + .eq(CustomerSettleCheckSheet::getId, id) + .eq(CustomerSettleCheckSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .set(CustomerSettleCheckSheet::getSettleStatus, SettleStatus.PART_SETTLE) + .eq(CustomerSettleCheckSheet::getId, id) + .in(CustomerSettleCheckSheet::getSettleStatus, SettleStatus.UN_SETTLE, + SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .set(CustomerSettleCheckSheet::getSettleStatus, SettleStatus.SETTLED) + .eq(CustomerSettleCheckSheet::getId, id) + .in(CustomerSettleCheckSheet::getSettleStatus, SettleStatus.UN_SETTLE, + SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleCheckSheetDetail.class) + .eq(CustomerSettleCheckSheetDetail::getSheetId, id) + .orderByAsc(CustomerSettleCheckSheetDetail::getOrderNo); + List sheetDetails = customerSettleCheckSheetDetailService.list( + queryDetailWrapper); + for (CustomerSettleCheckSheetDetail sheetDetail : sheetDetails) { + this.setBizItemSettled(sheetDetail.getBizId(), sheetDetail.getBizType()); + } + + return count; + } + + @Override + public List getApprovedList(String customerId, + LocalDateTime startTime, LocalDateTime endTime) { + + return getBaseMapper().getApprovedList(customerId, startTime, endTime); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setSettleAmount(String id, BigDecimal totalPayedAmount, + BigDecimal totalDiscountAmount) { + + CustomerSettleCheckSheet checkSheet = getBaseMapper().selectById(id); + BigDecimal remainTotalPayAmount = NumberUtil.sub(checkSheet.getTotalPayAmount(), + checkSheet.getTotalPayedAmount(), checkSheet.getTotalDiscountAmount(), + totalPayedAmount, + totalDiscountAmount); + BigDecimal totalPayAmount = NumberUtil.sub(checkSheet.getTotalPayAmount(), + checkSheet.getTotalPayedAmount(), + checkSheet.getTotalDiscountAmount()); + if (NumberUtil.lt(checkSheet.getTotalPayAmount(), 0)) { + if (NumberUtil.gt(remainTotalPayAmount, 0)) { + throw new DefaultClientException( + "对账单:" + checkSheet.getCode() + ",剩余收款金额为" + totalPayAmount + "元,本次收款金额为" + + NumberUtil.add( + totalPayedAmount, totalDiscountAmount) + "元,无法结算!"); + } + } + if (NumberUtil.gt(checkSheet.getTotalPayAmount(), 0)) { + if (NumberUtil.lt(remainTotalPayAmount, 0)) { + throw new DefaultClientException( + "对账单:" + checkSheet.getCode() + ",剩余收款金额为" + totalPayAmount + "元,本次收款金额为" + + NumberUtil.add( + totalPayedAmount, totalDiscountAmount) + "元,无法结算!"); + } + } + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleCheckSheet.class) + .set(CustomerSettleCheckSheet::getTotalPayedAmount, + NumberUtil.add(totalPayedAmount, checkSheet.getTotalPayedAmount())) + .set(CustomerSettleCheckSheet::getTotalDiscountAmount, + NumberUtil.add(totalDiscountAmount, checkSheet.getTotalDiscountAmount())) + .eq(CustomerSettleCheckSheet::getId, id) + .eq(CustomerSettleCheckSheet::getTotalPayedAmount, checkSheet.getTotalPayedAmount()) + .eq(CustomerSettleCheckSheet::getTotalDiscountAmount, + checkSheet.getTotalDiscountAmount()); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("结账单:" + checkSheet.getCode() + ",信息已过期,请刷新重试!"); + } + + if (NumberUtil.equal(remainTotalPayAmount, 0)) { + this.setSettled(id); + } + } + + private void create(CustomerSettleCheckSheet sheet, CreateCustomerSettleCheckSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + BigDecimal totalPayAmount = BigDecimal.ZERO; + + int orderNo = 0; + for (CustomerSettleCheckSheetItemVo itemVo : vo.getItems()) { + orderNo++; + CustomerSettleCheckBizItemDto item = this.getBizItem(itemVo.getId(), + EnumUtil.getByCode(CustomerSettleCheckSheetBizType.class, itemVo.getBizType())); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行业务单据不存在!"); + } + CustomerSettleCheckSheetDetail detail = new CustomerSettleCheckSheetDetail(); + + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setBizId(itemVo.getId()); + detail.setBizType( + EnumUtil.getByCode(CustomerSettleCheckSheetBizType.class, itemVo.getBizType())); + detail.setCalcType(item.getCalcType()); + if (item.getCalcType() == CustomerSettleCheckSheetCalcType.ADD) { + if (NumberUtil.lt(itemVo.getPayAmount(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行业务单据应收金额不允许小于0!"); + } + } else { + if (NumberUtil.gt(itemVo.getPayAmount(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行业务单据应收金额不允许大于0!"); + } + } + detail.setPayAmount(itemVo.getPayAmount()); + detail.setDescription(itemVo.getDescription()); + detail.setOrderNo(orderNo); + + customerSettleCheckSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, item.getTotalAmount()); + totalPayAmount = NumberUtil.add(totalPayAmount, itemVo.getPayAmount()); + + //将所有的单据的结算状态更新 + this.setBizItemPartSettle(detail.getBizId(), detail.getBizType()); + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setCustomerId(vo.getCustomerId()); + sheet.setTotalAmount(totalAmount); + sheet.setTotalPayAmount(totalPayAmount); + sheet.setTotalPayedAmount(BigDecimal.ZERO); + sheet.setTotalDiscountAmount(BigDecimal.ZERO); + sheet.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR + : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setSettleStatus(SettleStatus.UN_SETTLE); + sheet.setStartDate(vo.getStartDate()); + sheet.setEndDate(vo.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetDetailServiceImpl.java new file mode 100644 index 0000000..8c8b20e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheetDetail; +import com.lframework.xingyun.settle.mappers.CustomerSettleFeeSheetDetailMapper; +import com.lframework.xingyun.settle.service.CustomerSettleFeeSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class CustomerSettleFeeSheetDetailServiceImpl extends + BaseMpServiceImpl + implements CustomerSettleFeeSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetServiceImpl.java new file mode 100644 index 0000000..91ef597 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleFeeSheetServiceImpl.java @@ -0,0 +1,464 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.fee.customer.CustomerSettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheetDetail; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetType; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.CustomerSettleFeeSheetMapper; +import com.lframework.xingyun.settle.service.CustomerSettleFeeSheetDetailService; +import com.lframework.xingyun.settle.service.CustomerSettleFeeSheetService; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import com.lframework.xingyun.settle.vo.fee.customer.ApprovePassCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.ApproveRefuseCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.BatchApprovePassCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.BatchApproveRefuseCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.CreateCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.CustomerSettleFeeSheetItemVo; +import com.lframework.xingyun.settle.vo.fee.customer.QueryCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.UpdateCustomerSettleFeeSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CustomerSettleFeeSheetServiceImpl extends + BaseMpServiceImpl + implements CustomerSettleFeeSheetService { + + @Autowired + private CustomerSettleFeeSheetDetailService customerSettleFeeSheetDetailService; + + @Autowired + private SettleOutItemService settleOutItemService; + + @Autowired + private SettleInItemService settleInItemService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettleFeeSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryCustomerSettleFeeSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public CustomerSettleFeeSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建客户费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建费用单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheet sheet = new CustomerSettleFeeSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.CUSTOMER_SETTLE_FEE_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettleFeeSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改客户费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改费用单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户费用单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleFeeSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleFeeSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户费用单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("客户费用单无法修改!"); + } + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleFeeSheetDetail.class) + .eq(CustomerSettleFeeSheetDetail::getSheetId, sheet.getId()); + customerSettleFeeSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettleFeeSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleFeeSheetStatus.CREATED); + statusList.add(CustomerSettleFeeSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleFeeSheet.class) + .set(CustomerSettleFeeSheet::getApproveBy, null) + .set(CustomerSettleFeeSheet::getApproveTime, null) + .set(CustomerSettleFeeSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(CustomerSettleFeeSheet::getId, sheet.getId()) + .in(CustomerSettleFeeSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户费用单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过客户费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户费用单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleFeeSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleFeeSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户费用单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("客户费用单无法审核通过!"); + } + + sheet.setStatus(CustomerSettleFeeSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleFeeSheetStatus.CREATED); + statusList.add(CustomerSettleFeeSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleFeeSheet.class) + .eq(CustomerSettleFeeSheet::getId, sheet.getId()) + .in(CustomerSettleFeeSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户费用单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassCustomerSettleFeeSheetVo approveVo = new ApprovePassCustomerSettleFeeSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝客户费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户费用单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleFeeSheetStatus.CREATED) { + if (sheet.getStatus() == CustomerSettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户费用单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == CustomerSettleFeeSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("客户费用单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("客户费用单无法审核拒绝!"); + } + + sheet.setStatus(CustomerSettleFeeSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleFeeSheetStatus.CREATED); + statusList.add(CustomerSettleFeeSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleFeeSheet.class) + .eq(CustomerSettleFeeSheet::getId, sheet.getId()) + .in(CustomerSettleFeeSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户费用单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassCustomerSettleFeeSheetVo approveVo = new ApprovePassCustomerSettleFeeSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个客户费用单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseCustomerSettleFeeSheetVo vo) { + + CustomerSettleFeeSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseCustomerSettleFeeSheetVo approveVo = new ApproveRefuseCustomerSettleFeeSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个客户费用单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除客户费用单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + CustomerSettleFeeSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("客户费用单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleFeeSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleFeeSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == CustomerSettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的客户费用单不允许执行删除操作!"); + } + + throw new DefaultClientException("客户费用单无法删除!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleFeeSheetDetail.class) + .eq(CustomerSettleFeeSheetDetail::getSheetId, sheet.getId()); + customerSettleFeeSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + CustomerSettleFeeSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException( + "第" + orderNo + "个客户费用单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleFeeSheet.class) + .set(CustomerSettleFeeSheet::getSettleStatus, SettleStatus.UN_SETTLE) + .eq(CustomerSettleFeeSheet::getId, id) + .eq(CustomerSettleFeeSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleFeeSheet.class) + .set(CustomerSettleFeeSheet::getSettleStatus, SettleStatus.PART_SETTLE) + .eq(CustomerSettleFeeSheet::getId, id) + .in(CustomerSettleFeeSheet::getSettleStatus, SettleStatus.UN_SETTLE, + SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettleFeeSheet.class) + .set(CustomerSettleFeeSheet::getSettleStatus, SettleStatus.SETTLED) + .eq(CustomerSettleFeeSheet::getId, id) + .in(CustomerSettleFeeSheet::getSettleStatus, SettleStatus.UN_SETTLE, + SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(customerId, startTime, endTime, settleStatus); + } + + private void create(CustomerSettleFeeSheet sheet, CreateCustomerSettleFeeSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (CustomerSettleFeeSheetItemVo itemVo : vo.getItems()) { + if (vo.getSheetType() == CustomerSettleFeeSheetType.RECEIVE.getCode().intValue()) { + SettleInItem item = settleInItemService.findById(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行项目不存在!"); + } + } else { + SettleOutItem item = settleOutItemService.findById(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行项目不存在!"); + } + } + CustomerSettleFeeSheetDetail detail = new CustomerSettleFeeSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setItemId(itemVo.getId()); + detail.setAmount(itemVo.getAmount()); + detail.setOrderNo(orderNo); + + customerSettleFeeSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, detail.getAmount()); + + orderNo++; + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setCustomerId(vo.getCustomerId()); + sheet.setSheetType(EnumUtil.getByCode(CustomerSettleFeeSheetType.class, vo.getSheetType())); + sheet.setTotalAmount(totalAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setSettleStatus(SettleStatus.UN_SETTLE); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetDetailServiceImpl.java new file mode 100644 index 0000000..bee9c3a --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheetDetail; +import com.lframework.xingyun.settle.mappers.CustomerSettlePreSheetDetailMapper; +import com.lframework.xingyun.settle.service.CustomerSettlePreSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class CustomerSettlePreSheetDetailServiceImpl extends + BaseMpServiceImpl + implements CustomerSettlePreSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetServiceImpl.java new file mode 100644 index 0000000..9bec66d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettlePreSheetServiceImpl.java @@ -0,0 +1,446 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.pre.customer.CustomerSettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheetDetail; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.enums.CustomerSettlePreSheetStatus; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.CustomerSettlePreSheetMapper; +import com.lframework.xingyun.settle.service.CustomerSettlePreSheetDetailService; +import com.lframework.xingyun.settle.service.CustomerSettlePreSheetService; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.vo.pre.customer.ApprovePassCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.ApproveRefuseCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.BatchApprovePassCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.BatchApproveRefuseCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.CreateCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.CustomerSettlePreSheetItemVo; +import com.lframework.xingyun.settle.vo.pre.customer.QueryCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.UpdateCustomerSettlePreSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CustomerSettlePreSheetServiceImpl extends + BaseMpServiceImpl + implements CustomerSettlePreSheetService { + + @Autowired + private CustomerSettlePreSheetDetailService settlePreSheetDetailService; + + @Autowired + private SettleInItemService settleInItemService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettlePreSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryCustomerSettlePreSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public CustomerSettlePreSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建客户预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建预付款单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheet sheet = new CustomerSettlePreSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.CUSTOMER_SETTLE_PRE_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettlePreSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改客户预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改预付款单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户预付款单不存在!"); + } + + if (sheet.getStatus() != CustomerSettlePreSheetStatus.CREATED + && sheet.getStatus() != CustomerSettlePreSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户预付款单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("客户预付款单无法修改!"); + } + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettlePreSheetDetail.class) + .eq(CustomerSettlePreSheetDetail::getSheetId, sheet.getId()); + settlePreSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettlePreSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettlePreSheetStatus.CREATED); + statusList.add(CustomerSettlePreSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettlePreSheet.class) + .set(CustomerSettlePreSheet::getApproveBy, null) + .set(CustomerSettlePreSheet::getApproveTime, null) + .set(CustomerSettlePreSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(CustomerSettlePreSheet::getId, sheet.getId()) + .in(CustomerSettlePreSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户预付款单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过客户预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户预付款单不存在!"); + } + + if (sheet.getStatus() != CustomerSettlePreSheetStatus.CREATED + && sheet.getStatus() != CustomerSettlePreSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户预付款单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("客户预付款单无法审核通过!"); + } + + sheet.setStatus(CustomerSettlePreSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettlePreSheetStatus.CREATED); + statusList.add(CustomerSettlePreSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettlePreSheet.class) + .eq(CustomerSettlePreSheet::getId, sheet.getId()) + .in(CustomerSettlePreSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户预付款单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassCustomerSettlePreSheetVo approveVo = new ApprovePassCustomerSettlePreSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝客户预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户预付款单不存在!"); + } + + if (sheet.getStatus() != CustomerSettlePreSheetStatus.CREATED) { + if (sheet.getStatus() == CustomerSettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户预付款单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == CustomerSettlePreSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("客户预付款单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("客户预付款单无法审核拒绝!"); + } + + sheet.setStatus(CustomerSettlePreSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettlePreSheetStatus.CREATED); + statusList.add(CustomerSettlePreSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettlePreSheet.class) + .eq(CustomerSettlePreSheet::getId, sheet.getId()) + .in(CustomerSettlePreSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户预付款单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassCustomerSettlePreSheetVo approveVo = new ApprovePassCustomerSettlePreSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户预付款单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseCustomerSettlePreSheetVo vo) { + + CustomerSettlePreSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseCustomerSettlePreSheetVo approveVo = new ApproveRefuseCustomerSettlePreSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户预付款单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除客户预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + CustomerSettlePreSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("客户预付款单不存在!"); + } + + if (sheet.getStatus() != CustomerSettlePreSheetStatus.CREATED + && sheet.getStatus() != CustomerSettlePreSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == CustomerSettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的客户预付款单不允许执行删除操作!"); + } + + throw new DefaultClientException("客户预付款单无法删除!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettlePreSheetDetail.class) + .eq(CustomerSettlePreSheetDetail::getSheetId, sheet.getId()); + settlePreSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + CustomerSettlePreSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户预付款单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettlePreSheet.class) + .set(CustomerSettlePreSheet::getSettleStatus, SettleStatus.UN_SETTLE) + .eq(CustomerSettlePreSheet::getId, id) + .eq(CustomerSettlePreSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettlePreSheet.class) + .set(CustomerSettlePreSheet::getSettleStatus, SettleStatus.PART_SETTLE) + .eq(CustomerSettlePreSheet::getId, id) + .in(CustomerSettlePreSheet::getSettleStatus, SettleStatus.UN_SETTLE, + SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate( + CustomerSettlePreSheet.class) + .set(CustomerSettlePreSheet::getSettleStatus, SettleStatus.SETTLED) + .eq(CustomerSettlePreSheet::getId, id) + .in(CustomerSettlePreSheet::getSettleStatus, SettleStatus.UN_SETTLE, + SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(customerId, startTime, endTime, settleStatus); + } + + private void create(CustomerSettlePreSheet sheet, CreateCustomerSettlePreSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (CustomerSettlePreSheetItemVo itemVo : vo.getItems()) { + SettleInItem item = settleInItemService.findById(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行项目不存在!"); + } + CustomerSettlePreSheetDetail detail = new CustomerSettlePreSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setItemId(itemVo.getId()); + detail.setAmount(itemVo.getAmount()); + detail.setOrderNo(orderNo); + + settlePreSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, detail.getAmount()); + + orderNo++; + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setCustomerId(vo.getCustomerId()); + sheet.setTotalAmount(totalAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setSettleStatus(SettleStatus.UN_SETTLE); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetDetailServiceImpl.java new file mode 100644 index 0000000..83084c0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.CustomerSettleSheetDetail; +import com.lframework.xingyun.settle.mappers.CustomerSettleSheetDetailMapper; +import com.lframework.xingyun.settle.service.CustomerSettleSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class CustomerSettleSheetDetailServiceImpl extends + BaseMpServiceImpl + implements CustomerSettleSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetServiceImpl.java new file mode 100644 index 0000000..ef25b82 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/CustomerSettleSheetServiceImpl.java @@ -0,0 +1,558 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import com.lframework.xingyun.settle.entity.CustomerSettleSheet; +import com.lframework.xingyun.settle.entity.CustomerSettleSheetDetail; +import com.lframework.xingyun.settle.enums.CustomerSettleSheetStatus; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.CustomerSettleSheetMapper; +import com.lframework.xingyun.settle.service.CustomerSettleCheckSheetService; +import com.lframework.xingyun.settle.service.CustomerSettleSheetDetailService; +import com.lframework.xingyun.settle.service.CustomerSettleSheetService; +import com.lframework.xingyun.settle.vo.sheet.customer.ApprovePassCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.ApproveRefuseCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.BatchApprovePassCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.BatchApproveRefuseCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.CreateCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.CustomerSettleSheetItemVo; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerUnSettleBizItemVo; +import com.lframework.xingyun.settle.vo.sheet.customer.UpdateCustomerSettleSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CustomerSettleSheetServiceImpl extends + BaseMpServiceImpl + implements CustomerSettleSheetService { + + @Autowired + private CustomerSettleSheetDetailService customerSettleSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private CustomerSettleCheckSheetService customerSettleCheckSheetService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettleSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryCustomerSettleSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public CustomerSettleSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建客户结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建结算单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateCustomerSettleSheetVo vo) { + + CustomerSettleSheet sheet = new CustomerSettleSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.CUSTOMER_SETTLE_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettleSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改客户结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改结算单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateCustomerSettleSheetVo vo) { + + CustomerSettleSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户结算单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户结算单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("客户结算单无法修改!"); + } + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleSheetDetail.class) + .eq(CustomerSettleSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(CustomerSettleSheetDetail::getOrderNo); + List sheetDetails = customerSettleSheetDetailService.list( + queryDetailWrapper); + for (CustomerSettleSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleSheetDetail.class) + .eq(CustomerSettleSheetDetail::getSheetId, sheet.getId()); + customerSettleSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(CustomerSettleSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleSheetStatus.CREATED); + statusList.add(CustomerSettleSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(CustomerSettleSheet.class) + .set(CustomerSettleSheet::getApproveBy, null).set(CustomerSettleSheet::getApproveTime, null) + .set(CustomerSettleSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(CustomerSettleSheet::getId, sheet.getId()) + .in(CustomerSettleSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户结算单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过客户结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassCustomerSettleSheetVo vo) { + + CustomerSettleSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户结算单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == CustomerSettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户结算单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("客户结算单无法审核通过!"); + } + + sheet.setStatus(CustomerSettleSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleSheetStatus.CREATED); + statusList.add(CustomerSettleSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(CustomerSettleSheet.class) + .eq(CustomerSettleSheet::getId, sheet.getId()) + .in(CustomerSettleSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户结算单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleSheetDetail.class) + .eq(CustomerSettleSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(CustomerSettleSheetDetail::getOrderNo); + List details = customerSettleSheetDetailService.list( + queryDetailWrapper); + for (CustomerSettleSheetDetail detail : details) { + customerSettleCheckSheetService.setSettleAmount(detail.getBizId(), detail.getPayAmount(), + detail.getDiscountAmount()); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateCustomerSettleSheetVo vo) { + + CustomerSettleSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassCustomerSettleSheetVo approveVo = new ApprovePassCustomerSettleSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝客户结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseCustomerSettleSheetVo vo) { + + CustomerSettleSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("客户结算单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleSheetStatus.CREATED) { + if (sheet.getStatus() == CustomerSettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("客户结算单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == CustomerSettleSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("客户结算单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("客户结算单无法审核拒绝!"); + } + + sheet.setStatus(CustomerSettleSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(CustomerSettleSheetStatus.CREATED); + statusList.add(CustomerSettleSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(CustomerSettleSheet.class) + .eq(CustomerSettleSheet::getId, sheet.getId()) + .in(CustomerSettleSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("客户结算单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassCustomerSettleSheetVo vo) { + + CustomerSettleSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassCustomerSettleSheetVo approveVo = new ApprovePassCustomerSettleSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户结算单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseCustomerSettleSheetVo vo) { + + CustomerSettleSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseCustomerSettleSheetVo approveVo = new ApproveRefuseCustomerSettleSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户结算单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除客户结算单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + CustomerSettleSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("客户结算单不存在!"); + } + + if (sheet.getStatus() != CustomerSettleSheetStatus.CREATED + && sheet.getStatus() != CustomerSettleSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == CustomerSettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的客户结算单不允许执行删除操作!"); + } + + throw new DefaultClientException("客户结算单无法删除!"); + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleSheetDetail.class) + .eq(CustomerSettleSheetDetail::getSheetId, sheet.getId()) + .orderByAsc(CustomerSettleSheetDetail::getOrderNo); + List sheetDetails = customerSettleSheetDetailService.list( + queryDetailWrapper); + for (CustomerSettleSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery( + CustomerSettleSheetDetail.class) + .eq(CustomerSettleSheetDetail::getSheetId, sheet.getId()); + customerSettleSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + CustomerSettleSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个客户结算单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Override + public CustomerSettleBizItemDto getBizItem(String id) { + + CustomerSettleCheckSheet checkSheet = customerSettleCheckSheetService.getById(id); + + CustomerSettleBizItemDto result = new CustomerSettleBizItemDto(); + result.setId(checkSheet.getId()); + result.setCode(checkSheet.getCode()); + result.setTotalPayAmount(checkSheet.getTotalPayAmount()); + result.setTotalPayedAmount(checkSheet.getTotalPayedAmount()); + result.setTotalDiscountAmount(checkSheet.getTotalDiscountAmount()); + result.setTotalUnPayAmount( + NumberUtil.sub(checkSheet.getTotalPayAmount(), checkSheet.getTotalPayedAmount(), + checkSheet.getTotalDiscountAmount())); + result.setApproveTime(checkSheet.getApproveTime()); + + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemUnSettle(String id) { + + CustomerSettleCheckSheet item = customerSettleCheckSheetService.getById(id); + int count = customerSettleCheckSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "已结算,业务无法进行!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemPartSettle(String id) { + + CustomerSettleCheckSheet item = customerSettleCheckSheetService.getById(id); + int count = customerSettleCheckSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "已结算,业务无法进行!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemSettled(String id) { + + CustomerSettleCheckSheet item = customerSettleCheckSheetService.getById(id); + int count = customerSettleCheckSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "已结算,无法重复结算!"); + } + } + + @Override + public List getUnSettleBizItems(QueryCustomerUnSettleBizItemVo vo) { + + List results = new ArrayList<>(); + + List sheetList = customerSettleCheckSheetService.getApprovedList( + vo.getCustomerId(), + vo.getStartTime(), vo.getEndTime()); + + if (!CollectionUtil.isEmpty(sheetList)) { + for (CustomerSettleCheckSheet item : sheetList) { + CustomerSettleBizItemDto result = new CustomerSettleBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalPayAmount(item.getTotalPayAmount()); + result.setTotalPayedAmount(item.getTotalPayedAmount()); + result.setTotalDiscountAmount(item.getTotalDiscountAmount()); + result.setTotalUnPayAmount( + NumberUtil.sub(item.getTotalPayAmount(), item.getTotalPayedAmount(), + item.getTotalDiscountAmount())); + result.setApproveTime(item.getApproveTime()); + + results.add(result); + } + } + + return results; + } + + private void create(CustomerSettleSheet sheet, CreateCustomerSettleSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + BigDecimal totalDiscountAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (CustomerSettleSheetItemVo itemVo : vo.getItems()) { + CustomerSettleBizItemDto item = this.getBizItem(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行业务单据不存在!"); + } + + if (NumberUtil.lt(item.getTotalPayAmount(), 0)) { + if (NumberUtil.gt(itemVo.getPayAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实收金额不允许大于0!"); + } + + if (NumberUtil.gt(itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行优惠金额不允许大于0!"); + } + + if (NumberUtil.equal(itemVo.getPayAmount(), 0) && NumberUtil.equal( + itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实收金额、优惠金额不能同时等于0!"); + } + + if (NumberUtil.gt(item.getTotalUnPayAmount(), + NumberUtil.add(itemVo.getPayAmount(), itemVo.getDiscountAmount()))) { + throw new DefaultClientException("第" + orderNo + "行实收金额与优惠金额相加不允许小于未收款金额!"); + } + } else if (NumberUtil.gt(item.getTotalPayAmount(), 0)) { + if (NumberUtil.lt(itemVo.getPayAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实收金额不允许小于0!"); + } + + if (NumberUtil.lt(itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行优惠金额不允许小于0!"); + } + + if (NumberUtil.equal(itemVo.getPayAmount(), 0) && NumberUtil.equal( + itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实收金额、优惠金额不能同时等于0!"); + } + if (NumberUtil.lt(item.getTotalUnPayAmount(), + NumberUtil.add(itemVo.getPayAmount(), itemVo.getDiscountAmount()))) { + throw new DefaultClientException("第" + orderNo + "行实收金额与优惠金额相加不允许大于未收款金额!"); + } + } else { + // 单据应收款等于0 + if (!NumberUtil.equal(itemVo.getPayAmount(), 0) || !NumberUtil.equal( + itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实收金额、优惠金额必须同时等于0!"); + } + } + + CustomerSettleSheetDetail detail = new CustomerSettleSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setBizId(itemVo.getId()); + detail.setPayAmount(itemVo.getPayAmount()); + detail.setDiscountAmount(itemVo.getDiscountAmount()); + detail.setDescription(itemVo.getDescription()); + detail.setOrderNo(orderNo); + + customerSettleSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, itemVo.getPayAmount()); + totalDiscountAmount = NumberUtil.add(totalDiscountAmount, itemVo.getDiscountAmount()); + + //将所有的单据的结算状态更新 + this.setBizItemPartSettle(detail.getBizId()); + + orderNo++; + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setCustomerId(vo.getCustomerId()); + sheet.setTotalAmount(totalAmount); + sheet.setTotalDiscountAmount(totalDiscountAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setStartDate(vo.getStartDate()); + sheet.setEndDate(vo.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetDetailServiceImpl.java new file mode 100644 index 0000000..e540c35 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetDetailServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.SettleCheckSheetDetail; +import com.lframework.xingyun.settle.mappers.SettleCheckSheetDetailMapper; +import com.lframework.xingyun.settle.service.SettleCheckSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class SettleCheckSheetDetailServiceImpl + extends BaseMpServiceImpl + implements SettleCheckSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetServiceImpl.java new file mode 100644 index 0000000..96d593e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleCheckSheetServiceImpl.java @@ -0,0 +1,799 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.entity.PurchaseReturn; +import com.lframework.xingyun.sc.entity.ReceiveSheet; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.sc.service.purchase.PurchaseReturnService; +import com.lframework.xingyun.sc.service.purchase.ReceiveSheetService; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.check.SettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.SettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import com.lframework.xingyun.settle.entity.SettleCheckSheetDetail; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import com.lframework.xingyun.settle.enums.SettleCheckSheetBizType; +import com.lframework.xingyun.settle.enums.SettleCheckSheetCalcType; +import com.lframework.xingyun.settle.enums.SettleCheckSheetStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetType; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.SettleCheckSheetMapper; +import com.lframework.xingyun.settle.service.SettleCheckSheetDetailService; +import com.lframework.xingyun.settle.service.SettleCheckSheetService; +import com.lframework.xingyun.settle.service.SettleFeeSheetService; +import com.lframework.xingyun.settle.service.SettlePreSheetService; +import com.lframework.xingyun.settle.vo.check.ApprovePassSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.ApproveRefuseSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.BatchApprovePassSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.BatchApproveRefuseSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.CreateSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.QuerySettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.QueryUnCheckBizItemVo; +import com.lframework.xingyun.settle.vo.check.SettleCheckSheetItemVo; +import com.lframework.xingyun.settle.vo.check.UpdateSettleCheckSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SettleCheckSheetServiceImpl extends BaseMpServiceImpl + implements SettleCheckSheetService { + + @Autowired + private SettleCheckSheetDetailService settleCheckSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private ReceiveSheetService receiveSheetService; + + @Autowired + private PurchaseReturnService purchaseReturnService; + + @Autowired + private SettleFeeSheetService settleFeeSheetService; + + @Autowired + private SettlePreSheetService settlePreSheetService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySettleCheckSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySettleCheckSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public SettleCheckSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建供应商对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建对账单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSettleCheckSheetVo vo) { + + SettleCheckSheet sheet = new SettleCheckSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.SETTLE_CHECK_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(SettleCheckSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改供应商对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改对账单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSettleCheckSheetVo vo) { + + SettleCheckSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商对账单不存在!"); + } + + if (sheet.getStatus() != SettleCheckSheetStatus.CREATED + && sheet.getStatus() != SettleCheckSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商对账单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("供应商对账单无法修改!"); + } + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SettleCheckSheetDetail.class) + .eq(SettleCheckSheetDetail::getSheetId, sheet.getId()).orderByAsc(SettleCheckSheetDetail::getOrderNo); + List sheetDetails = settleCheckSheetDetailService.list(queryDetailWrapper); + for (SettleCheckSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId(), sheetDetail.getBizType()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettleCheckSheetDetail.class) + .eq(SettleCheckSheetDetail::getSheetId, sheet.getId()); + settleCheckSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(SettleCheckSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SettleCheckSheetStatus.CREATED); + statusList.add(SettleCheckSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .set(SettleCheckSheet::getApproveBy, null).set(SettleCheckSheet::getApproveTime, null) + .set(SettleCheckSheet::getRefuseReason, StringPool.EMPTY_STR).eq(SettleCheckSheet::getId, sheet.getId()) + .in(SettleCheckSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商对账单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过供应商对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSettleCheckSheetVo vo) { + + SettleCheckSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商对账单不存在!"); + } + + if (sheet.getStatus() != SettleCheckSheetStatus.CREATED + && sheet.getStatus() != SettleCheckSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商对账单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商对账单无法审核通过!"); + } + + sheet.setStatus(SettleCheckSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(SettleCheckSheetStatus.CREATED); + statusList.add(SettleCheckSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .eq(SettleCheckSheet::getId, sheet.getId()).in(SettleCheckSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商对账单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSettleCheckSheetVo vo) { + + SettleCheckSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassSettleCheckSheetVo approveVo = new ApprovePassSettleCheckSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝供应商对账单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSettleCheckSheetVo vo) { + + SettleCheckSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商对账单不存在!"); + } + + if (sheet.getStatus() != SettleCheckSheetStatus.CREATED) { + if (sheet.getStatus() == SettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商对账单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == SettleCheckSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("供应商对账单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商对账单无法审核拒绝!"); + } + + sheet.setStatus(SettleCheckSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(SettleCheckSheetStatus.CREATED); + statusList.add(SettleCheckSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .eq(SettleCheckSheet::getId, sheet.getId()).in(SettleCheckSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商对账单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSettleCheckSheetVo vo) { + + SettleCheckSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSettleCheckSheetVo approveVo = new ApprovePassSettleCheckSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商对账单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSettleCheckSheetVo vo) { + + SettleCheckSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSettleCheckSheetVo approveVo = new ApproveRefuseSettleCheckSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商对账单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除供应商对账单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SettleCheckSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("供应商对账单不存在!"); + } + + if (sheet.getStatus() != SettleCheckSheetStatus.CREATED + && sheet.getStatus() != SettleCheckSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SettleCheckSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的供应商对账单不允许执行删除操作!"); + } + + throw new DefaultClientException("供应商对账单无法删除!"); + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SettleCheckSheetDetail.class) + .eq(SettleCheckSheetDetail::getSheetId, sheet.getId()).orderByAsc(SettleCheckSheetDetail::getOrderNo); + List sheetDetails = settleCheckSheetDetailService.list(queryDetailWrapper); + for (SettleCheckSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId(), sheetDetail.getBizType()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettleCheckSheetDetail.class) + .eq(SettleCheckSheetDetail::getSheetId, sheet.getId()); + settleCheckSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SettleCheckSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商对账单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Override + public SettleCheckBizItemDto getBizItem(String id, SettleCheckSheetBizType bizType) { + + SettleCheckBizItemDto result = new SettleCheckBizItemDto(); + + switch (bizType) { + case RECEIVE_SHEET: { + ReceiveSheet receiveSheet = receiveSheetService.getById(id); + + result.setId(receiveSheet.getId()); + result.setCode(receiveSheet.getCode()); + result.setTotalAmount(receiveSheet.getTotalAmount()); + result.setApproveTime(receiveSheet.getApproveTime()); + result.setCalcType(SettleCheckSheetCalcType.ADD); + break; + } + case PURCHASE_RETURN: { + PurchaseReturn purchaseReturn = purchaseReturnService.getById(id); + + result.setId(purchaseReturn.getId()); + result.setCode(purchaseReturn.getCode()); + result.setTotalAmount(purchaseReturn.getTotalAmount()); + result.setApproveTime(purchaseReturn.getApproveTime()); + result.setCalcType(SettleCheckSheetCalcType.SUB); + break; + } + case SETTLE_FEE_SHEET: { + SettleFeeSheet feeSheet = settleFeeSheetService.getById(id); + + result.setId(feeSheet.getId()); + result.setCode(feeSheet.getCode()); + result.setTotalAmount(feeSheet.getTotalAmount()); + result.setApproveTime(feeSheet.getApproveTime()); + result.setCalcType(feeSheet.getSheetType() == SettleFeeSheetType.PAY ? + SettleCheckSheetCalcType.ADD : + SettleCheckSheetCalcType.SUB); + break; + } + case SETTLE_PRE_SHEET: { + SettlePreSheet preSheet = settlePreSheetService.getById(id); + + result.setId(preSheet.getId()); + result.setCode(preSheet.getCode()); + result.setTotalAmount(preSheet.getTotalAmount()); + result.setApproveTime(preSheet.getApproveTime()); + result.setCalcType(SettleCheckSheetCalcType.SUB); + break; + } + default: { + throw new DefaultSysException("未知的SettleCheckSheetBizType"); + } + } + + result.setBizType(bizType); + if (result.getCalcType() == SettleCheckSheetCalcType.SUB) { + result.setTotalAmount(result.getTotalAmount().negate()); + } + + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemUnSettle(String id, SettleCheckSheetBizType bizType) { + + SettleCheckBizItemDto item = this.getBizItem(id, bizType); + + switch (bizType) { + case RECEIVE_SHEET: { + int count = receiveSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case PURCHASE_RETURN: { + int count = purchaseReturnService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_FEE_SHEET: { + int count = settleFeeSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_PRE_SHEET: { + int count = settlePreSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + default: { + throw new DefaultSysException("未知的SettleCheckSheetBizType"); + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemPartSettle(String id, SettleCheckSheetBizType bizType) { + + SettleCheckBizItemDto item = this.getBizItem(id, bizType); + + switch (bizType) { + case RECEIVE_SHEET: { + int count = receiveSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case PURCHASE_RETURN: { + int count = purchaseReturnService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_FEE_SHEET: { + int count = settleFeeSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + case SETTLE_PRE_SHEET: { + int count = settlePreSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,业务无法进行!"); + } + break; + } + default: { + throw new DefaultSysException("未知的SettleCheckSheetBizType"); + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemSettled(String id, SettleCheckSheetBizType bizType) { + + SettleCheckBizItemDto item = this.getBizItem(id, bizType); + + switch (bizType) { + case RECEIVE_SHEET: { + int count = receiveSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + case PURCHASE_RETURN: { + int count = purchaseReturnService.setSettled(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + case SETTLE_FEE_SHEET: { + int count = settleFeeSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + case SETTLE_PRE_SHEET: { + int count = settlePreSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "," + bizType.getDesc() + "已结算,无法重复结算!"); + } + break; + } + default: { + throw new DefaultSysException("未知的SettleCheckSheetBizType"); + } + } + } + + @Override + public List getUnCheckBizItems(QueryUnCheckBizItemVo vo) { + + List results = new ArrayList<>(); + + List receiveSheetList = receiveSheetService.getApprovedList(vo.getSupplierId(), vo.getStartTime(), + vo.getEndTime(), SettleStatus.UN_SETTLE); + + List purchaseReturnList = purchaseReturnService.getApprovedList(vo.getSupplierId(), + vo.getStartTime(), vo.getEndTime(), SettleStatus.UN_SETTLE); + + List feeSheetList = settleFeeSheetService.getApprovedList(vo.getSupplierId(), vo.getStartTime(), + vo.getEndTime(), SettleStatus.UN_SETTLE); + + List preSheetList = settlePreSheetService.getApprovedList(vo.getSupplierId(), vo.getStartTime(), + vo.getEndTime(), SettleStatus.UN_SETTLE); + + if (!CollectionUtil.isEmpty(receiveSheetList)) { + for (ReceiveSheet item : receiveSheetList) { + SettleCheckBizItemDto result = new SettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(SettleCheckSheetBizType.RECEIVE_SHEET); + result.setCalcType(SettleCheckSheetCalcType.ADD); + + results.add(result); + } + } + + if (!CollectionUtil.isEmpty(purchaseReturnList)) { + for (PurchaseReturn item : purchaseReturnList) { + SettleCheckBizItemDto result = new SettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(SettleCheckSheetBizType.PURCHASE_RETURN); + result.setCalcType(SettleCheckSheetCalcType.SUB); + + results.add(result); + } + } + + if (!CollectionUtil.isEmpty(feeSheetList)) { + for (SettleFeeSheet item : feeSheetList) { + SettleCheckBizItemDto result = new SettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(SettleCheckSheetBizType.SETTLE_FEE_SHEET); + result.setCalcType(item.getSheetType() == SettleFeeSheetType.PAY ? + SettleCheckSheetCalcType.ADD : + SettleCheckSheetCalcType.SUB); + + results.add(result); + } + } + + if (!CollectionUtil.isEmpty(preSheetList)) { + for (SettlePreSheet item : preSheetList) { + SettleCheckBizItemDto result = new SettleCheckBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalAmount(item.getTotalAmount()); + result.setApproveTime(item.getApproveTime()); + result.setBizType(SettleCheckSheetBizType.SETTLE_PRE_SHEET); + result.setCalcType(SettleCheckSheetCalcType.SUB); + + results.add(result); + } + } + + results.stream().filter(t -> t.getCalcType() == SettleCheckSheetCalcType.SUB) + .forEach(t -> t.setTotalAmount(t.getTotalAmount().negate())); + + return results; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .set(SettleCheckSheet::getSettleStatus, SettleStatus.UN_SETTLE).eq(SettleCheckSheet::getId, id) + .eq(SettleCheckSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .set(SettleCheckSheet::getSettleStatus, SettleStatus.PART_SETTLE).eq(SettleCheckSheet::getId, id) + .in(SettleCheckSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .set(SettleCheckSheet::getSettleStatus, SettleStatus.SETTLED).eq(SettleCheckSheet::getId, id) + .in(SettleCheckSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SettleCheckSheetDetail.class) + .eq(SettleCheckSheetDetail::getSheetId, id).orderByAsc(SettleCheckSheetDetail::getOrderNo); + List sheetDetails = settleCheckSheetDetailService.list(queryDetailWrapper); + for (SettleCheckSheetDetail sheetDetail : sheetDetails) { + this.setBizItemSettled(sheetDetail.getBizId(), sheetDetail.getBizType()); + } + + return count; + } + + @Override + public List getApprovedList(String supplierId, LocalDateTime startTime, LocalDateTime endTime) { + + return getBaseMapper().getApprovedList(supplierId, startTime, endTime); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setSettleAmount(String id, BigDecimal totalPayedAmount, BigDecimal totalDiscountAmount) { + + SettleCheckSheet checkSheet = getBaseMapper().selectById(id); + BigDecimal remainTotalPayAmount = NumberUtil.sub(checkSheet.getTotalPayAmount(), + checkSheet.getTotalPayedAmount(), checkSheet.getTotalDiscountAmount(), totalPayedAmount, + totalDiscountAmount); + BigDecimal totalPayAmount = NumberUtil.sub(checkSheet.getTotalPayAmount(), checkSheet.getTotalPayedAmount(), + checkSheet.getTotalDiscountAmount()); + if (NumberUtil.lt(checkSheet.getTotalPayAmount(), 0)) { + if (NumberUtil.gt(remainTotalPayAmount, 0)) { + throw new DefaultClientException( + "对账单:" + checkSheet.getCode() + ",剩余付款金额为" + totalPayAmount + "元,本次付款金额为" + NumberUtil.add( + totalPayedAmount, totalDiscountAmount) + "元,无法结算!"); + } + } + if (NumberUtil.gt(checkSheet.getTotalPayAmount(), 0)) { + if (NumberUtil.lt(remainTotalPayAmount, 0)) { + throw new DefaultClientException( + "对账单:" + checkSheet.getCode() + ",剩余付款金额为" + totalPayAmount + "元,本次付款金额为" + NumberUtil.add( + totalPayedAmount, totalDiscountAmount) + "元,无法结算!"); + } + } + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleCheckSheet.class) + .set(SettleCheckSheet::getTotalPayedAmount, + NumberUtil.add(totalPayedAmount, checkSheet.getTotalPayedAmount())) + .set(SettleCheckSheet::getTotalDiscountAmount, + NumberUtil.add(totalDiscountAmount, checkSheet.getTotalDiscountAmount())) + .eq(SettleCheckSheet::getId, id) + .eq(SettleCheckSheet::getTotalPayedAmount, checkSheet.getTotalPayedAmount()) + .eq(SettleCheckSheet::getTotalDiscountAmount, checkSheet.getTotalDiscountAmount()); + if (getBaseMapper().update(updateWrapper) != 1) { + throw new DefaultClientException("结账单:" + checkSheet.getCode() + ",信息已过期,请刷新重试!"); + } + + if (NumberUtil.equal(remainTotalPayAmount, 0)) { + this.setSettled(id); + } + } + + private void create(SettleCheckSheet sheet, CreateSettleCheckSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + BigDecimal totalPayAmount = BigDecimal.ZERO; + + int orderNo = 0; + for (SettleCheckSheetItemVo itemVo : vo.getItems()) { + orderNo++; + SettleCheckBizItemDto item = this.getBizItem(itemVo.getId(), + EnumUtil.getByCode(SettleCheckSheetBizType.class, itemVo.getBizType())); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行业务单据不存在!"); + } + SettleCheckSheetDetail detail = new SettleCheckSheetDetail(); + + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setBizId(itemVo.getId()); + detail.setBizType(EnumUtil.getByCode(SettleCheckSheetBizType.class, itemVo.getBizType())); + detail.setCalcType(item.getCalcType()); + if (item.getCalcType() == SettleCheckSheetCalcType.ADD) { + if (NumberUtil.lt(itemVo.getPayAmount(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行业务单据应付金额不允许小于0!"); + } + } else { + if (NumberUtil.gt(itemVo.getPayAmount(), BigDecimal.ZERO)) { + throw new DefaultClientException("第" + orderNo + "行业务单据应付金额不允许大于0!"); + } + } + detail.setPayAmount(itemVo.getPayAmount()); + detail.setDescription(itemVo.getDescription()); + detail.setOrderNo(orderNo); + + settleCheckSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, item.getTotalAmount()); + totalPayAmount = NumberUtil.add(totalPayAmount, itemVo.getPayAmount()); + + //将所有的单据的结算状态更新 + this.setBizItemPartSettle(detail.getBizId(), detail.getBizType()); + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setSupplierId(vo.getSupplierId()); + sheet.setTotalAmount(totalAmount); + sheet.setTotalPayAmount(totalPayAmount); + sheet.setTotalPayedAmount(BigDecimal.ZERO); + sheet.setTotalDiscountAmount(BigDecimal.ZERO); + sheet.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setSettleStatus(SettleStatus.UN_SETTLE); + sheet.setStartDate(vo.getStartDate()); + sheet.setEndDate(vo.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetDetailServiceImpl.java new file mode 100644 index 0000000..cf9fb3e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetDetailServiceImpl.java @@ -0,0 +1,13 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.SettleFeeSheetDetail; +import com.lframework.xingyun.settle.mappers.SettleFeeSheetDetailMapper; +import com.lframework.xingyun.settle.service.SettleFeeSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class SettleFeeSheetDetailServiceImpl extends BaseMpServiceImpl + implements SettleFeeSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetServiceImpl.java new file mode 100644 index 0000000..6dbb10f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleFeeSheetServiceImpl.java @@ -0,0 +1,440 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.fee.SettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import com.lframework.xingyun.settle.entity.SettleFeeSheetDetail; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.enums.SettleFeeSheetStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetType; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.SettleFeeSheetMapper; +import com.lframework.xingyun.settle.service.SettleFeeSheetDetailService; +import com.lframework.xingyun.settle.service.SettleFeeSheetService; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import com.lframework.xingyun.settle.vo.fee.ApprovePassSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.ApproveRefuseSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.BatchApprovePassSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.BatchApproveRefuseSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.CreateSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.QuerySettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.SettleFeeSheetItemVo; +import com.lframework.xingyun.settle.vo.fee.UpdateSettleFeeSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SettleFeeSheetServiceImpl extends BaseMpServiceImpl + implements SettleFeeSheetService { + + @Autowired + private SettleFeeSheetDetailService settleFeeSheetDetailService; + + @Autowired + private SettleOutItemService settleOutItemService; + + @Autowired + private SettleInItemService settleInItemService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySettleFeeSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySettleFeeSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public SettleFeeSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建供应商费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建费用单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSettleFeeSheetVo vo) { + + SettleFeeSheet sheet = new SettleFeeSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.SETTLE_FEE_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(SettleFeeSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改供应商费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改费用单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSettleFeeSheetVo vo) { + + SettleFeeSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商费用单不存在!"); + } + + if (sheet.getStatus() != SettleFeeSheetStatus.CREATED + && sheet.getStatus() != SettleFeeSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商费用单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("供应商费用单无法修改!"); + } + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettleFeeSheetDetail.class) + .eq(SettleFeeSheetDetail::getSheetId, sheet.getId()); + settleFeeSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(SettleFeeSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SettleFeeSheetStatus.CREATED); + statusList.add(SettleFeeSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleFeeSheet.class) + .set(SettleFeeSheet::getApproveBy, null).set(SettleFeeSheet::getApproveTime, null) + .set(SettleFeeSheet::getRefuseReason, StringPool.EMPTY_STR).eq(SettleFeeSheet::getId, sheet.getId()) + .in(SettleFeeSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商费用单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过供应商费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSettleFeeSheetVo vo) { + + SettleFeeSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商费用单不存在!"); + } + + if (sheet.getStatus() != SettleFeeSheetStatus.CREATED + && sheet.getStatus() != SettleFeeSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商费用单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商费用单无法审核通过!"); + } + + sheet.setStatus(SettleFeeSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(SettleFeeSheetStatus.CREATED); + statusList.add(SettleFeeSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleFeeSheet.class) + .eq(SettleFeeSheet::getId, sheet.getId()).in(SettleFeeSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商费用单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSettleFeeSheetVo vo) { + + SettleFeeSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassSettleFeeSheetVo approveVo = new ApprovePassSettleFeeSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝供应商费用单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSettleFeeSheetVo vo) { + + SettleFeeSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商费用单不存在!"); + } + + if (sheet.getStatus() != SettleFeeSheetStatus.CREATED) { + if (sheet.getStatus() == SettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商费用单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == SettleFeeSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("供应商费用单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商费用单无法审核拒绝!"); + } + + sheet.setStatus(SettleFeeSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(SettleFeeSheetStatus.CREATED); + statusList.add(SettleFeeSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleFeeSheet.class) + .eq(SettleFeeSheet::getId, sheet.getId()).in(SettleFeeSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商费用单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSettleFeeSheetVo vo) { + + SettleFeeSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSettleFeeSheetVo approveVo = new ApprovePassSettleFeeSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商费用单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSettleFeeSheetVo vo) { + + SettleFeeSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSettleFeeSheetVo approveVo = new ApproveRefuseSettleFeeSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商费用单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除供应商费用单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SettleFeeSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("供应商费用单不存在!"); + } + + if (sheet.getStatus() != SettleFeeSheetStatus.CREATED + && sheet.getStatus() != SettleFeeSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SettleFeeSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的供应商费用单不允许执行删除操作!"); + } + + throw new DefaultClientException("供应商费用单无法删除!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettleFeeSheetDetail.class) + .eq(SettleFeeSheetDetail::getSheetId, sheet.getId()); + settleFeeSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SettleFeeSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商费用单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleFeeSheet.class) + .set(SettleFeeSheet::getSettleStatus, SettleStatus.UN_SETTLE).eq(SettleFeeSheet::getId, id) + .eq(SettleFeeSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleFeeSheet.class) + .set(SettleFeeSheet::getSettleStatus, SettleStatus.PART_SETTLE).eq(SettleFeeSheet::getId, id) + .in(SettleFeeSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleFeeSheet.class) + .set(SettleFeeSheet::getSettleStatus, SettleStatus.SETTLED).eq(SettleFeeSheet::getId, id) + .in(SettleFeeSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String supplierId, LocalDateTime startTime, LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(supplierId, startTime, endTime, settleStatus); + } + + private void create(SettleFeeSheet sheet, CreateSettleFeeSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (SettleFeeSheetItemVo itemVo : vo.getItems()) { + if (vo.getSheetType() == SettleFeeSheetType.RECEIVE.getCode().intValue()) { + SettleInItem item = settleInItemService.findById(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行项目不存在!"); + } + } else { + SettleOutItem item = settleOutItemService.findById(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行项目不存在!"); + } + } + SettleFeeSheetDetail detail = new SettleFeeSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setItemId(itemVo.getId()); + detail.setAmount(itemVo.getAmount()); + detail.setOrderNo(orderNo); + + settleFeeSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, detail.getAmount()); + + orderNo++; + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setSupplierId(vo.getSupplierId()); + sheet.setSheetType(EnumUtil.getByCode(SettleFeeSheetType.class, vo.getSheetType())); + sheet.setTotalAmount(totalAmount); + sheet.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setSettleStatus(SettleStatus.UN_SETTLE); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleInItemServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleInItemServiceImpl.java new file mode 100644 index 0000000..efe5e3c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleInItemServiceImpl.java @@ -0,0 +1,166 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.SettleInItemMapper; +import com.lframework.xingyun.settle.service.SettleInItemService; +import com.lframework.xingyun.settle.vo.item.in.CreateSettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.QuerySettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.SettleInItemSelectorVo; +import com.lframework.xingyun.settle.vo.item.in.UpdateSettleInItemVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SettleInItemServiceImpl extends BaseMpServiceImpl + implements SettleInItemService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySettleInItemVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySettleInItemVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, SettleInItemSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SettleInItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SettleInItem findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "停用收入项目,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleInItem.class) + .set(SettleInItem::getAvailable, Boolean.FALSE).in(SettleInItem::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "启用收入项目,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleInItem.class) + .set(SettleInItem::getAvailable, Boolean.TRUE).in(SettleInItem::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "新增收入项目,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSettleInItemVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SettleInItem.class) + .eq(SettleInItem::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + SettleInItem data = new SettleInItem(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setAvailable(Boolean.TRUE); + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改收入项目,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSettleInItemVo vo) { + + SettleInItem data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("收入项目不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(SettleInItem.class) + .eq(SettleInItem::getCode, vo.getCode()).ne(SettleInItem::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SettleInItem.class) + .set(SettleInItem::getCode, vo.getCode()).set(SettleInItem::getName, vo.getName()) + .set(SettleInItem::getAvailable, vo.getAvailable()).set(SettleInItem::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(SettleInItem::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = SettleInItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleOutItemServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleOutItemServiceImpl.java new file mode 100644 index 0000000..cca164a --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleOutItemServiceImpl.java @@ -0,0 +1,166 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.mappers.SettleOutItemMapper; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import com.lframework.xingyun.settle.vo.item.out.CreateSettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.QuerySettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.SettleOutItemSelectorVo; +import com.lframework.xingyun.settle.vo.item.out.UpdateSettleOutItemVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SettleOutItemServiceImpl extends BaseMpServiceImpl + implements SettleOutItemService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySettleOutItemVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySettleOutItemVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, SettleOutItemSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SettleOutItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SettleOutItem findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "停用支出项目,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleOutItem.class) + .set(SettleOutItem::getAvailable, Boolean.FALSE).in(SettleOutItem::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "启用支出项目,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleOutItem.class) + .set(SettleOutItem::getAvailable, Boolean.TRUE).in(SettleOutItem::getId, ids); + getBaseMapper().update(updateWrapper); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "新增支出项目,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSettleOutItemVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SettleOutItem.class) + .eq(SettleOutItem::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + SettleOutItem data = new SettleOutItem(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setAvailable(Boolean.TRUE); + data.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改支出项目,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSettleOutItemVo vo) { + + SettleOutItem data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("支出项目不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(SettleOutItem.class) + .eq(SettleOutItem::getCode, vo.getCode()).ne(SettleOutItem::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SettleOutItem.class) + .set(SettleOutItem::getCode, vo.getCode()).set(SettleOutItem::getName, vo.getName()) + .set(SettleOutItem::getAvailable, vo.getAvailable()).set(SettleOutItem::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(SettleOutItem::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @CacheEvict(value = SettleOutItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetDetailServiceImpl.java new file mode 100644 index 0000000..8745c01 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetDetailServiceImpl.java @@ -0,0 +1,13 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.SettlePreSheetDetail; +import com.lframework.xingyun.settle.mappers.SettlePreSheetDetailMapper; +import com.lframework.xingyun.settle.service.SettlePreSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class SettlePreSheetDetailServiceImpl extends BaseMpServiceImpl + implements SettlePreSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetServiceImpl.java new file mode 100644 index 0000000..eafaf65 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettlePreSheetServiceImpl.java @@ -0,0 +1,426 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.pre.SettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import com.lframework.xingyun.settle.entity.SettlePreSheetDetail; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.enums.SettlePreSheetStatus; +import com.lframework.xingyun.settle.mappers.SettlePreSheetMapper; +import com.lframework.xingyun.settle.service.SettleOutItemService; +import com.lframework.xingyun.settle.service.SettlePreSheetDetailService; +import com.lframework.xingyun.settle.service.SettlePreSheetService; +import com.lframework.xingyun.settle.vo.pre.ApprovePassSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.ApproveRefuseSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.BatchApprovePassSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.BatchApproveRefuseSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.CreateSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.QuerySettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.SettlePreSheetItemVo; +import com.lframework.xingyun.settle.vo.pre.UpdateSettlePreSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SettlePreSheetServiceImpl extends BaseMpServiceImpl + implements SettlePreSheetService { + + @Autowired + private SettlePreSheetDetailService settlePreSheetDetailService; + + @Autowired + private SettleOutItemService settleOutItemService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySettlePreSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySettlePreSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public SettlePreSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建供应商预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建预付款单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSettlePreSheetVo vo) { + + SettlePreSheet sheet = new SettlePreSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.SETTLE_PRE_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(SettlePreSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改供应商预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改预付款单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSettlePreSheetVo vo) { + + SettlePreSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商预付款单不存在!"); + } + + if (sheet.getStatus() != SettlePreSheetStatus.CREATED + && sheet.getStatus() != SettlePreSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商预付款单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("供应商预付款单无法修改!"); + } + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettlePreSheetDetail.class) + .eq(SettlePreSheetDetail::getSheetId, sheet.getId()); + settlePreSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(SettlePreSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SettlePreSheetStatus.CREATED); + statusList.add(SettlePreSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettlePreSheet.class) + .set(SettlePreSheet::getApproveBy, null).set(SettlePreSheet::getApproveTime, null) + .set(SettlePreSheet::getRefuseReason, StringPool.EMPTY_STR).eq(SettlePreSheet::getId, sheet.getId()) + .in(SettlePreSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商预付款单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过供应商预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSettlePreSheetVo vo) { + + SettlePreSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商预付款单不存在!"); + } + + if (sheet.getStatus() != SettlePreSheetStatus.CREATED + && sheet.getStatus() != SettlePreSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商预付款单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商预付款单无法审核通过!"); + } + + sheet.setStatus(SettlePreSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(SettlePreSheetStatus.CREATED); + statusList.add(SettlePreSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettlePreSheet.class) + .eq(SettlePreSheet::getId, sheet.getId()).in(SettlePreSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商预付款单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSettlePreSheetVo vo) { + + SettlePreSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassSettlePreSheetVo approveVo = new ApprovePassSettlePreSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝供应商预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSettlePreSheetVo vo) { + + SettlePreSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商预付款单不存在!"); + } + + if (sheet.getStatus() != SettlePreSheetStatus.CREATED) { + if (sheet.getStatus() == SettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商预付款单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == SettlePreSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("供应商预付款单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商预付款单无法审核拒绝!"); + } + + sheet.setStatus(SettlePreSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(SettlePreSheetStatus.CREATED); + statusList.add(SettlePreSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettlePreSheet.class) + .eq(SettlePreSheet::getId, sheet.getId()).in(SettlePreSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商预付款单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSettlePreSheetVo vo) { + + SettlePreSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSettlePreSheetVo approveVo = new ApprovePassSettlePreSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商预付款单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSettlePreSheetVo vo) { + + SettlePreSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSettlePreSheetVo approveVo = new ApproveRefuseSettlePreSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商预付款单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除供应商预付款单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SettlePreSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("供应商预付款单不存在!"); + } + + if (sheet.getStatus() != SettlePreSheetStatus.CREATED + && sheet.getStatus() != SettlePreSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SettlePreSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的供应商预付款单不允许执行删除操作!"); + } + + throw new DefaultClientException("供应商预付款单无法删除!"); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettlePreSheetDetail.class) + .eq(SettlePreSheetDetail::getSheetId, sheet.getId()); + settlePreSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SettlePreSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商预付款单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setUnSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettlePreSheet.class) + .set(SettlePreSheet::getSettleStatus, SettleStatus.UN_SETTLE).eq(SettlePreSheet::getId, id) + .eq(SettlePreSheet::getSettleStatus, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setPartSettle(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettlePreSheet.class) + .set(SettlePreSheet::getSettleStatus, SettleStatus.PART_SETTLE).eq(SettlePreSheet::getId, id) + .in(SettlePreSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int setSettled(String id) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettlePreSheet.class) + .set(SettlePreSheet::getSettleStatus, SettleStatus.SETTLED).eq(SettlePreSheet::getId, id) + .in(SettlePreSheet::getSettleStatus, SettleStatus.UN_SETTLE, SettleStatus.PART_SETTLE); + int count = getBaseMapper().update(updateWrapper); + + return count; + } + + @Override + public List getApprovedList(String supplierId, LocalDateTime startTime, LocalDateTime endTime, + SettleStatus settleStatus) { + + return getBaseMapper().getApprovedList(supplierId, startTime, endTime, settleStatus); + } + + private void create(SettlePreSheet sheet, CreateSettlePreSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (SettlePreSheetItemVo itemVo : vo.getItems()) { + SettleOutItem item = settleOutItemService.findById(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行项目不存在!"); + } + SettlePreSheetDetail detail = new SettlePreSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setItemId(itemVo.getId()); + detail.setAmount(itemVo.getAmount()); + detail.setOrderNo(orderNo); + + settlePreSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, detail.getAmount()); + + orderNo++; + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setSupplierId(vo.getSupplierId()); + sheet.setTotalAmount(totalAmount); + sheet.setDescription(StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setSettleStatus(SettleStatus.UN_SETTLE); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetDetailServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetDetailServiceImpl.java new file mode 100644 index 0000000..80fa401 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetDetailServiceImpl.java @@ -0,0 +1,13 @@ +package com.lframework.xingyun.settle.impl; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.settle.entity.SettleSheetDetail; +import com.lframework.xingyun.settle.mappers.SettleSheetDetailMapper; +import com.lframework.xingyun.settle.service.SettleSheetDetailService; +import org.springframework.stereotype.Service; + +@Service +public class SettleSheetDetailServiceImpl extends BaseMpServiceImpl + implements SettleSheetDetailService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetServiceImpl.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetServiceImpl.java new file mode 100644 index 0000000..3c1debb --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/impl/SettleSheetServiceImpl.java @@ -0,0 +1,542 @@ +package com.lframework.xingyun.settle.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.core.annations.OrderTimeLineLog; +import com.lframework.xingyun.core.enums.OrderTimeLineBizType; +import com.lframework.xingyun.settle.components.code.GenerateCodeTypePool; +import com.lframework.xingyun.settle.dto.sheet.SettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.SettleSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import com.lframework.xingyun.settle.entity.SettleSheet; +import com.lframework.xingyun.settle.entity.SettleSheetDetail; +import com.lframework.xingyun.settle.enums.SettleOpLogType; +import com.lframework.xingyun.settle.enums.SettleSheetStatus; +import com.lframework.xingyun.settle.mappers.SettleSheetMapper; +import com.lframework.xingyun.settle.service.SettleCheckSheetService; +import com.lframework.xingyun.settle.service.SettleSheetDetailService; +import com.lframework.xingyun.settle.service.SettleSheetService; +import com.lframework.xingyun.settle.vo.sheet.ApprovePassSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.ApproveRefuseSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.BatchApprovePassSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.BatchApproveRefuseSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.CreateSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.QuerySettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.QueryUnSettleBizItemVo; +import com.lframework.xingyun.settle.vo.sheet.SettleSheetItemVo; +import com.lframework.xingyun.settle.vo.sheet.UpdateSettleSheetVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SettleSheetServiceImpl extends BaseMpServiceImpl + implements SettleSheetService { + + @Autowired + private SettleSheetDetailService settleSheetDetailService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private SettleCheckSheetService settleCheckSheetService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySettleSheetVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySettleSheetVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public SettleSheetFullDto getDetail(String id) { + + return getBaseMapper().getDetail(id); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "创建供应商结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.CREATE, orderId = "#_result", name = "创建结算单") + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSettleSheetVo vo) { + + SettleSheet sheet = new SettleSheet(); + + sheet.setId(IdUtil.getId()); + sheet.setCode(generateCodeService.generate(GenerateCodeTypePool.SETTLE_SHEET)); + + this.create(sheet, vo); + + sheet.setStatus(SettleSheetStatus.CREATED); + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + + getBaseMapper().insert(sheet); + + return sheet.getId(); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "修改供应商结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.UPDATE, orderId = "#vo.id", name = "修改结算单") + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSettleSheetVo vo) { + + SettleSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商结算单不存在!"); + } + + if (sheet.getStatus() != SettleSheetStatus.CREATED + && sheet.getStatus() != SettleSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商结算单已审核通过,无法修改!"); + } else { + throw new DefaultClientException("供应商结算单无法修改!"); + } + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SettleSheetDetail.class) + .eq(SettleSheetDetail::getSheetId, sheet.getId()).orderByAsc(SettleSheetDetail::getOrderNo); + List sheetDetails = settleSheetDetailService.list(queryDetailWrapper); + for (SettleSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettleSheetDetail.class) + .eq(SettleSheetDetail::getSheetId, sheet.getId()); + settleSheetDetailService.remove(deleteDetailWrapper); + + this.create(sheet, vo); + + sheet.setStatus(SettleSheetStatus.CREATED); + + List statusList = new ArrayList<>(); + statusList.add(SettleSheetStatus.CREATED); + statusList.add(SettleSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleSheet.class) + .set(SettleSheet::getApproveBy, null).set(SettleSheet::getApproveTime, null) + .set(SettleSheet::getRefuseReason, StringPool.EMPTY_STR) + .eq(SettleSheet::getId, sheet.getId()) + .in(SettleSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商结算单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核通过供应商结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.id", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void approvePass(ApprovePassSettleSheetVo vo) { + + SettleSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商结算单不存在!"); + } + + if (sheet.getStatus() != SettleSheetStatus.CREATED + && sheet.getStatus() != SettleSheetStatus.APPROVE_REFUSE) { + if (sheet.getStatus() == SettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商结算单已审核通过,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商结算单无法审核通过!"); + } + + sheet.setStatus(SettleSheetStatus.APPROVE_PASS); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + if (!StringUtil.isBlank(vo.getDescription())) { + sheet.setDescription(vo.getDescription()); + } + + List statusList = new ArrayList<>(); + statusList.add(SettleSheetStatus.CREATED); + statusList.add(SettleSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleSheet.class) + .eq(SettleSheet::getId, sheet.getId()).in(SettleSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商结算单信息已过期,请刷新重试!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SettleSheetDetail.class) + .eq(SettleSheetDetail::getSheetId, sheet.getId()).orderByAsc(SettleSheetDetail::getOrderNo); + List details = settleSheetDetailService.list(queryDetailWrapper); + for (SettleSheetDetail detail : details) { + settleCheckSheetService.setSettleAmount(detail.getBizId(), detail.getPayAmount(), + detail.getDiscountAmount()); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#_result", name = "直接审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public String directApprovePass(CreateSettleSheetVo vo) { + + SettleSheetService thisService = getThis(this.getClass()); + + String id = thisService.create(vo); + + ApprovePassSettleSheetVo approveVo = new ApprovePassSettleSheetVo(); + approveVo.setId(id); + + thisService.approvePass(approveVo); + + return id; + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "审核拒绝供应商结算单,单号:{}", params = "#code") + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.id", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void approveRefuse(ApproveRefuseSettleSheetVo vo) { + + SettleSheet sheet = getBaseMapper().selectById(vo.getId()); + if (sheet == null) { + throw new DefaultClientException("供应商结算单不存在!"); + } + + if (sheet.getStatus() != SettleSheetStatus.CREATED) { + if (sheet.getStatus() == SettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("供应商结算单已审核通过,不允许继续执行审核!"); + } + if (sheet.getStatus() == SettleSheetStatus.APPROVE_REFUSE) { + throw new DefaultClientException("供应商结算单已审核拒绝,不允许继续执行审核!"); + } + throw new DefaultClientException("供应商结算单无法审核拒绝!"); + } + + sheet.setStatus(SettleSheetStatus.APPROVE_REFUSE); + sheet.setApproveBy(SecurityUtil.getCurrentUser().getId()); + sheet.setApproveTime(LocalDateTime.now()); + sheet.setRefuseReason(vo.getRefuseReason()); + + List statusList = new ArrayList<>(); + statusList.add(SettleSheetStatus.CREATED); + statusList.add(SettleSheetStatus.APPROVE_REFUSE); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SettleSheet.class) + .eq(SettleSheet::getId, sheet.getId()).in(SettleSheet::getStatus, statusList); + if (getBaseMapper().updateAllColumn(sheet, updateWrapper) != 1) { + throw new DefaultClientException("供应商结算单信息已过期,请刷新重试!"); + } + + OpLogUtil.setVariable("code", sheet.getCode()); + OpLogUtil.setExtra(vo); + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_PASS, orderId = "#vo.ids", name = "审核通过") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApprovePass(BatchApprovePassSettleSheetVo vo) { + + SettleSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApprovePassSettleSheetVo approveVo = new ApprovePassSettleSheetVo(); + approveVo.setId(id); + try { + thisService.approvePass(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商结算单审核通过失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OrderTimeLineLog(type = OrderTimeLineBizType.APPROVE_RETURN, orderId = "#vo.ids", name = "审核拒绝,拒绝理由:{}", params = "#vo.refuseReason") + @Transactional(rollbackFor = Exception.class) + @Override + public void batchApproveRefuse(BatchApproveRefuseSettleSheetVo vo) { + + SettleSheetService thisService = getThis(this.getClass()); + int orderNo = 1; + for (String id : vo.getIds()) { + ApproveRefuseSettleSheetVo approveVo = new ApproveRefuseSettleSheetVo(); + approveVo.setId(id); + approveVo.setRefuseReason(vo.getRefuseReason()); + + try { + thisService.approveRefuse(approveVo); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商结算单审核拒绝失败,失败原因:" + e.getMsg()); + } + orderNo++; + } + } + + @OpLog(type = SettleOpLogType.SETTLE, name = "删除供应商结算单,单号:{}", params = "#code") + @OrderTimeLineLog(orderId = "#id", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Assert.notBlank(id); + SettleSheet sheet = getBaseMapper().selectById(id); + if (sheet == null) { + throw new InputErrorException("供应商结算单不存在!"); + } + + if (sheet.getStatus() != SettleSheetStatus.CREATED + && sheet.getStatus() != SettleSheetStatus.APPROVE_REFUSE) { + + if (sheet.getStatus() == SettleSheetStatus.APPROVE_PASS) { + throw new DefaultClientException("“审核通过”的供应商结算单不允许执行删除操作!"); + } + + throw new DefaultClientException("供应商结算单无法删除!"); + } + + //将所有的单据的结算状态更新 + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(SettleSheetDetail.class) + .eq(SettleSheetDetail::getSheetId, sheet.getId()).orderByAsc(SettleSheetDetail::getOrderNo); + List sheetDetails = settleSheetDetailService.list(queryDetailWrapper); + for (SettleSheetDetail sheetDetail : sheetDetails) { + this.setBizItemUnSettle(sheetDetail.getBizId()); + } + + // 删除明细 + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(SettleSheetDetail.class) + .eq(SettleSheetDetail::getSheetId, sheet.getId()); + settleSheetDetailService.remove(deleteDetailWrapper); + + // 删除单据 + getBaseMapper().deleteById(id); + + OpLogUtil.setVariable("code", sheet.getCode()); + } + + @OrderTimeLineLog(orderId = "#ids", delete = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByIds(List ids) { + + if (!CollectionUtil.isEmpty(ids)) { + int orderNo = 1; + for (String id : ids) { + + try { + SettleSheetService thisService = getThis(this.getClass()); + thisService.deleteById(id); + } catch (ClientException e) { + throw new DefaultClientException("第" + orderNo + "个供应商结算单删除失败,失败原因:" + e.getMsg()); + } + + orderNo++; + } + } + } + + @Override + public SettleBizItemDto getBizItem(String id) { + + SettleCheckSheet checkSheet = settleCheckSheetService.getById(id); + + SettleBizItemDto result = new SettleBizItemDto(); + result.setId(checkSheet.getId()); + result.setCode(checkSheet.getCode()); + result.setTotalPayAmount(checkSheet.getTotalPayAmount()); + result.setTotalPayedAmount(checkSheet.getTotalPayedAmount()); + result.setTotalDiscountAmount(checkSheet.getTotalDiscountAmount()); + result.setTotalUnPayAmount( + NumberUtil.sub(checkSheet.getTotalPayAmount(), checkSheet.getTotalPayedAmount(), + checkSheet.getTotalDiscountAmount())); + result.setApproveTime(checkSheet.getApproveTime()); + + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemUnSettle(String id) { + + SettleCheckSheet item = settleCheckSheetService.getById(id); + int count = settleCheckSheetService.setUnSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "已结算,业务无法进行!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemPartSettle(String id) { + + SettleCheckSheet item = settleCheckSheetService.getById(id); + int count = settleCheckSheetService.setPartSettle(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "已结算,业务无法进行!"); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setBizItemSettled(String id) { + + SettleCheckSheet item = settleCheckSheetService.getById(id); + int count = settleCheckSheetService.setSettled(id); + if (count != 1) { + throw new DefaultClientException("单号:" + item.getCode() + "已结算,无法重复结算!"); + } + } + + @Override + public List getUnSettleBizItems(QueryUnSettleBizItemVo vo) { + + List results = new ArrayList<>(); + + List sheetList = settleCheckSheetService.getApprovedList(vo.getSupplierId(), + vo.getStartTime(), vo.getEndTime()); + + if (!CollectionUtil.isEmpty(sheetList)) { + for (SettleCheckSheet item : sheetList) { + SettleBizItemDto result = new SettleBizItemDto(); + result.setId(item.getId()); + result.setCode(item.getCode()); + result.setTotalPayAmount(item.getTotalPayAmount()); + result.setTotalPayedAmount(item.getTotalPayedAmount()); + result.setTotalDiscountAmount(item.getTotalDiscountAmount()); + result.setTotalUnPayAmount( + NumberUtil.sub(item.getTotalPayAmount(), item.getTotalPayedAmount(), + item.getTotalDiscountAmount())); + result.setApproveTime(item.getApproveTime()); + + results.add(result); + } + } + + return results; + } + + private void create(SettleSheet sheet, CreateSettleSheetVo vo) { + + BigDecimal totalAmount = BigDecimal.ZERO; + BigDecimal totalDiscountAmount = BigDecimal.ZERO; + + int orderNo = 1; + for (SettleSheetItemVo itemVo : vo.getItems()) { + SettleBizItemDto item = this.getBizItem(itemVo.getId()); + if (item == null) { + throw new DefaultClientException("第" + orderNo + "行业务单据不存在!"); + } + + if (NumberUtil.lt(item.getTotalPayAmount(), 0)) { + if (NumberUtil.gt(itemVo.getPayAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实付金额不允许大于0!"); + } + + if (NumberUtil.gt(itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行优惠金额不允许大于0!"); + } + + if (NumberUtil.equal(itemVo.getPayAmount(), 0) && NumberUtil.equal( + itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实付金额、优惠金额不能同时等于0!"); + } + + if (NumberUtil.gt(item.getTotalUnPayAmount(), + NumberUtil.add(itemVo.getPayAmount(), itemVo.getDiscountAmount()))) { + throw new DefaultClientException("第" + orderNo + "行实付金额与优惠金额相加不允许小于未付款金额!"); + } + } else if (NumberUtil.gt(item.getTotalPayAmount(), 0)) { + if (NumberUtil.lt(itemVo.getPayAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实付金额不允许小于0!"); + } + + if (NumberUtil.lt(itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行优惠金额不允许小于0!"); + } + + if (NumberUtil.equal(itemVo.getPayAmount(), 0) && NumberUtil.equal( + itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实付金额、优惠金额不能同时等于0!"); + } + if (NumberUtil.lt(item.getTotalUnPayAmount(), + NumberUtil.add(itemVo.getPayAmount(), itemVo.getDiscountAmount()))) { + throw new DefaultClientException("第" + orderNo + "行实付金额与优惠金额相加不允许大于未付款金额!"); + } + } else { + // 单据应付款等于0 + if (!NumberUtil.equal(itemVo.getPayAmount(), 0) || !NumberUtil.equal( + itemVo.getDiscountAmount(), 0)) { + throw new DefaultClientException("第" + orderNo + "行实付金额、优惠金额必须同时等于0!"); + } + } + + SettleSheetDetail detail = new SettleSheetDetail(); + detail.setId(IdUtil.getId()); + detail.setSheetId(sheet.getId()); + detail.setBizId(itemVo.getId()); + detail.setPayAmount(itemVo.getPayAmount()); + detail.setDiscountAmount(itemVo.getDiscountAmount()); + detail.setDescription(itemVo.getDescription()); + detail.setOrderNo(orderNo); + + settleSheetDetailService.save(detail); + + totalAmount = NumberUtil.add(totalAmount, itemVo.getPayAmount()); + totalDiscountAmount = NumberUtil.add(totalDiscountAmount, itemVo.getDiscountAmount()); + + //将所有的单据的结算状态更新 + this.setBizItemPartSettle(detail.getBizId()); + + orderNo++; + } + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + sheet.setSupplierId(vo.getSupplierId()); + sheet.setTotalAmount(totalAmount); + sheet.setTotalDiscountAmount(totalDiscountAmount); + sheet.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + sheet.setRefuseReason(StringPool.EMPTY_STR); + sheet.setStartDate(vo.getStartDate()); + sheet.setEndDate(vo.getEndDate()); + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetDetailMapper.java new file mode 100644 index 0000000..4f5acdb --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetDetailMapper.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface CustomerSettleCheckSheetDetailMapper extends + BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetMapper.java new file mode 100644 index 0000000..d96a5c7 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleCheckSheetMapper.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerSettleCheckSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface CustomerSettleCheckSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QueryCustomerSettleCheckSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettleCheckSheetFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("customerId") String customerId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetDetailMapper.java new file mode 100644 index 0000000..5a6a517 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetDetailMapper.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-30 + */ +public interface CustomerSettleFeeSheetDetailMapper extends + BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetMapper.java new file mode 100644 index 0000000..bc827c2 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleFeeSheetMapper.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.fee.customer.CustomerSettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import com.lframework.xingyun.settle.vo.fee.customer.QueryCustomerSettleFeeSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-30 + */ +public interface CustomerSettleFeeSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QueryCustomerSettleFeeSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettleFeeSheetFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("customerId") String customerId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetDetailMapper.java new file mode 100644 index 0000000..42d733f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetDetailMapper.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface CustomerSettlePreSheetDetailMapper extends + BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetMapper.java new file mode 100644 index 0000000..4704d95 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettlePreSheetMapper.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.pre.customer.CustomerSettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import com.lframework.xingyun.settle.vo.pre.customer.QueryCustomerSettlePreSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface CustomerSettlePreSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QueryCustomerSettlePreSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettlePreSheetFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("customerId") String customerId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetDetailMapper.java new file mode 100644 index 0000000..f3dd876 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.CustomerSettleSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-05 + */ +public interface CustomerSettleSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetMapper.java new file mode 100644 index 0000000..53134a3 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/CustomerSettleSheetMapper.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleSheet; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerSettleSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-05 + */ +public interface CustomerSettleSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QueryCustomerSettleSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettleSheetFullDto getDetail(String id); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetDetailMapper.java new file mode 100644 index 0000000..d78755b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.SettleCheckSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface SettleCheckSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetMapper.java new file mode 100644 index 0000000..12757af --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleCheckSheetMapper.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.dto.check.SettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import com.lframework.xingyun.settle.vo.check.QuerySettleCheckSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface SettleCheckSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QuerySettleCheckSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleCheckSheetFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("supplierId") String supplierId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetDetailMapper.java new file mode 100644 index 0000000..7109be8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.SettleFeeSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-30 + */ +public interface SettleFeeSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetMapper.java new file mode 100644 index 0000000..b691858 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleFeeSheetMapper.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.fee.SettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import com.lframework.xingyun.settle.vo.fee.QuerySettleFeeSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-30 + */ +public interface SettleFeeSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QuerySettleFeeSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleFeeSheetFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("supplierId") String supplierId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleInItemMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleInItemMapper.java new file mode 100644 index 0000000..1b239f5 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleInItemMapper.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.vo.item.in.QuerySettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.SettleInItemSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-28 + */ +public interface SettleInItemMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QuerySettleInItemVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SettleInItemSelectorVo vo); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleOutItemMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleOutItemMapper.java new file mode 100644 index 0000000..d216516 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleOutItemMapper.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.vo.item.out.QuerySettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.SettleOutItemSelectorVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-11-28 + */ +public interface SettleOutItemMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QuerySettleOutItemVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SettleOutItemSelectorVo vo); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetDetailMapper.java new file mode 100644 index 0000000..4d25008 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.SettlePreSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface SettlePreSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetMapper.java new file mode 100644 index 0000000..7dfc974 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettlePreSheetMapper.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.pre.SettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import com.lframework.xingyun.settle.vo.pre.QuerySettlePreSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-02 + */ +public interface SettlePreSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QuerySettlePreSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettlePreSheetFullDto getDetail(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(@Param("supplierId") String supplierId, + @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, + @Param("settleStatus") SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetDetailMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetDetailMapper.java new file mode 100644 index 0000000..b98472b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.entity.SettleSheetDetail; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-05 + */ +public interface SettleSheetDetailMapper extends BaseMapper { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetMapper.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetMapper.java new file mode 100644 index 0000000..85a2fbe --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/mappers/SettleSheetMapper.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.settle.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.settle.dto.sheet.SettleSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleSheet; +import com.lframework.xingyun.settle.vo.sheet.QuerySettleSheetVo; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-05 + */ +public interface SettleSheetMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "s", autoParse = true), + @Sort(value = "createTime", alias = "s", autoParse = true), + @Sort(value = "approveTime", alias = "s", autoParse = true), + }) + @DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = { + @DataPermission(template = "order", alias = "s") + }) + List query(@Param("vo") QuerySettleSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleSheetFullDto getDetail(String id); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetDetailService.java new file mode 100644 index 0000000..92a1c1f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetDetailService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheetDetail; + +public interface CustomerSettleCheckSheetDetailService extends + BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetService.java new file mode 100644 index 0000000..1649dec --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleCheckSheetService.java @@ -0,0 +1,198 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.customer.CustomerSettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleCheckSheet; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetBizType; +import com.lframework.xingyun.settle.vo.check.customer.ApprovePassCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.ApproveRefuseCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.BatchApprovePassCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.BatchApproveRefuseCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.CreateCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerSettleCheckSheetVo; +import com.lframework.xingyun.settle.vo.check.customer.QueryCustomerUnCheckBizItemVo; +import com.lframework.xingyun.settle.vo.check.customer.UpdateCustomerSettleCheckSheetVo; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +public interface CustomerSettleCheckSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettleCheckSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryCustomerSettleCheckSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettleCheckSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateCustomerSettleCheckSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateCustomerSettleCheckSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassCustomerSettleCheckSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateCustomerSettleCheckSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseCustomerSettleCheckSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassCustomerSettleCheckSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseCustomerSettleCheckSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 查询业务单据 + * + * @param id + * @param bizType + * @return + */ + CustomerSettleCheckBizItemDto getBizItem(String id, CustomerSettleCheckSheetBizType bizType); + + /** + * 更新业务单据未结算 + * + * @param id + * @param bizType + */ + void setBizItemUnSettle(String id, CustomerSettleCheckSheetBizType bizType); + + /** + * 更新业务单据结算中 + * + * @param id + * @param bizType + */ + void setBizItemPartSettle(String id, CustomerSettleCheckSheetBizType bizType); + + /** + * 更新业务单据已结算 + * + * @param id + * @param bizType + */ + void setBizItemSettled(String id, CustomerSettleCheckSheetBizType bizType); + + /** + * 查询未对账单据 + * + * @param vo + * @return + */ + List getUnCheckBizItems(QueryCustomerUnCheckBizItemVo vo); + + /** + * 更新结算状态-未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 更新结算状态-结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 更新结算状态-已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime); + + /** + * 设置结算金额 + * + * @param id + * @param totalPayedAmount + * @param totalDiscountAmount + */ + void setSettleAmount(String id, BigDecimal totalPayedAmount, BigDecimal totalDiscountAmount); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetDetailService.java new file mode 100644 index 0000000..304c19e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetDetailService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheetDetail; + +public interface CustomerSettleFeeSheetDetailService extends + BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetService.java new file mode 100644 index 0000000..fb0b7c1 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleFeeSheetService.java @@ -0,0 +1,146 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.fee.customer.CustomerSettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleFeeSheet; +import com.lframework.xingyun.settle.vo.fee.customer.ApprovePassCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.ApproveRefuseCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.BatchApprovePassCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.BatchApproveRefuseCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.CreateCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.QueryCustomerSettleFeeSheetVo; +import com.lframework.xingyun.settle.vo.fee.customer.UpdateCustomerSettleFeeSheetVo; +import java.time.LocalDateTime; +import java.util.List; + +public interface CustomerSettleFeeSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettleFeeSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryCustomerSettleFeeSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettleFeeSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateCustomerSettleFeeSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateCustomerSettleFeeSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassCustomerSettleFeeSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateCustomerSettleFeeSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseCustomerSettleFeeSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassCustomerSettleFeeSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseCustomerSettleFeeSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetDetailService.java new file mode 100644 index 0000000..9143854 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetDetailService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheetDetail; + +public interface CustomerSettlePreSheetDetailService extends + BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetService.java new file mode 100644 index 0000000..f6f4b78 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettlePreSheetService.java @@ -0,0 +1,146 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.pre.customer.CustomerSettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettlePreSheet; +import com.lframework.xingyun.settle.vo.pre.customer.ApprovePassCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.ApproveRefuseCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.BatchApprovePassCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.BatchApproveRefuseCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.CreateCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.QueryCustomerSettlePreSheetVo; +import com.lframework.xingyun.settle.vo.pre.customer.UpdateCustomerSettlePreSheetVo; +import java.time.LocalDateTime; +import java.util.List; + +public interface CustomerSettlePreSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettlePreSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryCustomerSettlePreSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettlePreSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateCustomerSettlePreSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateCustomerSettlePreSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassCustomerSettlePreSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateCustomerSettlePreSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseCustomerSettlePreSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassCustomerSettlePreSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseCustomerSettlePreSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param customerId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String customerId, LocalDateTime startTime, + LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetDetailService.java new file mode 100644 index 0000000..1da977c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetDetailService.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.CustomerSettleSheetDetail; + +public interface CustomerSettleSheetDetailService extends + BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetService.java new file mode 100644 index 0000000..6076f9a --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/CustomerSettleSheetService.java @@ -0,0 +1,147 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.customer.CustomerSettleSheetFullDto; +import com.lframework.xingyun.settle.entity.CustomerSettleSheet; +import com.lframework.xingyun.settle.vo.sheet.customer.ApprovePassCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.ApproveRefuseCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.BatchApprovePassCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.BatchApproveRefuseCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.CreateCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerSettleSheetVo; +import com.lframework.xingyun.settle.vo.sheet.customer.QueryCustomerUnSettleBizItemVo; +import com.lframework.xingyun.settle.vo.sheet.customer.UpdateCustomerSettleSheetVo; +import java.util.List; + +public interface CustomerSettleSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryCustomerSettleSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryCustomerSettleSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + CustomerSettleSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateCustomerSettleSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateCustomerSettleSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassCustomerSettleSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateCustomerSettleSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseCustomerSettleSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassCustomerSettleSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseCustomerSettleSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 查询业务单据 + * + * @param id + * @return + */ + CustomerSettleBizItemDto getBizItem(String id); + + /** + * 更新业务单据未结算 + * + * @param id + */ + void setBizItemUnSettle(String id); + + /** + * 更新业务单据结算中 + * + * @param id + */ + void setBizItemPartSettle(String id); + + /** + * 更新业务单据已结算 + * + * @param id + */ + void setBizItemSettled(String id); + + /** + * 查询未结算单据 + * + * @param vo + * @return + */ + List getUnSettleBizItems(QueryCustomerUnSettleBizItemVo vo); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetDetailService.java new file mode 100644 index 0000000..8abf17e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.SettleCheckSheetDetail; + +public interface SettleCheckSheetDetailService extends BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetService.java new file mode 100644 index 0000000..37e99b7 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleCheckSheetService.java @@ -0,0 +1,190 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.dto.check.SettleCheckBizItemDto; +import com.lframework.xingyun.settle.dto.check.SettleCheckSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleCheckSheet; +import com.lframework.xingyun.settle.enums.SettleCheckSheetBizType; +import com.lframework.xingyun.settle.vo.check.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +public interface SettleCheckSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySettleCheckSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySettleCheckSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleCheckSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSettleCheckSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSettleCheckSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSettleCheckSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSettleCheckSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSettleCheckSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSettleCheckSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSettleCheckSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 查询业务单据 + * + * @param id + * @param bizType + * @return + */ + SettleCheckBizItemDto getBizItem(String id, SettleCheckSheetBizType bizType); + + /** + * 更新业务单据未结算 + * + * @param id + * @param bizType + */ + void setBizItemUnSettle(String id, SettleCheckSheetBizType bizType); + + /** + * 更新业务单据结算中 + * + * @param id + * @param bizType + */ + void setBizItemPartSettle(String id, SettleCheckSheetBizType bizType); + + /** + * 更新业务单据已结算 + * + * @param id + * @param bizType + */ + void setBizItemSettled(String id, SettleCheckSheetBizType bizType); + + /** + * 查询未对账单据 + * + * @param vo + * @return + */ + List getUnCheckBizItems(QueryUnCheckBizItemVo vo); + + /** + * 更新结算状态-未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 更新结算状态-结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 更新结算状态-已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String supplierId, LocalDateTime startTime, LocalDateTime endTime); + + /** + * 设置结算金额 + * + * @param id + * @param totalPayedAmount + * @param totalDiscountAmount + */ + void setSettleAmount(String id, BigDecimal totalPayedAmount, BigDecimal totalDiscountAmount); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetDetailService.java new file mode 100644 index 0000000..0b4bf03 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.SettleFeeSheetDetail; + +public interface SettleFeeSheetDetailService extends BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetService.java new file mode 100644 index 0000000..99e4dbe --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleFeeSheetService.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.fee.SettleFeeSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleFeeSheet; +import com.lframework.xingyun.settle.vo.fee.*; + +import java.time.LocalDateTime; +import java.util.List; + +public interface SettleFeeSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySettleFeeSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySettleFeeSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleFeeSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSettleFeeSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSettleFeeSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSettleFeeSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSettleFeeSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSettleFeeSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSettleFeeSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSettleFeeSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String supplierId, LocalDateTime startTime, LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleInItemService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleInItemService.java new file mode 100644 index 0000000..fcfbcbb --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleInItemService.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.SettleInItem; +import com.lframework.xingyun.settle.vo.item.in.CreateSettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.QuerySettleInItemVo; +import com.lframework.xingyun.settle.vo.item.in.SettleInItemSelectorVo; +import com.lframework.xingyun.settle.vo.item.in.UpdateSettleInItemVo; + +import java.util.Collection; +import java.util.List; + +public interface SettleInItemService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySettleInItemVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySettleInItemVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SettleInItemSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleInItem findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSettleInItemVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSettleInItemVo vo); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleOutItemService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleOutItemService.java new file mode 100644 index 0000000..d75f1d3 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleOutItemService.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.SettleOutItem; +import com.lframework.xingyun.settle.vo.item.out.CreateSettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.QuerySettleOutItemVo; +import com.lframework.xingyun.settle.vo.item.out.SettleOutItemSelectorVo; +import com.lframework.xingyun.settle.vo.item.out.UpdateSettleOutItemVo; + +import java.util.Collection; +import java.util.List; + +public interface SettleOutItemService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySettleOutItemVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySettleOutItemVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SettleOutItemSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleOutItem findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSettleOutItemVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSettleOutItemVo vo); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetDetailService.java new file mode 100644 index 0000000..e397162 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.SettlePreSheetDetail; + +public interface SettlePreSheetDetailService extends BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetService.java new file mode 100644 index 0000000..457f985 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettlePreSheetService.java @@ -0,0 +1,139 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.dto.pre.SettlePreSheetFullDto; +import com.lframework.xingyun.settle.entity.SettlePreSheet; +import com.lframework.xingyun.settle.vo.pre.*; + +import java.time.LocalDateTime; +import java.util.List; + +public interface SettlePreSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySettlePreSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySettlePreSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettlePreSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSettlePreSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSettlePreSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSettlePreSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSettlePreSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSettlePreSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSettlePreSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSettlePreSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 设置成未结算 + * + * @param id + * @return + */ + int setUnSettle(String id); + + /** + * 设置成结算中 + * + * @param id + * @return + */ + int setPartSettle(String id); + + /** + * 设置成已结算 + * + * @param id + * @return + */ + int setSettled(String id); + + /** + * 查询已审核列表 + * + * @param supplierId + * @param startTime + * @param endTime + * @return + */ + List getApprovedList(String supplierId, LocalDateTime startTime, LocalDateTime endTime, + SettleStatus settleStatus); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetDetailService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetDetailService.java new file mode 100644 index 0000000..a0ed86f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetDetailService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.entity.SettleSheetDetail; + +public interface SettleSheetDetailService extends BaseMpService { + +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetService.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetService.java new file mode 100644 index 0000000..9a1be8d --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/service/SettleSheetService.java @@ -0,0 +1,140 @@ +package com.lframework.xingyun.settle.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.settle.dto.sheet.SettleBizItemDto; +import com.lframework.xingyun.settle.dto.sheet.SettleSheetFullDto; +import com.lframework.xingyun.settle.entity.SettleSheet; +import com.lframework.xingyun.settle.vo.sheet.*; + +import java.util.List; + +public interface SettleSheetService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySettleSheetVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySettleSheetVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SettleSheetFullDto getDetail(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSettleSheetVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSettleSheetVo vo); + + /** + * 审核通过 + * + * @param vo + */ + void approvePass(ApprovePassSettleSheetVo vo); + + /** + * 直接审核通过 + * + * @param vo + */ + String directApprovePass(CreateSettleSheetVo vo); + + /** + * 审核拒绝 + * + * @param vo + */ + void approveRefuse(ApproveRefuseSettleSheetVo vo); + + /** + * 批量审核通过 + * + * @param vo + */ + void batchApprovePass(BatchApprovePassSettleSheetVo vo); + + /** + * 批量审核拒绝 + * + * @param vo + */ + void batchApproveRefuse(BatchApproveRefuseSettleSheetVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 根据IDs删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 查询业务单据 + * + * @param id + * @return + */ + SettleBizItemDto getBizItem(String id); + + /** + * 更新业务单据未结算 + * + * @param id + */ + void setBizItemUnSettle(String id); + + /** + * 更新业务单据结算中 + * + * @param id + */ + void setBizItemPartSettle(String id); + + /** + * 更新业务单据已结算 + * + * @param id + */ + void setBizItemSettled(String id); + + /** + * 查询未结算单据 + * + * @param vo + * @return + */ + List getUnSettleBizItems(QueryUnSettleBizItemVo vo); +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApprovePassSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApprovePassSettleCheckSheetVo.java new file mode 100644 index 0000000..f0a354e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApprovePassSettleCheckSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApproveRefuseSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApproveRefuseSettleCheckSheetVo.java new file mode 100644 index 0000000..11bc8de --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/ApproveRefuseSettleCheckSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApprovePassSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApprovePassSettleCheckSheetVo.java new file mode 100644 index 0000000..c195b45 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApprovePassSettleCheckSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "对账单ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApproveRefuseSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApproveRefuseSettleCheckSheetVo.java new file mode 100644 index 0000000..c130920 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/BatchApproveRefuseSettleCheckSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "对账单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/CreateSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/CreateSettleCheckSheetVo.java new file mode 100644 index 0000000..49593f4 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/CreateSettleCheckSheetVo.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotNull(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 起始日期 + */ + @ApiModelProperty(value = "起始日期", required = true) + @NotNull(message = "起始日期不能为空!") + private LocalDate startDate; + + /** + * 截止日期 + */ + @ApiModelProperty(value = "截止日期", required = true) + @NotNull(message = "截止日期不能为空!") + private LocalDate endDate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (SettleCheckSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行业务单据不能为空!"); + } + + if (item.getBizType() == null) { + throw new InputErrorException("第" + orderNo + "行业务类型不能为空!"); + } + + if (item.getPayAmount() == null) { + throw new InputErrorException("第" + orderNo + "行应付金额不能为空!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QuerySettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QuerySettleCheckSheetVo.java new file mode 100644 index 0000000..943eec3 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QuerySettleCheckSheetVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettleCheckSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleCheckSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = SettleCheckSheetStatus.class) + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QueryUnCheckBizItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QueryUnCheckBizItemVo.java new file mode 100644 index 0000000..9740788 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/QueryUnCheckBizItemVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QueryUnCheckBizItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + @NotNull(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + private LocalDateTime startTime; + + /** + * 截至时间 + */ + @ApiModelProperty("截至时间") + private LocalDateTime endTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/SettleCheckSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/SettleCheckSheetItemVo.java new file mode 100644 index 0000000..1794073 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/SettleCheckSheetItemVo.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.settle.vo.check; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.settle.enums.SettleCheckSheetBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SettleCheckSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @IsEnum(message = "业务类型格式不正确!", enumClass = SettleCheckSheetBizType.class) + private Integer bizType; + + /** + * 应付金额 + */ + @ApiModelProperty("应付金额") + private BigDecimal payAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/UpdateSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/UpdateSettleCheckSheetVo.java new file mode 100644 index 0000000..9f24e5f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/UpdateSettleCheckSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.check; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSettleCheckSheetVo extends CreateSettleCheckSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApprovePassCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApprovePassCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..ba7268e --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApprovePassCustomerSettleCheckSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassCustomerSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApproveRefuseCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApproveRefuseCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..429a549 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/ApproveRefuseCustomerSettleCheckSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseCustomerSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApprovePassCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApprovePassCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..1f0b846 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApprovePassCustomerSettleCheckSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassCustomerSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "对账单ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApproveRefuseCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApproveRefuseCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..de8a645 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/BatchApproveRefuseCustomerSettleCheckSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseCustomerSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "对账单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CreateCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CreateCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..0728040 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CreateCustomerSettleCheckSheetVo.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateCustomerSettleCheckSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotNull(message = "客户ID不能为空!") + private String customerId; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 起始日期 + */ + @ApiModelProperty(value = "起始日期", required = true) + @NotNull(message = "起始日期不能为空!") + private LocalDate startDate; + + /** + * 截止日期 + */ + @ApiModelProperty(value = "截止日期", required = true) + @NotNull(message = "截止日期不能为空!") + private LocalDate endDate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (CustomerSettleCheckSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行业务单据不能为空!"); + } + + if (item.getBizType() == null) { + throw new InputErrorException("第" + orderNo + "行业务类型不能为空!"); + } + + if (item.getPayAmount() == null) { + throw new InputErrorException("第" + orderNo + "行应收金额不能为空!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CustomerSettleCheckSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CustomerSettleCheckSheetItemVo.java new file mode 100644 index 0000000..51780c5 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/CustomerSettleCheckSheetItemVo.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class CustomerSettleCheckSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 业务类型 + */ + @ApiModelProperty("业务类型") + @IsEnum(message = "业务类型格式不正确!", enumClass = CustomerSettleCheckSheetBizType.class) + private Integer bizType; + + /** + * 应收金额 + */ + @ApiModelProperty("应收金额") + private BigDecimal payAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..ba480e4 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerSettleCheckSheetVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleCheckSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettleCheckSheetVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = CustomerSettleCheckSheetStatus.class) + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerUnCheckBizItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerUnCheckBizItemVo.java new file mode 100644 index 0000000..6ac7b55 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/QueryCustomerUnCheckBizItemVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QueryCustomerUnCheckBizItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + @NotNull(message = "客户ID不能为空!") + private String customerId; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + private LocalDateTime startTime; + + /** + * 截至时间 + */ + @ApiModelProperty("截至时间") + private LocalDateTime endTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/UpdateCustomerSettleCheckSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/UpdateCustomerSettleCheckSheetVo.java new file mode 100644 index 0000000..5c2a1ca --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/check/customer/UpdateCustomerSettleCheckSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.check.customer; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateCustomerSettleCheckSheetVo extends CreateCustomerSettleCheckSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApprovePassSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApprovePassSettleFeeSheetVo.java new file mode 100644 index 0000000..f8f59c0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApprovePassSettleFeeSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApproveRefuseSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApproveRefuseSettleFeeSheetVo.java new file mode 100644 index 0000000..93e29e1 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/ApproveRefuseSettleFeeSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApprovePassSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApprovePassSettleFeeSheetVo.java new file mode 100644 index 0000000..75af822 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApprovePassSettleFeeSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "费用单ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApproveRefuseSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApproveRefuseSettleFeeSheetVo.java new file mode 100644 index 0000000..62ea2ae --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/BatchApproveRefuseSettleFeeSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "费用单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/CreateSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/CreateSettleFeeSheetVo.java new file mode 100644 index 0000000..e47cc35 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/CreateSettleFeeSheetVo.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.settle.enums.SettleFeeSheetType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotNull(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 收支方式 + */ + @ApiModelProperty(value = "收支方式", required = true) + @NotNull(message = "收支方式不能为空!") + @IsEnum(message = "收支方式不能为空!", enumClass = SettleFeeSheetType.class) + private Integer sheetType; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (SettleFeeSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行项目不能为空!"); + } + + if (item.getAmount() == null) { + throw new InputErrorException("第" + orderNo + "行金额不能为空!"); + } + + if (NumberUtil.le(item.getAmount(), 0D)) { + throw new InputErrorException("第" + orderNo + "行金额必须大于0!"); + } + + if (!NumberUtil.isNumberPrecision(item.getAmount(), 2)) { + throw new InputErrorException("第" + orderNo + "行金额最多允许2位小数!"); + } + + if (this.items.stream().filter(t -> t.getId().equals(item.getId())).count() > 1) { + throw new InputErrorException("第" + orderNo + "行项目与其他行重复,请检查!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/QuerySettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/QuerySettleFeeSheetVo.java new file mode 100644 index 0000000..b898cd1 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/QuerySettleFeeSheetVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettleFeeSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleFeeSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = SettleFeeSheetStatus.class) + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/SettleFeeSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/SettleFeeSheetItemVo.java new file mode 100644 index 0000000..b5d4ae0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/SettleFeeSheetItemVo.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.settle.vo.fee; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SettleFeeSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String id; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/UpdateSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/UpdateSettleFeeSheetVo.java new file mode 100644 index 0000000..266be51 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/UpdateSettleFeeSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.fee; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSettleFeeSheetVo extends CreateSettleFeeSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApprovePassCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApprovePassCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..c6be005 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApprovePassCustomerSettleFeeSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassCustomerSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApproveRefuseCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApproveRefuseCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..936c5aa --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/ApproveRefuseCustomerSettleFeeSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseCustomerSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApprovePassCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApprovePassCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..5dafc63 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApprovePassCustomerSettleFeeSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassCustomerSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "费用单ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApproveRefuseCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApproveRefuseCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..e94cad2 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/BatchApproveRefuseCustomerSettleFeeSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseCustomerSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "费用单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CreateCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CreateCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..a3a8b76 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CreateCustomerSettleFeeSheetVo.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateCustomerSettleFeeSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotNull(message = "客户ID不能为空!") + private String customerId; + + /** + * 收支方式 + */ + @ApiModelProperty(value = "收支方式", required = true) + @NotNull(message = "收支方式不能为空!") + @IsEnum(message = "收支方式不能为空!", enumClass = CustomerSettleFeeSheetType.class) + private Integer sheetType; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (CustomerSettleFeeSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行项目不能为空!"); + } + + if (item.getAmount() == null) { + throw new InputErrorException("第" + orderNo + "行金额不能为空!"); + } + + if (NumberUtil.le(item.getAmount(), 0D)) { + throw new InputErrorException("第" + orderNo + "行金额必须大于0!"); + } + + if (!NumberUtil.isNumberPrecision(item.getAmount(), 2)) { + throw new InputErrorException("第" + orderNo + "行金额最多允许2位小数!"); + } + + if (this.items.stream().filter(t -> t.getId().equals(item.getId())).count() > 1) { + throw new InputErrorException("第" + orderNo + "行项目与其他行重复,请检查!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CustomerSettleFeeSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CustomerSettleFeeSheetItemVo.java new file mode 100644 index 0000000..3730990 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/CustomerSettleFeeSheetItemVo.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class CustomerSettleFeeSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String id; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/QueryCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/QueryCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..d8ec9ad --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/QueryCustomerSettleFeeSheetVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettleFeeSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettleFeeSheetVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = CustomerSettleFeeSheetStatus.class) + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/UpdateCustomerSettleFeeSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/UpdateCustomerSettleFeeSheetVo.java new file mode 100644 index 0000000..65967cd --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/fee/customer/UpdateCustomerSettleFeeSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.fee.customer; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateCustomerSettleFeeSheetVo extends CreateCustomerSettleFeeSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/CreateSettleInItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/CreateSettleInItemVo.java new file mode 100644 index 0000000..d7797ee --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/CreateSettleInItemVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.settle.vo.item.in; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSettleInItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/QuerySettleInItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/QuerySettleInItemVo.java new file mode 100644 index 0000000..f44fddb --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/QuerySettleInItemVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.vo.item.in; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySettleInItemVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/SettleInItemSelectorVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/SettleInItemSelectorVo.java new file mode 100644 index 0000000..9f44ca0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/SettleInItemSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.vo.item.in; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SettleInItemSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/UpdateSettleInItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/UpdateSettleInItemVo.java new file mode 100644 index 0000000..00bc42b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/in/UpdateSettleInItemVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.settle.vo.item.in; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSettleInItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/CreateSettleOutItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/CreateSettleOutItemVo.java new file mode 100644 index 0000000..9658b56 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/CreateSettleOutItemVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.settle.vo.item.out; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSettleOutItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/QuerySettleOutItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/QuerySettleOutItemVo.java new file mode 100644 index 0000000..b27717f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/QuerySettleOutItemVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.vo.item.out; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySettleOutItemVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/SettleOutItemSelectorVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/SettleOutItemSelectorVo.java new file mode 100644 index 0000000..f019142 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/SettleOutItemSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.settle.vo.item.out; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SettleOutItemSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/UpdateSettleOutItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/UpdateSettleOutItemVo.java new file mode 100644 index 0000000..3becb1c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/item/out/UpdateSettleOutItemVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.settle.vo.item.out; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSettleOutItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApprovePassSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApprovePassSettlePreSheetVo.java new file mode 100644 index 0000000..f5de560 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApprovePassSettlePreSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApproveRefuseSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApproveRefuseSettlePreSheetVo.java new file mode 100644 index 0000000..d96f83c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/ApproveRefuseSettlePreSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApprovePassSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApprovePassSettlePreSheetVo.java new file mode 100644 index 0000000..9422224 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApprovePassSettlePreSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "费用单ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApproveRefuseSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApproveRefuseSettlePreSheetVo.java new file mode 100644 index 0000000..ddf4c47 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/BatchApproveRefuseSettlePreSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotNull(message = "费用单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/CreateSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/CreateSettlePreSheetVo.java new file mode 100644 index 0000000..18d0777 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/CreateSettlePreSheetVo.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotNull(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (SettlePreSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行项目不能为空!"); + } + + if (item.getAmount() == null) { + throw new InputErrorException("第" + orderNo + "行金额不能为空!"); + } + + if (NumberUtil.le(item.getAmount(), 0D)) { + throw new InputErrorException("第" + orderNo + "行金额必须大于0!"); + } + + if (!NumberUtil.isNumberPrecision(item.getAmount(), 2)) { + throw new InputErrorException("第" + orderNo + "行金额最多允许2位小数!"); + } + + if (this.items.stream().filter(t -> t.getId().equals(item.getId())).count() > 1) { + throw new InputErrorException("第" + orderNo + "行项目与其他行重复,请检查!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/QuerySettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/QuerySettlePreSheetVo.java new file mode 100644 index 0000000..74f9557 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/QuerySettlePreSheetVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.SettlePreSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettlePreSheetVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = SettlePreSheetStatus.class) + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/SettlePreSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/SettlePreSheetItemVo.java new file mode 100644 index 0000000..90e0ded --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/SettlePreSheetItemVo.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.settle.vo.pre; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SettlePreSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String id; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/UpdateSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/UpdateSettlePreSheetVo.java new file mode 100644 index 0000000..23fadae --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/UpdateSettlePreSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.pre; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSettlePreSheetVo extends CreateSettlePreSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApprovePassCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApprovePassCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..127354b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApprovePassCustomerSettlePreSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassCustomerSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApproveRefuseCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApproveRefuseCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..d8f6c15 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/ApproveRefuseCustomerSettlePreSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseCustomerSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApprovePassCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApprovePassCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..7d8f071 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApprovePassCustomerSettlePreSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassCustomerSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "费用单ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApproveRefuseCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApproveRefuseCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..af9d7a8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/BatchApproveRefuseCustomerSettlePreSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseCustomerSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotNull(message = "费用单ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CreateCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CreateCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..4279c39 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CreateCustomerSettlePreSheetVo.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.NumberUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateCustomerSettlePreSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotNull(message = "客户ID不能为空!") + private String customerId; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (CustomerSettlePreSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行项目不能为空!"); + } + + if (item.getAmount() == null) { + throw new InputErrorException("第" + orderNo + "行金额不能为空!"); + } + + if (NumberUtil.le(item.getAmount(), 0D)) { + throw new InputErrorException("第" + orderNo + "行金额必须大于0!"); + } + + if (!NumberUtil.isNumberPrecision(item.getAmount(), 2)) { + throw new InputErrorException("第" + orderNo + "行金额最多允许2位小数!"); + } + + if (this.items.stream().filter(t -> t.getId().equals(item.getId())).count() > 1) { + throw new InputErrorException("第" + orderNo + "行项目与其他行重复,请检查!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CustomerSettlePreSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CustomerSettlePreSheetItemVo.java new file mode 100644 index 0000000..2843780 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/CustomerSettlePreSheetItemVo.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class CustomerSettlePreSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 项目ID + */ + @ApiModelProperty("项目ID") + private String id; + + /** + * 金额 + */ + @ApiModelProperty("金额") + private BigDecimal amount; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/QueryCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/QueryCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..e8b7ab1 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/QueryCustomerSettlePreSheetVo.java @@ -0,0 +1,77 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.sc.enums.SettleStatus; +import com.lframework.xingyun.settle.enums.CustomerSettlePreSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettlePreSheetVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = CustomerSettlePreSheetStatus.class) + private Integer status; + + /** + * 结算状态 + */ + @ApiModelProperty("结算状态") + @IsEnum(message = "结算状态格式不正确!", enumClass = SettleStatus.class) + private Integer settleStatus; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/UpdateCustomerSettlePreSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/UpdateCustomerSettlePreSheetVo.java new file mode 100644 index 0000000..376b335 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/pre/customer/UpdateCustomerSettlePreSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.pre.customer; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateCustomerSettlePreSheetVo extends CreateCustomerSettlePreSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApprovePassSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApprovePassSettleSheetVo.java new file mode 100644 index 0000000..809ad98 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApprovePassSettleSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApproveRefuseSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApproveRefuseSettleSheetVo.java new file mode 100644 index 0000000..13f5d49 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/ApproveRefuseSettleSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApprovePassSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApprovePassSettleSheetVo.java new file mode 100644 index 0000000..f9b3535 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApprovePassSettleSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApproveRefuseSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApproveRefuseSettleSheetVo.java new file mode 100644 index 0000000..ea6e69c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/BatchApproveRefuseSettleSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/CreateSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/CreateSettleSheetVo.java new file mode 100644 index 0000000..3703b56 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/CreateSettleSheetVo.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotNull(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 起始日期 + */ + @ApiModelProperty(value = "起始日期", required = true) + @NotNull(message = "起始日期不能为空!") + private LocalDate startDate; + + /** + * 截止日期 + */ + @ApiModelProperty(value = "截止日期", required = true) + @NotNull(message = "截止日期不能为空!") + private LocalDate endDate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (SettleSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行对账单不能为空!"); + } + + if (item.getPayAmount() == null) { + throw new InputErrorException("第" + orderNo + "行实付金额不能为空!"); + } + + if (item.getDiscountAmount() == null) { + throw new InputErrorException("第" + orderNo + "行优惠金额不能为空!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QuerySettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QuerySettleSheetVo.java new file mode 100644 index 0000000..cfa73c8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QuerySettleSheetVo.java @@ -0,0 +1,69 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.settle.enums.SettleSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySettleSheetVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 供应商ID + */ + @ApiModelProperty("供应商ID") + private String supplierId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = SettleSheetStatus.class) + private Integer status; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QueryUnSettleBizItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QueryUnSettleBizItemVo.java new file mode 100644 index 0000000..e771f1b --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/QueryUnSettleBizItemVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QueryUnSettleBizItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 供应商ID + */ + @ApiModelProperty(value = "供应商ID", required = true) + @NotNull(message = "供应商ID不能为空!") + private String supplierId; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + private LocalDateTime startTime; + + /** + * 截至时间 + */ + @ApiModelProperty("截至时间") + private LocalDateTime endTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/SettleSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/SettleSheetItemVo.java new file mode 100644 index 0000000..312f7e9 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/SettleSheetItemVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class SettleSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 实付金额 + */ + @ApiModelProperty("实付金额") + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal discountAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/UpdateSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/UpdateSettleSheetVo.java new file mode 100644 index 0000000..da5f4b0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/UpdateSettleSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.sheet; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSettleSheetVo extends CreateSettleSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApprovePassCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApprovePassCustomerSettleSheetVo.java new file mode 100644 index 0000000..73990d0 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApprovePassCustomerSettleSheetVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ApprovePassCustomerSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApproveRefuseCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApproveRefuseCustomerSettleSheetVo.java new file mode 100644 index 0000000..1407de2 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/ApproveRefuseCustomerSettleSheetVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class ApproveRefuseCustomerSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApprovePassCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApprovePassCustomerSettleSheetVo.java new file mode 100644 index 0000000..dfc05ed --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApprovePassCustomerSettleSheetVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApprovePassCustomerSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private List ids; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApproveRefuseCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApproveRefuseCustomerSettleSheetVo.java new file mode 100644 index 0000000..4321730 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/BatchApproveRefuseCustomerSettleSheetVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class BatchApproveRefuseCustomerSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private List ids; + + /** + * 拒绝理由 + */ + @ApiModelProperty(value = "拒绝理由", required = true) + @NotBlank(message = "拒绝理由不能为空!") + private String refuseReason; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CreateCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CreateCustomerSettleSheetVo.java new file mode 100644 index 0000000..e5d7866 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CreateCustomerSettleSheetVo.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateCustomerSettleSheetVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotNull(message = "客户ID不能为空!") + private String customerId; + + /** + * 项目 + */ + @ApiModelProperty(value = "项目", required = true) + @NotEmpty(message = "项目不能为空!") + private List items; + + /** + * 起始日期 + */ + @ApiModelProperty(value = "起始日期", required = true) + @NotNull(message = "起始日期不能为空!") + private LocalDate startDate; + + /** + * 截止日期 + */ + @ApiModelProperty(value = "截止日期", required = true) + @NotNull(message = "截止日期不能为空!") + private LocalDate endDate; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public void validate() { + + int orderNo = 1; + for (CustomerSettleSheetItemVo item : this.items) { + if (StringUtil.isBlank(item.getId())) { + throw new InputErrorException("第" + orderNo + "行对账单不能为空!"); + } + + if (item.getPayAmount() == null) { + throw new InputErrorException("第" + orderNo + "行实收金额不能为空!"); + } + + if (item.getDiscountAmount() == null) { + throw new InputErrorException("第" + orderNo + "行优惠金额不能为空!"); + } + + orderNo++; + } + } +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CustomerSettleSheetItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CustomerSettleSheetItemVo.java new file mode 100644 index 0000000..fb52b4c --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/CustomerSettleSheetItemVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class CustomerSettleSheetItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 单据ID + */ + @ApiModelProperty("单据ID") + private String id; + + /** + * 实收金额 + */ + @ApiModelProperty("实收金额") + private BigDecimal payAmount; + + /** + * 优惠金额 + */ + @ApiModelProperty("优惠金额") + private BigDecimal discountAmount; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerSettleSheetVo.java new file mode 100644 index 0000000..a77554f --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerSettleSheetVo.java @@ -0,0 +1,69 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.settle.enums.CustomerSettleSheetStatus; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryCustomerSettleSheetVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 业务单据号 + */ + @ApiModelProperty("业务单据号") + private String code; + + /** + * 客户ID + */ + @ApiModelProperty("客户ID") + private String customerId; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime createStartTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime createEndTime; + + /** + * 审核人 + */ + @ApiModelProperty("审核人") + private String approveBy; + + /** + * 审核起始时间 + */ + @ApiModelProperty("审核起始时间") + private LocalDateTime approveStartTime; + + /** + * 审核截止时间 + */ + @ApiModelProperty("审核截止时间") + private LocalDateTime approveEndTime; + + /** + * 审核状态 + */ + @ApiModelProperty("审核状态") + @IsEnum(message = "审核状态格式不正确!", enumClass = CustomerSettleSheetStatus.class) + private Integer status; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerUnSettleBizItemVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerUnSettleBizItemVo.java new file mode 100644 index 0000000..0eec7e8 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/QueryCustomerUnSettleBizItemVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QueryCustomerUnSettleBizItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 客户ID + */ + @ApiModelProperty(value = "客户ID", required = true) + @NotNull(message = "客户ID不能为空!") + private String customerId; + + /** + * 起始时间 + */ + @ApiModelProperty("起始时间") + private LocalDateTime startTime; + + /** + * 截至时间 + */ + @ApiModelProperty("截至时间") + private LocalDateTime endTime; +} diff --git a/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/UpdateCustomerSettleSheetVo.java b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/UpdateCustomerSettleSheetVo.java new file mode 100644 index 0000000..c943951 --- /dev/null +++ b/xingyun-settle/src/main/java/com/lframework/xingyun/settle/vo/sheet/customer/UpdateCustomerSettleSheetVo.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.settle.vo.sheet.customer; + +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateCustomerSettleSheetVo extends CreateCustomerSettleSheetVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; +} diff --git a/xingyun-settle/src/main/java/lombok.config b/xingyun-settle/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-settle/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-settle/src/main/resources/mappers/CustomerSettleCheckSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/CustomerSettleCheckSheetMapper.xml new file mode 100644 index 0000000..5dfd3da --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/CustomerSettleCheckSheetMapper.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT s.id, + s.code, + s.customer_id, + s.total_amount, + s.total_pay_amount, + s.total_payed_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status + FROM customer_settle_check_sheet AS s + + + SELECT s.id, + s.code, + s.customer_id, + s.total_amount, + s.total_pay_amount, + s.total_payed_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + d.biz_id AS detail_biz_id, + d.biz_type AS detail_biz_type, + d.calc_type AS detail_calc_type, + d.pay_amount AS detail_pay_amount, + d.description AS detail_description + FROM customer_settle_check_sheet AS s + LEFT JOIN customer_settle_check_sheet_detail AS d ON d.sheet_id = s.id + + diff --git a/xingyun-settle/src/main/resources/mappers/CustomerSettleFeeSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/CustomerSettleFeeSheetMapper.xml new file mode 100644 index 0000000..3737952 --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/CustomerSettleFeeSheetMapper.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT s.id, + s.code, + s.customer_id, + s.sheet_type, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status + FROM customer_settle_fee_sheet AS s + + + SELECT s.id, + s.code, + s.customer_id, + s.sheet_type, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + d.item_id AS detail_item_id, + d.amount AS detail_amount + FROM customer_settle_fee_sheet AS s + LEFT JOIN customer_settle_fee_sheet_detail AS d ON d.sheet_id = s.id + + diff --git a/xingyun-settle/src/main/resources/mappers/CustomerSettlePreSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/CustomerSettlePreSheetMapper.xml new file mode 100644 index 0000000..480df8d --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/CustomerSettlePreSheetMapper.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT s.id, + s.code, + s.customer_id, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status + FROM customer_settle_pre_sheet AS s + + + + SELECT s.id, + s.code, + s.customer_id, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + d.item_id AS detail_item_id, + d.amount AS detail_amount + FROM customer_settle_pre_sheet AS s + LEFT JOIN customer_settle_pre_sheet_detail AS d ON d.sheet_id = s.id + + diff --git a/xingyun-settle/src/main/resources/mappers/CustomerSettleSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/CustomerSettleSheetMapper.xml new file mode 100644 index 0000000..597c250 --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/CustomerSettleSheetMapper.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT s.id, + s.code, + s.customer_id, + s.total_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + d.id AS detail_id, + d.biz_id AS detail_biz_id, + d.pay_amount AS detail_pay_amount, + d.discount_amount AS detail_discount_amount, + d.description AS detail_description + FROM customer_settle_sheet AS s + LEFT JOIN customer_settle_sheet_detail AS d ON d.sheet_id = s.id + + + + SELECT s.id, + s.code, + s.customer_id, + s.total_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason + FROM customer_settle_sheet AS s + + diff --git a/xingyun-settle/src/main/resources/mappers/SettleCheckSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/SettleCheckSheetMapper.xml new file mode 100644 index 0000000..2387483 --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/SettleCheckSheetMapper.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.total_amount, + s.total_pay_amount, + s.total_payed_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status + FROM settle_check_sheet AS s + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.total_amount, + s.total_pay_amount, + s.total_payed_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + d.biz_id AS detail_biz_id, + d.biz_type AS detail_biz_type, + d.calc_type AS detail_calc_type, + d.pay_amount AS detail_pay_amount, + d.description AS detail_description + FROM settle_check_sheet AS s + LEFT JOIN settle_check_sheet_detail AS d ON d.sheet_id = s.id + + + + + + + + diff --git a/xingyun-settle/src/main/resources/mappers/SettleFeeSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/SettleFeeSheetMapper.xml new file mode 100644 index 0000000..1f6f616 --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/SettleFeeSheetMapper.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.sheet_type, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status + FROM settle_fee_sheet AS s + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.sheet_type, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + d.item_id AS detail_item_id, + d.amount AS detail_amount + FROM settle_fee_sheet AS s + LEFT JOIN settle_fee_sheet_detail AS d ON d.sheet_id = s.id + + + + + + + + diff --git a/xingyun-settle/src/main/resources/mappers/SettleInItemMapper.xml b/xingyun-settle/src/main/resources/mappers/SettleInItemMapper.xml new file mode 100644 index 0000000..32e6e72 --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/SettleInItemMapper.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM settle_in_item + + + + diff --git a/xingyun-settle/src/main/resources/mappers/SettleOutItemMapper.xml b/xingyun-settle/src/main/resources/mappers/SettleOutItemMapper.xml new file mode 100644 index 0000000..d00010a --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/SettleOutItemMapper.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + SELECT + id, + code, + name, + available, + description, + create_by, + create_time, + update_by, + update_time + FROM settle_out_item + + + + diff --git a/xingyun-settle/src/main/resources/mappers/SettlePreSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/SettlePreSheetMapper.xml new file mode 100644 index 0000000..1d02cdb --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/SettlePreSheetMapper.xml @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status + FROM settle_pre_sheet AS s + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.total_amount, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + s.settle_status, + d.id AS detail_id, + d.item_id AS detail_item_id, + d.amount AS detail_amount + FROM settle_pre_sheet AS s + LEFT JOIN settle_pre_sheet_detail AS d ON d.sheet_id = s.id + + + + + + + + diff --git a/xingyun-settle/src/main/resources/mappers/SettleSheetMapper.xml b/xingyun-settle/src/main/resources/mappers/SettleSheetMapper.xml new file mode 100644 index 0000000..70990df --- /dev/null +++ b/xingyun-settle/src/main/resources/mappers/SettleSheetMapper.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.total_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason + FROM settle_sheet AS s + + + + SELECT + s.id, + s.code, + s.supplier_id, + s.total_amount, + s.total_discount_amount, + s.start_date, + s.end_date, + s.description, + s.create_by, + s.create_time, + s.update_by, + s.update_time, + s.approve_by, + s.approve_time, + s.status, + s.refuse_reason, + d.id AS detail_id, + d.biz_id AS detail_biz_id, + d.pay_amount AS detail_pay_amount, + d.discount_amount AS detail_discount_amount, + d.description AS detail_description + FROM settle_sheet AS s + LEFT JOIN settle_sheet_detail AS d ON d.sheet_id = s.id + + + + + + diff --git a/xingyun-template-core/pom.xml b/xingyun-template-core/pom.xml new file mode 100644 index 0000000..47320cb --- /dev/null +++ b/xingyun-template-core/pom.xml @@ -0,0 +1,22 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-template-core + + 【${project.artifactId}】此Module与业务无关,提供业务Module与Template Module的交互能力 + + + + com.lframework + web-starter + + + \ No newline at end of file diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/OpLog.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/OpLog.java new file mode 100644 index 0000000..1724e18 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/OpLog.java @@ -0,0 +1,56 @@ +package com.lframework.xingyun.template.core.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 系统日志注解 + *

+ * 使用方法: 比如关于用户的日志可以分为“登录、退出登录” 此时type可以使用统一的字符串,这样可以将关于用户行为的日志全部查出 然后再根据不同的name将这些日志进一步细分 + * name同时也用于前端显示 在上述例子中,可以将type设置为“user.operation” 登录的name设置为“用户登录” 退出登录的name设置为“退出登录” + * + * @author zmj + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OpLog { + + /** + * 日志类型 用于做业务区分 + * + * @return + */ + int type(); + + /** + * 日志名称 需要填充参数部分用{}占位,会根据params的值进行填充 + * + * @return + */ + String name() default ""; + + /** + * 需要保存的参数 Spel表达式 + * + * @return + */ + String[] params() default {}; + + /** + * 是否循环填充日志名称 会将params中的collection循环format + * + * @return + */ + boolean loopFormat() default false; + + /** + * 是否自动保存参数 + * + * @return + */ + boolean autoSaveParams() default false; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermission.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermission.java new file mode 100644 index 0000000..224c2f9 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermission.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.template.core.annotations.permission; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataPermission { + + String template(); + + String alias(); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermissions.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermissions.java new file mode 100644 index 0000000..0a2a76e --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/permission/DataPermissions.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.template.core.annotations.permission; + +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataPermissions { + + SysDataPermissionDataPermissionType type(); + + DataPermission[] value(); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sort.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sort.java new file mode 100644 index 0000000..8e81cfb --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sort.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.template.core.annotations.sort; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Sort { + + /** + * 传入列名 + * + * @return + */ + String value(); + + /** + * SQL列名 + * + * @return + */ + String alias() default ""; + + /** + * 是否自动解析 + *

+ * 如果自动解析,那么alias只需要指定表的别名即可,会直接将alias和转为下划线的value拼接作为SQL列名 + * + * @return + */ + boolean autoParse() default false; +} \ No newline at end of file diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sorts.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sorts.java new file mode 100644 index 0000000..89f70ac --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/annotations/sort/Sorts.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.template.core.annotations.sort; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Sorts { + + Sort[] value(); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/aop/OpLogAspector.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/aop/OpLogAspector.java new file mode 100644 index 0000000..9dd0c3d --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/aop/OpLogAspector.java @@ -0,0 +1,190 @@ +package com.lframework.xingyun.template.core.aop; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.core.vo.CreateOpLogsVo; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.SpelUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.expression.EvaluationContext; +import org.springframework.stereotype.Component; + +/** + * OpLog切面 + * + * @author zmj + */ +@Slf4j +@Aspect +@Component +@ConditionalOnProperty(value = "op-logs.enabled", matchIfMissing = true) +public class OpLogAspector { + + @Pointcut("@annotation(com.lframework.xingyun.template.core.annotations.OpLog)") + public void opLogCutPoint() { + + } + + @Around(value = "opLogCutPoint()") + public Object opLog(ProceedingJoinPoint joinPoint) throws Throwable { + + try { + //生成logId,多层嵌套时,隔离不同bean的数据 + String logId = IdUtil.getUUID(); + OpLogUtil.init(logId); + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + + Object value = joinPoint.proceed(); + + if (currentUser != null) { + try { + //获取方法的参数名和参数值 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + List paramNameList = Arrays.asList(methodSignature.getParameterNames()); + List paramList = Arrays.asList(joinPoint.getArgs()); + + //将方法的参数名和参数值一一对应的放入上下文中 + EvaluationContext ctx = SpelUtil.buildContext(); + for (int i = 0; i < paramNameList.size(); i++) { + ctx.setVariable(paramNameList.get(i), paramList.get(i)); + } + + //将返回值放入上下文中 + ctx.setVariable("_result", value); + + Map variables = OpLogUtil.getVariables(); + if (!CollectionUtil.isEmpty(variables)) { + variables.forEach((k, v) -> { + ctx.setVariable(k, v); + }); + } + + // 解析SpEL表达式获取结果 + Object[] params; + OpLog opLog = methodSignature.getMethod().getAnnotation(OpLog.class); + if (!ArrayUtil.isEmpty(opLog.params())) { + params = new Object[opLog.params().length]; + for (int i = 0; i < opLog.params().length; i++) { + String param = opLog.params()[i]; + Object p = SpelUtil.parse(param, ctx); + params[i] = p; + } + } else { + params = new String[0]; + } + + List paramsList = new ArrayList<>(); + //循环format + if (opLog.loopFormat() && Arrays.stream(params).anyMatch(t -> t instanceof Collection)) { + String[] strParams = new String[params.length]; + //collectionIndex的索引 + List collectionIndexes = new ArrayList<>(); + for (int i = 0; i < params.length; i++) { + //先处理不是Collection的元素 + if (params[i] instanceof Collection) { + collectionIndexes.add(i); + continue; + } + strParams[i] = params[i] == null ? null : params[i].toString(); + } + + paramsList.add(strParams); + + if (!CollectionUtil.isEmpty(collectionIndexes)) { + //将所有的collection组合,例:collection1的size是2 collection2的size是3 则组合后的条数为2*3=6 + for (Integer collectionIndex : collectionIndexes) { + List tmpParamsList = new ArrayList<>(); + for (String[] paramsArr : paramsList) { + + Collection collection = (Collection) params[collectionIndex]; + for (Object o : collection) { + String[] tmp = new String[paramsArr.length]; + for (int j = 0; j < paramsArr.length; j++) { + if (j == collectionIndex) { + tmp[j] = o == null ? null : o.toString(); + } else { + tmp[j] = paramsArr[j]; + } + } + + tmpParamsList.add(tmp); + } + } + + paramsList.clear(); + paramsList.addAll(tmpParamsList); + } + } else { + paramsList.add(strParams); + } + } else { + String[] strParams = new String[params.length]; + for (int i = 0; i < params.length; i++) { + strParams[i] = params[i] == null ? null : params[i].toString(); + } + paramsList.add(strParams); + } + + List createOpLogsVoList = new ArrayList<>(); + for (String[] strArr : paramsList) { + String extra = OpLogUtil.getExtra(); + if (extra == null) { + if (opLog.autoSaveParams()) { + // 没有手动指定extra + if (CollectionUtil.isNotEmpty(paramNameList)) { + if (paramNameList.size() == 1) { + // 只有一个参数 + OpLogUtil.setExtra(ctx.lookupVariable(paramNameList.get(0))); + } else { + // 多个参数 + Map paramMap = new LinkedHashMap<>(paramNameList.size(), 1); + for (String paramName : paramNameList) { + paramMap.put(paramName, ctx.lookupVariable(paramName)); + } + OpLogUtil.setExtra(paramMap); + } + } + extra = OpLogUtil.getExtra(); + } + } + + String finalExtra = extra; + CreateOpLogsVo vo = new CreateOpLogsVo(); + vo.setName(StringUtil.format(opLog.name(), strArr)); + vo.setLogType(opLog.type()); + vo.setExtra(finalExtra); + vo.setIp(currentUser.getIp()); + createOpLogsVoList.add(vo); + } + + if (CollectionUtil.isNotEmpty(createOpLogsVoList)) { + OpLogUtil.addLogs(createOpLogsVoList); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + return value; + } finally { + OpLogUtil.clear(); + } + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/WebExceptionHandler.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/WebExceptionHandler.java new file mode 100644 index 0000000..e9c7dab --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/WebExceptionHandler.java @@ -0,0 +1,391 @@ +package com.lframework.xingyun.template.core.components; + +import cn.dev33.satoken.exception.NotPermissionException; +import com.lframework.starter.common.exceptions.BaseException; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.common.exceptions.SysException; +import com.lframework.starter.common.exceptions.impl.AccessDeniedException; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.Response; +import com.lframework.starter.web.resp.ResponseErrorBuilder; +import com.lframework.starter.web.utils.ResponseUtil; +import java.util.Map; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.UnexpectedTypeException; + +import com.lframework.xingyun.template.core.utils.WebUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.util.http.fileupload.FileUploadException; +import org.springframework.beans.TypeMismatchException; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpStatus; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +/** + * 异常处理器 + * + * @author zmj + */ +@Slf4j +@RestControllerAdvice +public class WebExceptionHandler { + + /** + * 处理系统异常 + * + * @param e + * @return + */ + @ExceptionHandler(ClientException.class) + public Response handle(ClientException e, HandlerMethod method) { + + this.logException(e, method); + + this.setResponseCode(e); + + return InvokeResultBuilder.fail(e); + } + + /** + * 处理系统异常 + * + * @param e + * @return + */ + @ExceptionHandler(SysException.class) + public Response handle(SysException e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new DefaultSysException(); + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + /** + * 处理传入参数类型转换错误异常 + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(UnexpectedTypeException.class) + public Response handle(UnexpectedTypeException e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new InputErrorException(); + + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + @ExceptionHandler(BindException.class) + public Response handle(BindException e, HandlerMethod method) { + + this.logException(e, method); + + InputErrorException exception = null; + + if (e.getErrorCount() > 0) { + ObjectError objectError = e.getAllErrors().get(0); + + if (objectError instanceof FieldError && "typeMismatch".equals(objectError.getCode())) { + String fieldName = ((FieldError) objectError).getField(); + + Class targetClazz = e.getBindingResult().getTarget().getClass(); + + TypeMismatch typeMismatch = null; + try { + typeMismatch = targetClazz.getDeclaredField(fieldName).getAnnotation(TypeMismatch.class); + } catch (NoSuchFieldException exp) { + throw new DefaultSysException(exp.getMessage()); + } + if (typeMismatch != null) { + exception = new InputErrorException(typeMismatch.message()); + } + } + } + if (exception == null) { + for (ObjectError error : e.getAllErrors()) { + exception = new InputErrorException(error.getDefaultMessage()); + break; + } + + if (exception == null) { + exception = new InputErrorException(); + } + } + + this.setResponseCode(exception); + + return getBuilder(method.getBean()).fail(exception); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public Response methodArgumentNotValidException(MethodArgumentNotValidException e, + HandlerMethod method) { + + this.logException(e, method); + InputErrorException exception = null; + for (ObjectError error : e.getBindingResult().getAllErrors()) { + exception = new InputErrorException(error.getDefaultMessage()); + break; + } + + if (exception == null) { + throw new InputErrorException(); + } + + this.setResponseCode(exception); + + return getBuilder(method.getBean()).fail(exception); + } + + /** + * 处理未通过校验异常 + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(ConstraintViolationException.class) + public Response handle(ConstraintViolationException e, HandlerMethod method) { + + this.logException(e, method); + + InputErrorException exception = null; + for (ConstraintViolation constraintViolation : e.getConstraintViolations()) { + exception = new InputErrorException(constraintViolation.getMessage()); + break; + } + + if (exception == null) { + throw new InputErrorException(); + } + + this.setResponseCode(exception); + + return getBuilder(method.getBean()).fail(exception); + } + + /** + * 处理由于传入参数类型不匹配导致的异常 + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(TypeMismatchException.class) + public Response methodArgumentTypeMismatchException(TypeMismatchException e, + HandlerMethod method) { + + this.logException(e, method); + + MethodParameter methodParameter = null; + if (e instanceof MethodArgumentConversionNotSupportedException) { + methodParameter = ((MethodArgumentConversionNotSupportedException) e).getParameter(); + } else if (e instanceof MethodArgumentTypeMismatchException) { + methodParameter = ((MethodArgumentTypeMismatchException) e).getParameter(); + } + + BaseException ex = null; + if (methodParameter != null) { + TypeMismatch typeMismatch = methodParameter.getMethod() + .getParameters()[methodParameter.getParameterIndex()].getAnnotation(TypeMismatch.class); + if (typeMismatch != null) { + ex = new InputErrorException(typeMismatch.message()); + } + } + + if (ex == null) { + ex = new InputErrorException(); + } + + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + /** + * 处理由于传入参数类型不匹配导致的异常 + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(HttpMessageNotReadableException.class) + public Response invalidFormatException(HttpMessageNotReadableException e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new InputErrorException(); + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + /** + * 处理由于传入方式错误导致的异常 + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public Response httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, + HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new DefaultSysException(); + + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(); + } + + @ExceptionHandler(FileUploadException.class) + public Response fileUploadExceptionHandler(FileUploadException e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new DefaultClientException("文件上传失败!"); + + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + /** + * 处理Exception + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(Exception.class) + public Response exceptionHandler(Exception e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new DefaultSysException(); + + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + /** + * 处理Throwable + * + * @param e + * @param method + * @return + */ + @ExceptionHandler(Throwable.class) + public Response throwableHandle(Throwable e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new InputErrorException(); + + this.setResponseCode(ex); + + return getBuilder(method.getBean()).fail(ex); + } + + /** + * 处理无权限异常 + * + * @param e + * @return + */ + @ExceptionHandler(AccessDeniedException.class) + public Response handle(AccessDeniedException e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new AccessDeniedException(); + this.setResponseCode(ex); + + return this.getBuilder(method.getBean()).fail(ex); + } + + @ExceptionHandler(NotPermissionException.class) + public Response notPermissionException(NotPermissionException e, HandlerMethod method) { + + this.logException(e, method); + + BaseException ex = new AccessDeniedException(); + + this.setResponseCode(ex); + + return this.getBuilder(method.getBean()).fail(ex); + } + + protected void logException(Throwable e, HandlerMethod method) { + + if (e instanceof ClientException) { + if (log.isDebugEnabled()) { + String className = method.getBeanType().getName(); + String methodName = method.getMethod().getName(); + log.debug("className={}, methodName={}, 有异常产生", className, methodName, e); + } + } else { + String className = method.getBeanType().getName(); + String methodName = method.getMethod().getName(); + log.error("className={}, methodName={}, 有异常产生", className, methodName, e); + } + } + + protected void setResponseCode(BaseException e) { + //如果请求地址是/ydool开头的,则返回200 + String requestURI = WebUtils.getHttpRequest().getRequestURI(); + if (requestURI.startsWith("/ydool")) { + ResponseUtil.getResponse().setStatus(HttpStatus.OK.value()); + }else { + ResponseUtil.getResponse().setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + } + } + + protected ResponseErrorBuilder getBuilder(Object bean) { + + Map builders = ApplicationUtil.getBeansOfType( + ResponseErrorBuilder.class); + ResponseErrorBuilder builder = null; + for (ResponseErrorBuilder value : builders.values()) { + if (value.isDefault()) { + builder = value; + break; + } + } + + for (ResponseErrorBuilder value : builders.values()) { + if (value.isMatch(bean)) { + builder = value; + break; + } + } + + return builder; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/DataPermissionHandlerImpl.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/DataPermissionHandlerImpl.java new file mode 100644 index 0000000..0179185 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/DataPermissionHandlerImpl.java @@ -0,0 +1,155 @@ +package com.lframework.xingyun.template.core.components.permission; + +import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.session.SaSession; +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.template.core.annotations.permission.DataPermission; +import com.lframework.xingyun.template.core.annotations.permission.DataPermissions; +import com.lframework.xingyun.template.core.service.SysDataPermissionModelDetailService; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; + +public class DataPermissionHandlerImpl implements DataPermissionHandler { + + private static final String EMPTY_SQL = "(1 = 1)"; + + @Override + public Expression getSqlSegment(Expression where, String mappedStatementId) { + try { + String sqlSegment = this.convertDataPermissionSql(mappedStatementId); + if (StringUtil.isEmpty(sqlSegment)) { + return null; + } + Expression sqlSegmentExpression = CCJSqlParserUtil.parseCondExpression(sqlSegment); + if (null != where) { + return new AndExpression(where, sqlSegmentExpression); + } + return sqlSegmentExpression; + } catch (JSQLParserException e) { + e.printStackTrace(); + } + return null; + } + + private String getDataPermission(SysDataPermissionDataPermissionType permissionType, + List keys, + List values) { + + Map dataPermissionMap = null; + Map dataPermissionVar = null; + try { + SaSession session = StpUtil.getSession(false); + if (session == null) { + return EMPTY_SQL; + } + dataPermissionMap = (Map) session.get( + SecurityConstants.DATA_PERMISSION_SQL_MAP); + + dataPermissionVar = (Map) session.get( + SecurityConstants.DATA_PERMISSION_SQL_VAR); + if (CollectionUtil.isEmpty(dataPermissionMap)) { + return EMPTY_SQL; + } + } catch (SaTokenException e) { + return EMPTY_SQL; + } + + Assert.notNull(permissionType); + Assert.notNull(keys); + Assert.notNull(values); + + String sqlTemplate = dataPermissionMap.get(permissionType.getCode().toString()); + if (StringUtil.isBlank(sqlTemplate)) { + return EMPTY_SQL; + } + + if (keys.size() != values.size()) { + throw new DefaultSysException("keys和values长度不一致!"); + } + + Map sqlParams = new HashMap<>(); + for (int i = 0; i < keys.size(); i++) { + sqlParams.put(keys.get(i), values.get(i)); + } + + if (CollectionUtil.isNotEmpty(dataPermissionVar)) { + dataPermissionVar.forEach((k, v) -> { + sqlParams.put("__var#" + k, v); + }); + } + + SysDataPermissionModelDetailService sysDataPermissionModelDetailService = ApplicationUtil.getBean( + SysDataPermissionModelDetailService.class); + return sysDataPermissionModelDetailService.formatSql(sqlTemplate, sqlParams); + } + + private String convertDataPermissionSql(String statementId) { + // 获取Mapper执行方法上的注解 + Method mapperMethod = null; + try { + mapperMethod = this.findMapperMethod(this.convertMsId(statementId)); + } catch (ClassNotFoundException e) { + return null; + } + if (mapperMethod == null) { + return null; + } + DataPermissions dataPermissions = mapperMethod.getAnnotation(DataPermissions.class); + + if (dataPermissions != null) { + SysDataPermissionDataPermissionType dataPermissionType = dataPermissions.type(); + DataPermission[] dataPermissionList = dataPermissions.value(); + String dataPermissionSql = this.getDataPermission(dataPermissionType, + Arrays.stream(dataPermissionList).map(DataPermission::template) + .collect(Collectors.toList()), + Arrays.stream(dataPermissionList).map(DataPermission::alias) + .collect(Collectors.toList())); + + return dataPermissionSql; + } + + return null; + } + + private String convertMsId(String id) { + String pageHelperSuffix = "_COUNT"; + if (id.endsWith(pageHelperSuffix)) { + return id.substring(0, id.length() - pageHelperSuffix.length()); + } + + String mpSuffix = "_mpCount"; + if (id.endsWith(mpSuffix)) { + return id.substring(0, id.length() - mpSuffix.length()); + } + + return id; + } + + private Method findMapperMethod(String statementId) + throws ClassNotFoundException { + int lastDotIndex = statementId.lastIndexOf("."); + String className = statementId.substring(0, lastDotIndex); + String methodName = statementId.substring(lastDotIndex + 1); + + Class mapperInterface = Class.forName(className); + return Arrays.stream(mapperInterface.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .findFirst() + .orElse(null); + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/SysDataPermissionDataPermissionType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/SysDataPermissionDataPermissionType.java new file mode 100644 index 0000000..e908f51 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/permission/SysDataPermissionDataPermissionType.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.core.components.permission; + +public enum SysDataPermissionDataPermissionType { + + PRODUCT(1, "商品"), ORDER(2, "单据"); + + private Integer code; + + private String desc; + + SysDataPermissionDataPermissionType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + public Integer getCode() { + return this.code; + } + + public String getDesc() { + return desc; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzHandler.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzHandler.java new file mode 100644 index 0000000..95aedf9 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzHandler.java @@ -0,0 +1,321 @@ +package com.lframework.xingyun.template.core.components.qrtz; + +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.JobBuilder; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; + +@Slf4j +public class QrtzHandler { + + private static final SchedulerFactoryBean SCHEDULER_FACTORY = ApplicationUtil.getBean( + SchedulerFactoryBean.class); + + public static void addJob(Class jobClass, String cron, + Map jobDatas) { + + addJob(null, null, jobClass, null, null, cron, jobDatas); + } + + public static void addJob(Class jobClass, String cron) { + + addJob(null, null, jobClass, null, null, cron, null); + } + + public static void addJob(String jobName, String jobGroupName, Class jobClass, + String triggerName, String triggerGroupName, String cron) { + + addJob(jobName, jobGroupName, jobClass, triggerName, triggerGroupName, cron, null); + } + + public static void addJob(String jobName, String jobGroupName, Class jobClass, + String triggerName, String triggerGroupName, String cron, Map jobDatas) { + + addJob(jobName, jobGroupName, jobClass, triggerName, triggerGroupName, cron, jobDatas, null); + } + + /** + * 添加任务 + * + * @param jobName 任务名 + * @param jobGroupName 任务组名 + * @param jobClass 任务类Class + * @param triggerName 触发器名 + * @param triggerGroupName 触发器组名 + * @param cron cron表达式 + * @param jobDatas 附加数据 + */ + public static void addJob(String jobName, String jobGroupName, Class jobClass, + String triggerName, String triggerGroupName, String cron, Map jobDatas, + String description) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + JobBuilder jobBuilder = JobBuilder.newJob(jobClass); + if (!StringUtil.isBlank(jobName)) { + jobBuilder.withIdentity(jobName, jobGroupName); + } + + JobDetail jobDetail = jobBuilder.withDescription( + StringUtil.isBlank(description) ? StringPool.EMPTY_STR : description).build(); + if (!CollectionUtil.isEmpty(jobDatas)) { + jobDatas.forEach((k, v) -> jobDetail.getJobDataMap().put(k, v)); + } + + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + if (!StringUtil.isBlank(triggerName)) { + triggerBuilder.withIdentity(triggerName, triggerGroupName); + } + + triggerBuilder.startNow(); + triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); + CronTrigger trigger = (CronTrigger) triggerBuilder.build(); + sched.scheduleJob(jobDetail, trigger); + + if (!sched.isShutdown()) { + sched.start(); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 查询触发器 + * + * @param triggerName 触发器名称 + * @param triggerGroupName 触发器组名称 + * @return + */ + public static CronTrigger getTrigger(String triggerName, String triggerGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); + CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey); + + return trigger; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 查询任务 + * + * @param jobName + * @param jobGroupName + * @return + */ + public static JobDetail getJob(String jobName, String jobGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName)); + return jobDetail; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 修改任务Cron + * + * @param triggerName 触发器名称 + * @param triggerGroupName 触发器组名称 + * @param cron cron表达式 + */ + public static void updateJobCron(String triggerName, String triggerGroupName, String cron) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + CronTrigger trigger = getTrigger(triggerName, triggerGroupName); + if (trigger == null) { + return; + } + + String oriCron = trigger.getCronExpression(); + if (!oriCron.equalsIgnoreCase(cron)) { + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + triggerBuilder.withIdentity(triggerName, triggerGroupName); + triggerBuilder.startNow(); + triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); + trigger = (CronTrigger) triggerBuilder.build(); + sched.rescheduleJob(TriggerKey.triggerKey(triggerName, triggerGroupName), trigger); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 删除任务 + * + * @param jobName 任务名称 + * @param jobGroupName 任务组名称 + * @param triggerName 触发器名称 + * @param triggerGroupName 触发器组名称 + */ + public static void deleteJob(String jobName, String jobGroupName, String triggerName, + String triggerGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + + TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); + + sched.pauseTrigger(triggerKey); + sched.unscheduleJob(triggerKey); + sched.deleteJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 启动所有任务 + */ + public static void startJobs() { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.start(); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 关闭所有任务 + */ + public static void shutdownJobs() { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + if (!sched.isShutdown()) { + sched.shutdown(); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 安全关闭 + * + * @throws SchedulerException + */ + public static void safeShutdown() throws SchedulerException { + + try { + DynamicDataSourceContextHolder.push("master"); + int executingJobSize = SCHEDULER_FACTORY.getScheduler().getCurrentlyExecutingJobs().size(); + log.info("当前运行任务个数:{},等待完成后关闭", executingJobSize); + SCHEDULER_FACTORY.getScheduler().shutdown(true); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 恢复任务 + * + * @param jobName + * @param jobGroupName + */ + public static void resume(String jobName, String jobGroupName) { + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.resumeJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (SchedulerException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 暂停任务 + * + * @param jobName + * @param jobGroupName + */ + public static void pause(String jobName, String jobGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.pauseJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (SchedulerException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } + + /** + * 触发任务 + * + * @param jobName + * @param jobGroupName + */ + public static void trigger(String jobName, String jobGroupName) { + + try { + DynamicDataSourceContextHolder.push("master"); + Scheduler sched = SCHEDULER_FACTORY.getScheduler(); + sched.triggerJob(JobKey.jobKey(jobName, jobGroupName)); + } catch (SchedulerException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } finally { + DynamicDataSourceContextHolder.poll(); + } + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzJob.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzJob.java new file mode 100644 index 0000000..cf7c53d --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/components/qrtz/QrtzJob.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.template.core.components.qrtz; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.ClientException; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import java.io.Serializable; +import lombok.extern.slf4j.Slf4j; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * 定时任务 + */ +@Slf4j +@DisallowConcurrentExecution +public abstract class QrtzJob implements Job, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + + log.info("开始执行定时任务【{}】", this.getClass().getName()); + long begTime = System.currentTimeMillis(); + + try { + // 这里获取tenantId 如果为空则不设置租户ID + Integer tenantId = (Integer) context.getJobDetail().getJobDataMap().get(StringPool.TENANT_ID_QRTZ); + if (tenantId != null) { + TenantContextHolder.setTenantId(tenantId); + } + this.onExecute(context); + long endTime = System.currentTimeMillis(); + log.info("定时任务【{}】执行完毕,共耗时{}ms", this.getClass().getName(), endTime - begTime); + } catch (Exception e) { + if (e instanceof ClientException) { + log.warn("执行定时任务【{}】失败", this.getClass().getName()); + log.warn(e.getMessage(), e); + } else { + log.error("执行定时任务【{}】失败", this.getClass().getName()); + log.error(e.getMessage(), e); + } + throw new JobExecutionException(e); + } finally { + TenantContextHolder.clearTenantId(); + } + } + + protected abstract void onExecute(JobExecutionContext context) throws Exception; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/config/MpInterceptorConfiguration.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/config/MpInterceptorConfiguration.java new file mode 100644 index 0000000..11b9135 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/config/MpInterceptorConfiguration.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.template.core.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.lframework.xingyun.template.core.components.permission.DataPermissionHandlerImpl; +import com.lframework.xingyun.template.core.interceptors.CustomSortInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MpInterceptorConfiguration { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor( + new DataPermissionInterceptor(new DataPermissionHandlerImpl())); + interceptor.addInnerInterceptor(new CustomSortInterceptor()); + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/DeptDto.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/DeptDto.java new file mode 100644 index 0000000..25820f6 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/DeptDto.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.core.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class DeptDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "DeptDto"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/UserDto.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/UserDto.java new file mode 100644 index 0000000..96e1d67 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/dto/UserDto.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.core.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +/** + * 用户Dto + * + * @author zmj + */ +@Data +public class UserDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "UserDto"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 姓名 + */ + private String name; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/OpLogs.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/OpLogs.java new file mode 100644 index 0000000..6d685c1 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/OpLogs.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.template.core.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 操作日志实体类 + *

+ * + * @author zmj + */ +@Data +@TableName("op_logs") +public class OpLogs extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 日志名称 + */ + private String name; + + /** + * 类别 + */ + private Integer logType; + + /** + * IP地址 + */ + private String ip; + + /** + * 补充信息 + */ + private String extra; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/RecursionMapping.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/RecursionMapping.java new file mode 100644 index 0000000..655c7d3 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/RecursionMapping.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * 递归映射 + *

+ * + * @author zmj + * @since 2021-06-27 + */ +@Data +@TableName("recursion_mapping") +public class RecursionMapping extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 节点ID + */ + private String nodeId; + + /** + * 节点类型 + */ + private Integer nodeType; + + /** + * 从顶点到当前结点的路径,用,分割 + */ + private String path; + + /** + * 节点层级 + */ + private Integer level; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionData.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionData.java new file mode 100644 index 0000000..aa27649 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionData.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.template.core.enums.SysDataPermissionDataBizType; +import lombok.Data; + +/** + *

+ * 数据权限数据 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_permission_data") +public class SysDataPermissionData extends BaseEntity implements BaseDto { + + /** + * ID + */ + private String id; + + /** + * 业务ID + */ + private String bizId; + + /** + * 业务类型 + */ + private SysDataPermissionDataBizType bizType; + + /** + * 权限类型 + */ + private Integer permissionType; + + /** + * 权限 + */ + private String permission; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionModelDetail.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionModelDetail.java new file mode 100644 index 0000000..462dad9 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysDataPermissionModelDetail.java @@ -0,0 +1,67 @@ +package com.lframework.xingyun.template.core.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailInputType; +import lombok.Data; + +/** + *

+ * 数据权限模型明细 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_permission_model_detail") +public class SysDataPermissionModelDetail extends BaseEntity implements BaseDto { + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 模型ID + */ + private Integer modelId; + + /** + * 条件 + */ + private String conditionType; + + /** + * 输入类型 + */ + private SysDataPermissionModelDetailInputType inputType; + + /** + * 表名 + */ + private String tableName; + + /** + * 字段名 + */ + private String columnName; + + /** + * 前段枚举名 + */ + private String enumName; + + /** + * SQL + */ + private String sqlValue; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysUser.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysUser.java new file mode 100644 index 0000000..c90dead --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/entity/SysUser.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.template.core.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.template.core.enums.Gender; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user") +public class SysUser extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysUser"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 姓名 + */ + private String name; + + /** + * 用户名 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 邮箱 + */ + private String email; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 性别 0-未知 1-男 2-女 + */ + private Gender gender; + + /** + * 状态 1-在用 0停用 + */ + private Boolean available; + + /** + * 锁定状态 + */ + private Boolean lockStatus; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Available.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Available.java new file mode 100644 index 0000000..597ce0e --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Available.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum Available implements BaseEnum { + ENABLE(Boolean.TRUE, "启用"), UNABLE(Boolean.FALSE, "停用"); + + + @EnumValue + private final Boolean code; + + private final String desc; + + Available(Boolean code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Boolean getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/DefaultOpLogType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/DefaultOpLogType.java new file mode 100644 index 0000000..3d42c74 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/DefaultOpLogType.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.core.enums; + +/** + * 默认操作日志类别 + * + * @author zmj + */ +public interface DefaultOpLogType { + + /** + * 用户认证 + */ + int AUTH = 1; + + /** + * 系统管理 + */ + int SYSTEM = 2; + + /** + * 其他 + */ + int OTHER = 99; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Gender.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Gender.java new file mode 100644 index 0000000..a3d51d5 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/Gender.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum Gender implements BaseEnum { + UNKNOWN(0, "未知"), MAN(1, "男"), FEMALE(2, "女"); + + @EnumValue + private final Integer code; + + private final String desc; + + Gender(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/NodeType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/NodeType.java new file mode 100644 index 0000000..5fa2615 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/NodeType.java @@ -0,0 +1,7 @@ +package com.lframework.xingyun.template.core.enums; + +import com.lframework.starter.web.enums.BaseEnum; + +public interface NodeType extends BaseEnum { + +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionDataBizType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionDataBizType.java new file mode 100644 index 0000000..a4897c8 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionDataBizType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysDataPermissionDataBizType implements BaseEnum { + ROLE(0, "角色"), DEPT(1, "部门"), USER(2, "用户"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysDataPermissionDataBizType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailCalcType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailCalcType.java new file mode 100644 index 0000000..13c070f --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailCalcType.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysDataPermissionModelDetailCalcType implements BaseEnum { + + AND(1, "AND", "并且"), OR(2, "OR", "或者"); + + @EnumValue + private final Integer code; + + private String operation; + + private final String desc; + + SysDataPermissionModelDetailCalcType(Integer code, String operation, String desc) { + + this.code = code; + this.operation = operation; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public String getOperation() { + return operation; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailConditionType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailConditionType.java new file mode 100644 index 0000000..bb8b0a4 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailConditionType.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysDataPermissionModelDetailConditionType implements BaseEnum { + + EQ(0, "=", "等于"), GT(1, ">", "大于"), GE(2, ">=", "大于或等于"), LT(3, "<", "小于"), LE(4, "<=", + "小于或等于"), NE(5, + "!=", "不等于"), IN(6, "IN", "在列表中"), NOT_IN(7, + "NOT IN", "不在列表中"), LEFT_LIKE(8, "LIKE", "结尾"), RIGHT_LIKE(9, "LIKE", + "开头"), AROUND_LIKE(10, "LIKE", "包含"); + + @EnumValue + private final Integer code; + + private final String operation; + + private final String desc; + + SysDataPermissionModelDetailConditionType(Integer code, String operation, String desc) { + + this.code = code; + this.operation = operation; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public String getOperation() { + return operation; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailInputType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailInputType.java new file mode 100644 index 0000000..b9f1b1e --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailInputType.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysDataPermissionModelDetailInputType implements BaseEnum { + + INPUT(0, "输入框"), SELECT(1, "选择器"), DATE_TIME(2, "日期时间选择器"), DATE(3, + "日期选择器"), SQL(99, "SQL"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysDataPermissionModelDetailInputType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailNodeType.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailNodeType.java new file mode 100644 index 0000000..507b2ce --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/enums/SysDataPermissionModelDetailNodeType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.core.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysDataPermissionModelDetailNodeType implements BaseEnum { + + CALC(1, "运算节点"), CONDITION(2, "条件节点"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysDataPermissionModelDetailNodeType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/DeptServiceImpl.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/DeptServiceImpl.java new file mode 100644 index 0000000..460fb8a --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/DeptServiceImpl.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.core.impl; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.dto.DeptDto; +import com.lframework.xingyun.template.core.mappers.DeptMapper; +import com.lframework.xingyun.template.core.service.DeptService; +import java.io.Serializable; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +/** + * @author zmj + */ +@Service +public class DeptServiceImpl implements DeptService { + + @Autowired + private DeptMapper deptMapper; + + @Cacheable(value = DeptDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public DeptDto findById(String id) { + + if (StringUtil.isBlank(id)) { + return null; + } + + return deptMapper.findById(id); + } + + @Override + public DeptDto findByCode(String code) { + return deptMapper.findByCode(code); + } + + @CacheEvict(value = {DeptDto.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/OpLogsServiceImpl.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/OpLogsServiceImpl.java new file mode 100644 index 0000000..abad287 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/OpLogsServiceImpl.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.template.core.impl; + +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.mappers.OpLogsMapper; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.vo.CreateOpLogsVo; +import com.lframework.xingyun.template.core.vo.QueryOpLogsVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 操作日志Service实现 + * + * @author zmj + */ +@Slf4j +@Service +public class OpLogsServiceImpl extends BaseMpServiceImpl + implements OpLogsService { + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateOpLogsVo vo) { + + OpLogs record = this.doCreate(vo); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(Collection list) { + if (CollectionUtil.isEmpty(list)) { + return; + } + List records = list.stream().map(this::doCreate).collect(Collectors.toList()); + this.saveBatch(records); + } + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryOpLogsVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doQuery(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public OpLogs findById(String id) { + + return this.doGetById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void clearLogs(LocalDateTime endTime) { + + log.info("开始清除创建时间早于{}的操作日志", endTime); + + this.doClearLogs(endTime); + } + + protected OpLogs doCreate(CreateOpLogsVo vo) { + + OpLogs record = new OpLogs(); + record.setId(IdUtil.getId()); + record.setName(vo.getName()); + record.setLogType(vo.getLogType()); + if (!StringUtil.isBlank(vo.getCreateBy())) { + record.setCreateBy(vo.getCreateBy()); + } + + if (!StringUtil.isBlank(vo.getCreateById())) { + record.setCreateById(vo.getCreateById()); + } + + if (!StringUtil.isBlank(vo.getExtra())) { + record.setExtra(vo.getExtra()); + } + record.setIp(vo.getIp()); + + return record; + } + + protected List doQuery(QueryOpLogsVo vo) { + + return getBaseMapper().query(vo); + } + + protected OpLogs doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected void doClearLogs(LocalDateTime endTime) { + + getBaseMapper().clearLogs(endTime); + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/RecursionMappingServiceImpl.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/RecursionMappingServiceImpl.java new file mode 100644 index 0000000..2c4b71a --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/RecursionMappingServiceImpl.java @@ -0,0 +1,102 @@ +package com.lframework.xingyun.template.core.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.entity.RecursionMapping; +import com.lframework.xingyun.template.core.enums.NodeType; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.core.mappers.RecursionMappingMapper; +import java.util.ArrayList; +import java.util.List; +import lombok.NonNull; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class RecursionMappingServiceImpl extends + BaseMpServiceImpl + implements RecursionMappingService { + + @Override + public List getNodeParentIds(@NonNull String nodeId, @NonNull NodeType nodeType) { + + if (StringUtil.isEmpty(nodeId)) { + return CollectionUtil.emptyList(); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .eq(RecursionMapping::getNodeId, nodeId) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + + RecursionMapping recursionMappings = getBaseMapper().selectOne(queryWrapper); + if (recursionMappings == null || StringUtil.isEmpty(recursionMappings.getPath())) { + return CollectionUtil.emptyList(); + } + + return StringUtil.split(recursionMappings.getPath(), StringPool.STR_SPLIT); + } + + @Override + public List getNodeChildIds(String nodeId, NodeType nodeType) { + + return getBaseMapper().getNodeChildIds(nodeId, nodeType.getCode()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveNode(String nodeId, NodeType nodeType) { + + this.saveNode(nodeId, nodeType, null); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteNode(String nodeId, NodeType nodeType) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .eq(RecursionMapping::getNodeId, nodeId) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + getBaseMapper().delete(deleteWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteNodeAndChildren(String nodeId, NodeType nodeType) { + List childNodeIds = this.getNodeChildIds(nodeId, nodeType); + List allNodeIds = new ArrayList<>(); + allNodeIds.add(nodeId); + allNodeIds.addAll(childNodeIds); + Wrapper deleteWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .in(RecursionMapping::getNodeId, allNodeIds) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + getBaseMapper().delete(deleteWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveNode(@NonNull String nodeId, @NonNull NodeType nodeType, List parentIds) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(RecursionMapping.class) + .eq(RecursionMapping::getNodeId, nodeId) + .eq(RecursionMapping::getNodeType, nodeType.getCode()); + getBaseMapper().delete(deleteWrapper); + + RecursionMapping data = new RecursionMapping(); + data.setId(IdUtil.getId()); + data.setNodeId(nodeId); + data.setNodeType(nodeType.getCode()); + data.setLevel(1); + data.setPath(StringPool.EMPTY_STR); + if (!CollectionUtil.isEmpty(parentIds)) { + data.setPath(StringUtil.join(StringPool.STR_SPLIT, parentIds)); + data.setLevel(parentIds.size() + 1); + } + + getBaseMapper().insert(data); + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/SysDataPermissionModelDetailServiceImpl.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/SysDataPermissionModelDetailServiceImpl.java new file mode 100644 index 0000000..9734d1a --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/SysDataPermissionModelDetailServiceImpl.java @@ -0,0 +1,145 @@ +package com.lframework.xingyun.template.core.impl; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.xingyun.template.core.vo.permission.SysDataPermissionModelDetailVo; +import com.lframework.xingyun.template.core.entity.SysDataPermissionModelDetail; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailCalcType; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailConditionType; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailInputType; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailNodeType; +import com.lframework.xingyun.template.core.mappers.SysDataPermissionModelDetailMapper; +import com.lframework.xingyun.template.core.service.SysDataPermissionModelDetailService; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.springframework.stereotype.Service; + +@Service +public class SysDataPermissionModelDetailServiceImpl extends + BaseMpServiceImpl implements + SysDataPermissionModelDetailService { + + @Override + public String toSql(List models) { + if (CollectionUtil.isEmpty(models)) { + return null; + } + + StringBuilder builder = new StringBuilder(); + + for (SysDataPermissionModelDetailVo model : models) { + SysDataPermissionModelDetailNodeType nodeType = EnumUtil.getByCode( + SysDataPermissionModelDetailNodeType.class, model.getNodeType()); + if (nodeType == SysDataPermissionModelDetailNodeType.CALC) { + SysDataPermissionModelDetailCalcType calcType = EnumUtil.getByCode( + SysDataPermissionModelDetailCalcType.class, model.getCalcType()); + if (CollectionUtil.isNotEmpty(model.getChildren())) { + builder.append(" ("); + builder.append(this.buildChildrenSql(model.getChildren(), calcType.getOperation())); + builder.append(") "); + } + builder.append("AND "); + } else { + throw new DefaultSysException("nodeType有误,请检查!"); + } + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - 4); + } + return builder.toString(); + } + + @Override + public String formatSql(String sqlTemplate, Map params) { + return StringUtil.format(sqlTemplate, params); + } + + private String buildChildrenSql(List children, String operation) { + if (CollectionUtil.isEmpty(children)) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + for (SysDataPermissionModelDetailVo child : children) { + SysDataPermissionModelDetailNodeType nodeType = EnumUtil.getByCode( + SysDataPermissionModelDetailNodeType.class, child.getNodeType()); + if (nodeType == SysDataPermissionModelDetailNodeType.CALC) { + SysDataPermissionModelDetailCalcType calcType = EnumUtil.getByCode( + SysDataPermissionModelDetailCalcType.class, child.getCalcType()); + if (CollectionUtil.isNotEmpty(child.getChildren())) { + builder.append(" ("); + builder.append(this.buildChildrenSql(child.getChildren(), calcType.getOperation())); + builder.append(")"); + builder.append(operation).append(" "); + } + } else { + SysDataPermissionModelDetailConditionType conditionType = EnumUtil.getByCode( + SysDataPermissionModelDetailConditionType.class, child.getConditionType()); + SysDataPermissionModelDetail record = this.getById(child.getDetailId()); + builder.append("{").append(record.getTableName()).append("}.") + .append(record.getColumnName()).append(" ").append(conditionType.getOperation()) + .append(" ").append(this.buildLeft(conditionType)) + .append(this.buildValue(child, record)) + .append(this.buildRight(conditionType)).append(" ").append(operation).append(" "); + } + } + + if (builder.length() > 0) { + builder.setLength(builder.length() - operation.length() - 1); + } + + return builder.toString(); + } + + private String buildLeft(SysDataPermissionModelDetailConditionType conditionType) { + if (conditionType == SysDataPermissionModelDetailConditionType.IN + || conditionType == SysDataPermissionModelDetailConditionType.NOT_IN) { + return "("; + } else if (conditionType == SysDataPermissionModelDetailConditionType.LEFT_LIKE) { + return "CONCAT('%',"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.RIGHT_LIKE) { + return "CONCAT("; + } else if (conditionType == SysDataPermissionModelDetailConditionType.AROUND_LIKE) { + return "CONCAT('%',"; + } + + return ""; + } + + private String buildRight(SysDataPermissionModelDetailConditionType conditionType) { + if (conditionType == SysDataPermissionModelDetailConditionType.IN + || conditionType == SysDataPermissionModelDetailConditionType.NOT_IN) { + return ")"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.LEFT_LIKE) { + return ")"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.RIGHT_LIKE) { + return ",'%')"; + } else if (conditionType == SysDataPermissionModelDetailConditionType.AROUND_LIKE) { + return ",'%')"; + } + + return ""; + } + + private String buildValue(SysDataPermissionModelDetailVo child, + SysDataPermissionModelDetail record) { + SysDataPermissionModelDetailConditionType conditionType = EnumUtil.getByCode( + SysDataPermissionModelDetailConditionType.class, child.getConditionType()); + if (conditionType == SysDataPermissionModelDetailConditionType.IN + || conditionType == SysDataPermissionModelDetailConditionType.NOT_IN) { + if (record.getInputType() == SysDataPermissionModelDetailInputType.SQL) { + return record.getSqlValue(); + } else { + return CollectionUtil.join( + child.getValues().stream().map(t -> "'" + t + "'").collect(Collectors.toList()), ","); + } + } + + return "'" + child.getValue() + "'"; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/UserServiceImpl.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/UserServiceImpl.java new file mode 100644 index 0000000..a2589bd --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/impl/UserServiceImpl.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.template.core.impl; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.core.mappers.UserMapper; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.dto.UserDto; +import java.io.Serializable; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +/** + * 默认用户Service实现 + * + * @author zmj + */ +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserMapper userMapper; + + @Cacheable(value = UserDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public UserDto findById(String id) { + + if (StringUtil.isBlank(id)) { + return null; + } + + return userMapper.findById(id); + } + + @Override + public UserDto findByCode(String code) { + return userMapper.findByCode(code); + } + + @CacheEvict(value = {UserDto.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/interceptors/CustomSortInterceptor.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/interceptors/CustomSortInterceptor.java new file mode 100644 index 0000000..c3fdcb7 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/interceptors/CustomSortInterceptor.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.template.core.interceptors; + +import com.baomidou.mybatisplus.core.toolkit.PluginUtils; +import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.vo.SortPageVo; +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParser; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.parser.ParseException; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +@Slf4j +public class CustomSortInterceptor extends JsqlParserSupport implements InnerInterceptor { + + @Override + public void beforeQuery( + Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, + ResultHandler resultHandler, BoundSql boundSql) throws SQLException { + if (parameter instanceof Map) { + Map map = (Map) parameter; + List sortPageVos = map.values().stream() + .filter(t -> t instanceof SortPageVo).map(t -> (SortPageVo) t) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(sortPageVos)) { + return; + } + Map sortMap = this.convertSortMap(ms.getId()); + if (CollectionUtil.isEmpty(sortMap)) { + return; + } + + StringBuilder sqlBuilder = new StringBuilder("ORDER BY "); + + List orderBySqlElements = sortPageVos.stream() + .filter(t -> sortMap.containsKey(t.getSortField())).map( + t -> sortMap.get(t.getSortField()) + " " + ( + "asc".equalsIgnoreCase(t.getSortOrder()) ? "ASC" : "DESC")).distinct() + .collect( + Collectors.toList()); + + if (CollectionUtil.isEmpty(orderBySqlElements)) { + return; + } + + // order by code asc, name desc + String sqlProvider = sqlBuilder.append(StringUtil.join(",", orderBySqlElements)) + .toString(); + + CCJSqlParser parser = CCJSqlParserUtil.newParser(sqlProvider); + + PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); + + String sql = mpBs.sql(); + try { + Statement statement = CCJSqlParserUtil.parse(sql); + PlainSelect plainSelect = (PlainSelect) ((Select) statement).getSelectBody(); + plainSelect.setOrderByElements(parser.OrderByElements()); + mpBs.sql(statement.toString()); + } catch (JSQLParserException | ParseException e) { + log.error("Failed to process, Error SQL: {}", sql); + log.error(e.getMessage(), e); + } + } + } + + private Map convertSortMap(String statementId) { + // 获取Mapper执行方法上的注解 + Method mapperMethod = null; + try { + mapperMethod = this.findMapperMethod(this.convertMsId(statementId)); + } catch (ClassNotFoundException e) { + return null; + } + if (mapperMethod == null) { + return null; + } + Sorts sorts = mapperMethod.getAnnotation(Sorts.class); + + if (sorts != null) { + Sort[] sortList = sorts.value(); + Map sortKeyMap = new HashMap<>(sortList.length); + for (Sort sort : sortList) { + if (sort.autoParse()) { + sortKeyMap.put(sort.value(), (StringUtil.isEmpty(sort.alias()) ? "" : (sort.alias() + ".")) + StringUtil.toUnderlineCase(sort.value())); + } else { + sortKeyMap.put(sort.value(), sort.alias()); + } + } + + return sortKeyMap; + } + + return null; + } + + private String convertMsId(String id) { + return id; + } + + private Method findMapperMethod(String statementId) + throws ClassNotFoundException { + int lastDotIndex = statementId.lastIndexOf("."); + String className = statementId.substring(0, lastDotIndex); + String methodName = statementId.substring(lastDotIndex + 1); + + Class mapperInterface = Class.forName(className); + return Arrays.stream(mapperInterface.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .findFirst() + .orElse(null); + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/DeptMapper.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/DeptMapper.java new file mode 100644 index 0000000..5050f09 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/DeptMapper.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.template.core.mappers; + +import com.lframework.xingyun.template.core.dto.DeptDto; + +/** + * @author zmj + */ +public interface DeptMapper { + + /** + * 根据ID查询 主要用于各个业务关联查询信息 + * + * @param id + * @return + */ + DeptDto findById(String id); + + /** + * 根据编号查询 + * + * @param code + * @return + */ + DeptDto findByCode(String code); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/OpLogsMapper.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/OpLogsMapper.java new file mode 100644 index 0000000..6691cfa --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/OpLogsMapper.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.vo.QueryOpLogsVo; +import java.time.LocalDateTime; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 操作日志 Mapper + *

+ * + * @author zmj + */ +public interface OpLogsMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryOpLogsVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + OpLogs findById(String id); + + /** + * 根据截止时间删除日志 + * + * @param endTime + */ + void clearLogs(@Param("endTime") LocalDateTime endTime); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/RecursionMappingMapper.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/RecursionMappingMapper.java new file mode 100644 index 0000000..13e5513 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/RecursionMappingMapper.java @@ -0,0 +1,19 @@ +package com.lframework.xingyun.template.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.core.entity.RecursionMapping; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 递归映射 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-06-27 + */ +public interface RecursionMappingMapper extends BaseMapper { + + List getNodeChildIds(@Param("nodeId") String nodeId, @Param("nodeType") Integer nodeType); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/SysDataPermissionModelDetailMapper.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/SysDataPermissionModelDetailMapper.java new file mode 100644 index 0000000..9398f06 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/SysDataPermissionModelDetailMapper.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.template.core.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.core.entity.SysDataPermissionModelDetail; + +public interface SysDataPermissionModelDetailMapper extends + BaseMapper { + +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/UserMapper.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/UserMapper.java new file mode 100644 index 0000000..e8f2fc8 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/mappers/UserMapper.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.core.mappers; + +import com.lframework.xingyun.template.core.dto.UserDto; + +/** + * 默认UserMapper + * + * @author zmj + */ +public interface UserMapper { + + /** + * 根据ID查询 主要用于各个业务关联查询用户信息 + * + * @param id + * @return + */ + UserDto findById(String id); + + /** + * 根据编号查询 + * + * @param code + * @return + */ + UserDto findByCode(String code); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/DeptService.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/DeptService.java new file mode 100644 index 0000000..f33c5a1 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/DeptService.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.core.service; + +import com.lframework.starter.web.service.BaseService; +import com.lframework.xingyun.template.core.dto.DeptDto; + +/** + * 部门Service + * + * @author zmj + */ +public interface DeptService extends BaseService { + + /** + * 根据ID查询 主要用于各个业务关联查询信息 + * + * @param id + * @return + */ + DeptDto findById(String id); + + /** + * 根据编号查询 + * + * @param code + * @return + */ + DeptDto findByCode(String code); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/OpLogsService.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/OpLogsService.java new file mode 100644 index 0000000..1537d09 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/OpLogsService.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.template.core.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.vo.CreateOpLogsVo; +import com.lframework.xingyun.template.core.vo.QueryOpLogsVo; +import java.time.LocalDateTime; +import java.util.Collection; + +/** + * 操作日志Service + * + * @author zmj + */ +public interface OpLogsService extends BaseMpService { + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateOpLogsVo vo); + + /** + * 创建 + * + * @param list + * @return + */ + void create(Collection list); + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryOpLogsVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + OpLogs findById(String id); + + /** + * 根据截止时间删除日志 + * + * @param endTime + */ + void clearLogs(LocalDateTime endTime); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/RecursionMappingService.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/RecursionMappingService.java new file mode 100644 index 0000000..7588761 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/RecursionMappingService.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.template.core.service; + + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.core.entity.RecursionMapping; +import com.lframework.xingyun.template.core.enums.NodeType; +import java.util.List; + +public interface RecursionMappingService extends BaseMpService { + + /** + * 查询节点的父节点ID + * + * @param nodeId + * @param nodeType + * @return + */ + List getNodeParentIds(String nodeId, NodeType nodeType); + + /** + * 查询节点的子节点ID + * + * @param nodeId + * @param nodeType + * @return + */ + List getNodeChildIds(String nodeId, NodeType nodeType); + + + /** + * 保存节点递归信息 + * + * @param nodeId + * @param nodeType + * @param parentIds 顺序有意义,需要从顶点到终点的顺序排列 + */ + void saveNode(String nodeId, NodeType nodeType, List parentIds); + + /** + * 保存节点递归信息 + * + * @param nodeId + * @param nodeType + */ + void saveNode(String nodeId, NodeType nodeType); + + /** + * 根据节点ID删除 + * + * @param nodeId + * @param nodeType + */ + void deleteNode(String nodeId, NodeType nodeType); + + /** + * 根据节点ID删除以及子节点 + * + * @param nodeId + * @param nodeType + */ + void deleteNodeAndChildren(String nodeId, NodeType nodeType); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/SysDataPermissionModelDetailService.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/SysDataPermissionModelDetailService.java new file mode 100644 index 0000000..6868f7f --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/SysDataPermissionModelDetailService.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.core.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.core.vo.permission.SysDataPermissionModelDetailVo; +import com.lframework.xingyun.template.core.entity.SysDataPermissionModelDetail; +import java.util.List; +import java.util.Map; + +public interface SysDataPermissionModelDetailService extends + BaseMpService { + + /** + * 解析SQL + * + * @param models + * @return + */ + String toSql(List models); + + /** + * 格式化SQL + * + * @param sqlTemplate + * @param params 表别名Map Key:表名占位符,具体定义数据表中的table_name Value:具体SQL的别名 + * @return + */ + String formatSql(String sqlTemplate, Map params); + +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/UserService.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/UserService.java new file mode 100644 index 0000000..e009d30 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/service/UserService.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.core.service; + +import com.lframework.xingyun.template.core.dto.UserDto; +import com.lframework.starter.web.service.BaseService; + +/** + * 用户Service + * + * @author zmj + */ +public interface UserService extends BaseService { + + /** + * 根据ID查询 主要用于各个业务关联查询用户信息 + * + * @param id + * @return + */ + UserDto findById(String id); + + /** + * 根据编号查询 + * + * @param code + * @return + */ + UserDto findByCode(String code); +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/OpLogUtil.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/OpLogUtil.java new file mode 100644 index 0000000..9493165 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/OpLogUtil.java @@ -0,0 +1,117 @@ +package com.lframework.xingyun.template.core.utils; + +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.vo.CreateOpLogsVo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.JsonUtil; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; + +/** + * 操作日志Util + * + * @author zmj + */ +@Slf4j +public class OpLogUtil { + + private static final ThreadLocal>> VARIABLE_POOL = new ThreadLocal<>(); + + private static final ThreadLocal> LOG_ID_POOL = new ThreadLocal<>(); + + private static final ThreadLocal> EXTRA_POOL = new ThreadLocal<>(); + + public static void init(String logId) { + + initPool(); + + LOG_ID_POOL.get().add(logId); + + VARIABLE_POOL.get().putIfAbsent(logId, new HashMap<>()); + } + + public static void addLog(CreateOpLogsVo vo) { + + try { + OpLogsService opLogsService = ApplicationUtil.getBean(OpLogsService.class); + + // 这里不异步,需要在同事务内执行 + opLogsService.create(vo); + } catch (Exception e) { + // 这里异常不抛出 + log.error(e.getMessage(), e); + } + } + + public static void addLogs(Collection list) { + + try { + OpLogsService opLogsService = ApplicationUtil.getBean(OpLogsService.class); + + // 这里不异步,需要在同事务内执行 + opLogsService.create(list); + } catch (Exception e) { + // 这里异常不抛出 + log.error(e.getMessage(), e); + } + } + + public static void setVariable(String key, Object value) { + try { + VARIABLE_POOL.get().get(getCurrentLogId()).put(key, value); + }catch (Exception e){ + String logId = IdUtil.getUUID(); + init(logId); + VARIABLE_POOL.get().get(getCurrentLogId()).put(key, value); + } + + } + + public static Map getVariables() { + + return VARIABLE_POOL.get().get(getCurrentLogId()); + } + + public static String getExtra() { + + Object value = EXTRA_POOL.get().get(getCurrentLogId()); + + return value == null ? null : JsonUtil.toJsonString(value); + } + + public static void setExtra(Object value) { + + EXTRA_POOL.get().put(getCurrentLogId(), value); + } + + public static void clear() { + + VARIABLE_POOL.get().remove(getCurrentLogId()); + EXTRA_POOL.get().remove(getCurrentLogId()); + LOG_ID_POOL.get().remove(LOG_ID_POOL.get().size() - 1); + } + + private static void initPool() { + + if (VARIABLE_POOL.get() == null) { + VARIABLE_POOL.set(new HashMap<>()); + } + + if (LOG_ID_POOL.get() == null) { + LOG_ID_POOL.set(new ArrayList<>()); + } + + if (EXTRA_POOL.get() == null) { + EXTRA_POOL.set(new HashMap<>()); + } + } + + private static String getCurrentLogId() { + return LOG_ID_POOL.get().get(LOG_ID_POOL.get().size() - 1); + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/WebUtils.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/WebUtils.java new file mode 100644 index 0000000..c3be30f --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/utils/WebUtils.java @@ -0,0 +1,117 @@ +package com.lframework.xingyun.template.core.utils; + +import cn.hutool.core.collection.ArrayIter; +import cn.hutool.core.collection.IterUtil; +import cn.hutool.core.map.CaseInsensitiveMap; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.ArrayUtil; +import org.springframework.util.Assert; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.Objects; + + +public class WebUtils { + + private static final String UNKNOWN ="unknown"; + + public static HttpServletRequest getHttpRequest() { + ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + Assert.notNull(attributes, "RequestContextHolder.getRequestAttributes can't be NULL"); + return attributes.getRequest(); + } + + public static HttpServletRequest getRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getRequest(); + } + + public static HttpServletResponse getResponse() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getResponse(); + } + + public static void redirect(String url) throws Exception { + redirect(getResponse(), url); + } + + public static void redirect(HttpServletResponse response, String url) throws Exception { + response.sendRedirect(url); + } + + public static void addCookie(String name, String value) { + getResponse().addCookie(new Cookie(name, value)); + } + + public static void addCookie(String name, String value, int expiry) { + Cookie cookie = new Cookie(name, value); + cookie.setMaxAge(expiry); + cookie.setPath("/"); + getResponse().addCookie(cookie); + } + + public static String getCookie(String name) { + Map cookieMap = readCookieMap(getRequest()); + return cookieMap.containsKey(name) ? ((Cookie)cookieMap.get(name)).getValue() : null; + } + + public static Map readCookieMap(HttpServletRequest httpServletRequest) { + Cookie[] cookies = httpServletRequest.getCookies(); + return ArrayUtil.isEmpty(cookies) ? MapUtil.empty() : IterUtil.toMap(new ArrayIter(httpServletRequest.getCookies()), new CaseInsensitiveMap(), Cookie::getName); + } + + + + public static String getRemoteIpAddress() { + return getRemoteIpAddress(getRequest()); + } + + /** + * 获取请求路径 + * + */ + public static String getRequestPath() { + return Objects.requireNonNull(getRequest()).getRequestURI(); + } + + public static String getRemoteIpAddress(HttpServletRequest request) { + String ip = null; + // X-Forwarded-For:Squid 服务代理 + String ipAddresses = request.getHeader("X-Forwarded-For"); + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // Proxy-Client-IP:apache 服务代理 + ipAddresses = request.getHeader("Proxy-Client-IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ipAddresses = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // WL-Proxy-Client-IP:weblogic 服务代理 + ipAddresses = request.getHeader("WL-Proxy-Client-IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // HTTP_CLIENT_IP:有些代理服务器 + ipAddresses = request.getHeader("HTTP_CLIENT_IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // X-Real-IP:nginx服务代理 + ipAddresses = request.getHeader("X-Real-IP"); + } + // 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP + if (CharSequenceUtil.isNotBlank(ipAddresses)) { + ip = ipAddresses.split(",")[0]; + } + // 还是不能获取到,最后再通过request.getRemoteAddr();获取 + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ip = request.getRemoteAddr(); + } + return ip; + } +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/CreateOpLogsVo.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/CreateOpLogsVo.java new file mode 100644 index 0000000..c2c7dc9 --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/CreateOpLogsVo.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.template.core.vo; + +import com.lframework.starter.web.vo.BaseVo; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 新增操作日志Vo + * + * @author zmj + */ +@Data +public class CreateOpLogsVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 日志名称 + */ + @NotBlank(message = "日志名称不能为空!") + private String name; + + /** + * 类型 + */ + @NotNull(message = "日志类型不能为空!") + private Integer logType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建人ID + */ + private String createById; + + /** + * IP地址 + */ + @NotBlank(message = "IP地址不能为空!") + private String ip; + + /** + * 补充信息 + */ + private String extra; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/QueryOpLogsVo.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/QueryOpLogsVo.java new file mode 100644 index 0000000..cf3d54e --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/QueryOpLogsVo.java @@ -0,0 +1,47 @@ +package com.lframework.xingyun.template.core.vo; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 查询操作日志Vo + * + * @author zmj + */ +@Data +public class QueryOpLogsVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 日志名称 + */ + @ApiModelProperty("日志名称") + private String name; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 日志类别 + */ + @ApiModelProperty("日志类别") + private Integer logType; + + /** + * 创建起始时间 + */ + @ApiModelProperty("创建起始时间") + private LocalDateTime startTime; + + /** + * 创建截止时间 + */ + @ApiModelProperty("创建截止时间") + private LocalDateTime endTime; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/CreateSysDataPermissionDataVo.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/CreateSysDataPermissionDataVo.java new file mode 100644 index 0000000..5d090ec --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/CreateSysDataPermissionDataVo.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.template.core.vo.permission; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.template.core.enums.SysDataPermissionDataBizType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSysDataPermissionDataVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务ID + */ + @ApiModelProperty(value = "业务ID", required = true) + @NotEmpty(message = "业务ID不能为空!") + private List bizIds; + + /** + * 业务类型 + */ + @ApiModelProperty(value = "业务类型", required = true) + @NotNull(message = "业务类型不能为空!") + @IsEnum(message = "业务类型格式错误!", enumClass = SysDataPermissionDataBizType.class) + private Integer bizType; + + /** + * 权限类型 + */ + @ApiModelProperty(value = "权限类型", required = true) + @NotNull(message = "权限类型不能为空!") + private Integer permissionType; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; +} diff --git a/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/SysDataPermissionModelDetailVo.java b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/SysDataPermissionModelDetailVo.java new file mode 100644 index 0000000..b69246d --- /dev/null +++ b/xingyun-template-core/src/main/java/com/lframework/xingyun/template/core/vo/permission/SysDataPermissionModelDetailVo.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.template.core.vo.permission; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class SysDataPermissionModelDetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + + private String id; + + /** + * 明细ID + */ + @ApiModelProperty(value = "明细ID", required = true) + @NotNull(message = "明细ID不能为空!") + private Integer detailId; + + /** + * 节点类型 + */ + @ApiModelProperty(value = "节点类型", required = true) + @NotNull(message = "节点类型不能为空!") + private Integer nodeType; + + /** + * 计算类型 + */ + @ApiModelProperty("计算类型") + private Integer calcType; + + /** + * 值 + */ + @ApiModelProperty("值") + private String value; + + /** + * 值 + */ + @ApiModelProperty("值") + private List values; + + /** + * 条件类型 + */ + @ApiModelProperty("条件类型") + private Integer conditionType; + + /** + * 子节点 + */ + @ApiModelProperty("子节点") + private List children; +} diff --git a/xingyun-template-core/src/main/java/lombok.config b/xingyun-template-core/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-template-core/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-template-core/src/main/resources/mappers/DeptMapper.xml b/xingyun-template-core/src/main/resources/mappers/DeptMapper.xml new file mode 100644 index 0000000..2d30636 --- /dev/null +++ b/xingyun-template-core/src/main/resources/mappers/DeptMapper.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/xingyun-template-core/src/main/resources/mappers/OpLogsMapper.xml b/xingyun-template-core/src/main/resources/mappers/OpLogsMapper.xml new file mode 100644 index 0000000..537503d --- /dev/null +++ b/xingyun-template-core/src/main/resources/mappers/OpLogsMapper.xml @@ -0,0 +1,49 @@ + + + + + + SELECT + * + FROM op_logs + + + DELETE FROM op_logs + WHERE + + + + + + + diff --git a/xingyun-template-core/src/main/resources/mappers/RecursionMappingMappre.xml b/xingyun-template-core/src/main/resources/mappers/RecursionMappingMappre.xml new file mode 100644 index 0000000..66c2164 --- /dev/null +++ b/xingyun-template-core/src/main/resources/mappers/RecursionMappingMappre.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/xingyun-template-core/src/main/resources/mappers/UserMapper.xml b/xingyun-template-core/src/main/resources/mappers/UserMapper.xml new file mode 100644 index 0000000..04c331f --- /dev/null +++ b/xingyun-template-core/src/main/resources/mappers/UserMapper.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/xingyun-template/pom.xml b/xingyun-template/pom.xml new file mode 100644 index 0000000..3ff0b86 --- /dev/null +++ b/xingyun-template/pom.xml @@ -0,0 +1,38 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-template + + 【${project.artifactId}】此Module与业务无关,提供用户、角色、部门、岗位等基础接口 + + + + com.lframework + xingyun-template-core + + + com.lframework + websocket-starter + + + org.freemarker + freemarker + + + org.ssssssss + magic-api-spring-boot-starter + + + org.ssssssss + magic-api-plugin-cluster + + + \ No newline at end of file diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/config/TemplateApiConfiguration.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/config/TemplateApiConfiguration.java new file mode 100644 index 0000000..4cd982e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/config/TemplateApiConfiguration.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.config; + +import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +@Configuration +public class TemplateApiConfiguration { + + @Bean("templateApiDocket") + public Docket securityAPiDocket(ApiInfo info, OpenApiExtensionResolver openApiExtensionResolver) { + + // 除了描述 其他全与info保持一致 + ApiInfo apiInfo = new ApiInfo(info.getTitle(), "系统内置模块", info.getVersion(), + info.getTermsOfServiceUrl(), + info.getContact(), info.getLicense(), info.getLicenseUrl(), info.getVendorExtensions()); + + Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName("系统内置模块") + .select() + .apis(RequestHandlerSelectors.basePackage("com.lframework.xingyun.template")) + .paths(PathSelectors.any()) + .build() + .extensions(openApiExtensionResolver.buildSettingExtensions()); + return docket; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GenCustomListSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GenCustomListSelectorBo.java new file mode 100644 index 0000000..36e4702 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GenCustomListSelectorBo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.template.gen.bo.custom.list; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.service.GenCustomListCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomListSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 数据对象ID + */ + @ApiModelProperty("数据对象ID") + private String dataObjId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + public GenCustomListSelectorBo() { + } + + public GenCustomListSelectorBo(GenCustomList dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomList dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomListCategoryService genCustomListCategoryService = ApplicationUtil.getBean( + GenCustomListCategoryService.class); + GenCustomListCategory category = genCustomListCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GetGenCustomListBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GetGenCustomListBo.java new file mode 100644 index 0000000..278ded8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/GetGenCustomListBo.java @@ -0,0 +1,500 @@ +package com.lframework.xingyun.template.gen.bo.custom.list; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.bo.SuperBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.xingyun.template.gen.entity.GenCustomListHandleColumn; +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.xingyun.template.gen.entity.GenCustomListToolbar; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.service.GenCustomListCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomListDetailService; +import com.lframework.xingyun.template.gen.service.GenCustomListHandleColumnService; +import com.lframework.xingyun.template.gen.service.GenCustomListQueryParamsService; +import com.lframework.xingyun.template.gen.service.GenCustomListToolbarService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetGenCustomListBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 数据对象ID + */ + @ApiModelProperty("数据对象ID") + private String dataObjId; + + /** + * 列表类型 + */ + @ApiModelProperty("列表类型") + private Integer listType; + + /** + * 数据对象名称 + */ + @ApiModelProperty("数据对象名称") + private String dataObjName; + + /** + * 表单Label宽度 + */ + @ApiModelProperty("表单Label宽度") + private Integer labelWidth; + + /** + * 是否分页 + */ + @ApiModelProperty("是否分页") + private Boolean hasPage; + + /** + * 是否树形列表 + */ + @ApiModelProperty("是否树形列表") + private Boolean treeData; + + /** + * ID字段 + */ + @ApiModelProperty("ID字段") + private String idColumn; + + /** + * 父级ID字段 + */ + @ApiModelProperty("父级ID字段") + private String treePidColumn; + + /** + * 树形节点字段 + */ + @ApiModelProperty("树形节点字段") + private String treeNodeColumn; + + /** + * 子节点Key值 + */ + @ApiModelProperty("子节点Key值") + private String treeChildrenKey; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 查询前置SQL + */ + @ApiModelProperty("查询前置SQL") + private String queryPrefixSql; + + /** + * 查询后置SQL + */ + @ApiModelProperty("查询后置SQL") + private String querySuffixSql; + + /** + * 后置SQL + */ + @ApiModelProperty("后置SQL") + private String suffixSql; + + /** + * 是否允许导出 + */ + @ApiModelProperty("是否允许导出") + private Boolean allowExport; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 工具栏 + */ + @ApiModelProperty("工具栏") + private List toolbars; + + /** + * 操作列 + */ + @ApiModelProperty("操作列") + private List handleColumns; + + /** + * 查询条件 + */ + @ApiModelProperty("查询条件") + private List queryParams; + + /** + * 详情 + */ + @ApiModelProperty("详情") + private List details; + + public GetGenCustomListBo() { + } + + public GetGenCustomListBo(GenCustomList dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomList dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomListCategoryService genCustomListCategoryService = ApplicationUtil.getBean( + GenCustomListCategoryService.class); + GenCustomListCategory category = genCustomListCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + + this.listType = dto.getListType().getCode(); + + GenDataEntityDetailService genDataEntityDetailService = ApplicationUtil + .getBean(GenDataEntityDetailService.class); + GenDataObjService genDataObjService = ApplicationUtil.getBean(GenDataObjService.class); + GenDataObj dataObj = genDataObjService.findById(dto.getDataObjId()); + this.dataObjName = dataObj.getName(); + + GenCustomListQueryParamsService genCustomListQueryParamsService = ApplicationUtil.getBean( + GenCustomListQueryParamsService.class); + List queryParams = genCustomListQueryParamsService.getByCustomListId( + dto.getId()); + if (!CollectionUtil.isEmpty(queryParams)) { + this.queryParams = queryParams.stream().map(t -> { + GenDataEntityDetail entityDetail = genDataEntityDetailService.getById(t.getDataEntityId()); + QueryParamsBo bo = new QueryParamsBo(); + bo.setId(t.getDataEntityId()); + bo.setRelaId(t.getRelaId()); + bo.setFrontShow(t.getFrontShow()); + bo.setQueryType(t.getQueryType().getCode()); + bo.setFormWidth(t.getFormWidth()); + bo.setDefaultValue(t.getDefaultValue()); + bo.setType(t.getType().getCode()); + bo.setDataType(entityDetail.getDataType().getCode()); + bo.setViewType(entityDetail.getViewType().getCode()); + + return bo; + }).collect(Collectors.toList()); + } + + GenCustomListDetailService genCustomListDetailService = ApplicationUtil.getBean( + GenCustomListDetailService.class); + List details = genCustomListDetailService.getByCustomListId(dto.getId()); + this.details = details.stream().map(t -> { + DetailBo bo = new DetailBo(); + bo.setId(t.getDataEntityId()); + bo.setRelaId(t.getRelaId()); + bo.setWidthType(t.getWidthType().getCode()); + bo.setSortable(t.getSortable()); + bo.setWidth(t.getWidth()); + bo.setType(t.getType().getCode()); + if (t.getType() == GenCustomListDetailType.CUSTOM) { + bo.setId(t.getRelaId()); + } + bo.setFormatter(t.getFormatter()); + + return bo; + }).collect(Collectors.toList()); + + GenCustomListToolbarService genCustomListToolbarService = ApplicationUtil + .getBean(GenCustomListToolbarService.class); + List toolbars = genCustomListToolbarService + .getByCustomListId(dto.getId()); + + this.toolbars = toolbars.stream().map(t -> { + ToolbarBo toolbar = new ToolbarBo(); + toolbar.setId(t.getId()); + toolbar.setName(t.getName()); + toolbar.setViewType(t.getViewType().getCode()); + toolbar.setBtnType(t.getBtnType().getCode()); + toolbar.setBtnConfig(t.getBtnConfig()); + toolbar.setIcon(t.getIcon()); + return toolbar; + }).collect(Collectors.toList()); + + GenCustomListHandleColumnService genCustomListHandleColumnService = ApplicationUtil + .getBean(GenCustomListHandleColumnService.class); + List handleColumns = genCustomListHandleColumnService + .getByCustomListId(dto.getId()); + + this.handleColumns = handleColumns.stream().map(t -> { + HandleColumnBo handleColumn = new HandleColumnBo(); + handleColumn.setId(t.getId()); + handleColumn.setName(t.getName()); + handleColumn.setViewType(t.getViewType().getCode()); + handleColumn.setBtnType(t.getBtnType().getCode()); + handleColumn.setBtnConfig(t.getBtnConfig()); + handleColumn.setWidth(t.getWidth()); + handleColumn.setIcon(t.getIcon()); + return handleColumn; + }).collect(Collectors.toList()); + } + + @Data + public static class ToolbarBo implements SuperBo { + + /** + * ID + */ + @ApiModelProperty(value = "ID") + private String id; + + /** + * 显示名称 + */ + @ApiModelProperty(value = "显示名称") + private String name; + + /** + * 显示类型 + */ + @ApiModelProperty(value = "显示类型") + private String viewType; + + /** + * 按钮类型 + */ + @ApiModelProperty(value = "按钮类型") + private Integer btnType; + + /** + * 按钮配置 + */ + @ApiModelProperty(value = "按钮配置") + private String btnConfig; + + /** + * 图标 + */ + @ApiModelProperty(value = "图标") + private String icon; + + /** + * 请求参数 + */ + @ApiModelProperty(value = "请求参数") + private String requestParam; + + /** + * 自定义表单ID + */ + @ApiModelProperty(value = "自定义表单ID") + private String customFormId; + + /** + * 自定义表单名称 + */ + @ApiModelProperty(value = "自定义表单名称") + private String customFormName; + } + + @Data + public static class QueryParamsBo implements SuperBo { + + /** + * ID + */ + @ApiModelProperty(value = "ID") + private String id; + + /** + * 关联ID + */ + @ApiModelProperty(value = "关联ID") + private String relaId; + + /** + * 前端显示 + */ + @ApiModelProperty(value = "前端显示") + private Boolean frontShow; + + /** + * 查询类型 + */ + @ApiModelProperty(value = "查询类型") + private Integer queryType; + + /** + * 表单宽度 + */ + @ApiModelProperty(value = "表单宽度") + private Integer formWidth; + + /** + * 默认值 + */ + @ApiModelProperty(value = "默认值") + private String defaultValue; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * 数据类型 + */ + @ApiModelProperty("数据对象") + private Integer dataType; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private Integer viewType; + } + + @Data + public static class DetailBo implements SuperBo { + + /** + * ID + */ + @ApiModelProperty(value = "ID") + private String id; + + /** + * 关联ID + */ + @ApiModelProperty("关联ID") + private String relaId; + + /** + * 宽度类型 + */ + @ApiModelProperty(value = "宽度类型") + private Integer widthType; + + /** + * 是否页面排序 + */ + @ApiModelProperty(value = "是否页面排序") + private Boolean sortable; + + /** + * 宽度 + */ + @ApiModelProperty(value = "宽度") + private Integer width; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型") + private Integer type; + + /** + * 格式化脚本 + */ + @ApiModelProperty("格式化脚本") + private String formatter; + } + + @Data + public static class HandleColumnBo implements SuperBo { + + /** + * ID + */ + @ApiModelProperty(value = "ID") + private String id; + + /** + * 显示名称 + */ + @ApiModelProperty(value = "显示名称") + private String name; + + /** + * 显示类型 + */ + @ApiModelProperty(value = "显示类型") + private String viewType; + + /** + * 按钮类型 + */ + @ApiModelProperty(value = "按钮类型") + private Integer btnType; + + /** + * 按钮配置 + */ + @ApiModelProperty(value = "按钮配置") + private String btnConfig; + + /** + * 图标 + */ + @ApiModelProperty(value = "图标") + private String icon; + + /** + * 请求参数 + */ + @ApiModelProperty(value = "请求参数") + private String requestParam; + + /** + * 宽度 + */ + @ApiModelProperty(value = "宽度") + private Integer width; + + /** + * 自定义表单ID + */ + @ApiModelProperty(value = "自定义表单ID") + private String customFormId; + + /** + * 自定义表单名称 + */ + @ApiModelProperty(value = "自定义表单名称") + private String customFormName; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/QueryGenCustomListBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/QueryGenCustomListBo.java new file mode 100644 index 0000000..6958e99 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/QueryGenCustomListBo.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.template.gen.bo.custom.list; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.service.GenCustomListCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryGenCustomListBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryGenCustomListBo() { + } + + public QueryGenCustomListBo(GenCustomList dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomList dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomListCategoryService genDataObjCategoryService = ApplicationUtil.getBean( + GenCustomListCategoryService.class); + GenCustomListCategory category = genDataObjCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GenCustomListCategorySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GenCustomListCategorySelectorBo.java new file mode 100644 index 0000000..a1ae71c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GenCustomListCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.bo.custom.list.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomListCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public GenCustomListCategorySelectorBo() { + } + + public GenCustomListCategorySelectorBo(GenCustomListCategory dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GetGenCustomListCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GetGenCustomListCategoryBo.java new file mode 100644 index 0000000..4483cc8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/GetGenCustomListCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.custom.list.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenCustomListCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public GetGenCustomListCategoryBo() { + + } + + public GetGenCustomListCategoryBo(GenCustomListCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/QueryGenCustomListCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/QueryGenCustomListCategoryBo.java new file mode 100644 index 0000000..8f2056b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/list/category/QueryGenCustomListCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.custom.list.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryGenCustomListCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public QueryGenCustomListCategoryBo() { + + } + + public QueryGenCustomListCategoryBo(GenCustomListCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GenCustomPageSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GenCustomPageSelectorBo.java new file mode 100644 index 0000000..a04cd61 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GenCustomPageSelectorBo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.gen.bo.custom.page; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.xingyun.template.gen.service.GenCustomPageCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomPageSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + public GenCustomPageSelectorBo() { + } + + public GenCustomPageSelectorBo(GenCustomPage dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomPage dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomPageCategoryService genCustomPageCategoryService = ApplicationUtil.getBean( + GenCustomPageCategoryService.class); + GenCustomPageCategory category = genCustomPageCategoryService + .findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GetGenCustomPageBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GetGenCustomPageBo.java new file mode 100644 index 0000000..eca5112 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/GetGenCustomPageBo.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.template.gen.bo.custom.page; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.xingyun.template.gen.service.GenCustomPageCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenCustomPageBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 页面代码 + */ + @ApiModelProperty("页面代码") + private String pageCode; + + /** + * 脚本代码 + */ + @ApiModelProperty("脚本代码") + private String scriptCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetGenCustomPageBo() { + } + + public GetGenCustomPageBo(GenCustomPage dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomPage dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomPageCategoryService genCustomPageCategoryService = ApplicationUtil.getBean( + GenCustomPageCategoryService.class); + GenCustomPageCategory category = genCustomPageCategoryService + .findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/QueryGenCustomPageBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/QueryGenCustomPageBo.java new file mode 100644 index 0000000..6c586d6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/QueryGenCustomPageBo.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.template.gen.bo.custom.page; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.xingyun.template.gen.service.GenCustomPageCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryGenCustomPageBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryGenCustomPageBo() { + } + + public QueryGenCustomPageBo(GenCustomPage dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomPage dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomPageCategoryService genCustomPageCategoryService = ApplicationUtil.getBean( + GenCustomPageCategoryService.class); + GenCustomPageCategory category = genCustomPageCategoryService + .findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GenCustomPageCategorySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GenCustomPageCategorySelectorBo.java new file mode 100644 index 0000000..9fd8647 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GenCustomPageCategorySelectorBo.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.gen.bo.custom.page.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomPageCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + public GenCustomPageCategorySelectorBo() { + } + + public GenCustomPageCategorySelectorBo(GenCustomPageCategory dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GetGenCustomPageCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GetGenCustomPageCategoryBo.java new file mode 100644 index 0000000..bdcee25 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/GetGenCustomPageCategoryBo.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.gen.bo.custom.page.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenCustomPageCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + + public GetGenCustomPageCategoryBo() { + + } + + public GetGenCustomPageCategoryBo(GenCustomPageCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/QueryGenCustomPageCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/QueryGenCustomPageCategoryBo.java new file mode 100644 index 0000000..9cf1b32 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/page/category/QueryGenCustomPageCategoryBo.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.gen.bo.custom.page.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryGenCustomPageCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + + public QueryGenCustomPageCategoryBo() { + + } + + public QueryGenCustomPageCategoryBo(GenCustomPageCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GenCustomSelectorSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GenCustomSelectorSelectorBo.java new file mode 100644 index 0000000..51530f9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GenCustomSelectorSelectorBo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.gen.bo.custom.selector; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomSelectorSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + public GenCustomSelectorSelectorBo() { + } + + public GenCustomSelectorSelectorBo(GenCustomSelector dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomSelector dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomSelectorCategoryService genCustomListCategoryService = ApplicationUtil.getBean( + GenCustomSelectorCategoryService.class); + GenCustomSelectorCategory category = genCustomListCategoryService + .findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GetGenCustomSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GetGenCustomSelectorBo.java new file mode 100644 index 0000000..6fa75ba --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/GetGenCustomSelectorBo.java @@ -0,0 +1,125 @@ +package com.lframework.xingyun.template.gen.bo.custom.selector; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenCustomSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 数据对象ID + */ + @ApiModelProperty("数据对象ID") + private String dataObjId; + + /** + * 自定义列表ID + */ + @ApiModelProperty("自定义列表ID") + private String customListId; + + /** + * 自定义列表名称 + */ + @ApiModelProperty("自定义列表名称") + private String customListName; + + /** + * 对话框标题 + */ + @ApiModelProperty("对话框标题") + private String dialogTittle; + + /** + * 对话框宽度 + */ + @ApiModelProperty("对话框宽度") + private String dialogWidth; + + /** + * 占位符 + */ + @ApiModelProperty("占位符") + private String placeholder; + + /** + * ID字段 + */ + @ApiModelProperty("ID字段") + private String idColumn; + + /** + * 名称字段 + */ + @ApiModelProperty("名称字段") + private String nameColumn; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetGenCustomSelectorBo() { + } + + public GetGenCustomSelectorBo(GenCustomSelector dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomSelector dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomSelectorCategoryService genCustomListCategoryService = ApplicationUtil.getBean( + GenCustomSelectorCategoryService.class); + GenCustomSelectorCategory category = genCustomListCategoryService + .findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + + GenCustomListService genCustomListService = ApplicationUtil + .getBean(GenCustomListService.class); + GenCustomList customList = genCustomListService.findById(dto.getCustomListId()); + this.customListName = customList.getName(); + + this.dataObjId = customList.getDataObjId(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/QueryGenCustomSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/QueryGenCustomSelectorBo.java new file mode 100644 index 0000000..0bc1dd0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/QueryGenCustomSelectorBo.java @@ -0,0 +1,98 @@ +package com.lframework.xingyun.template.gen.bo.custom.selector; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryGenCustomSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryGenCustomSelectorBo() { + } + + public QueryGenCustomSelectorBo(GenCustomSelector dto) { + super(dto); + } + + @Override + protected void afterInit(GenCustomSelector dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenCustomSelectorCategoryService customSelectorCategoryService = ApplicationUtil.getBean( + GenCustomSelectorCategoryService.class); + GenCustomSelectorCategory category = customSelectorCategoryService + .findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GenCustomSelectorCategorySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GenCustomSelectorCategorySelectorBo.java new file mode 100644 index 0000000..3388b13 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GenCustomSelectorCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.bo.custom.selector.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomSelectorCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public GenCustomSelectorCategorySelectorBo() { + } + + public GenCustomSelectorCategorySelectorBo(GenCustomSelectorCategory dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GetGenCustomSelectorCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GetGenCustomSelectorCategoryBo.java new file mode 100644 index 0000000..f6f303b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/GetGenCustomSelectorCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.custom.selector.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenCustomSelectorCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public GetGenCustomSelectorCategoryBo() { + + } + + public GetGenCustomSelectorCategoryBo(GenCustomSelectorCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/QueryGenCustomSelectorCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/QueryGenCustomSelectorCategoryBo.java new file mode 100644 index 0000000..17f0a54 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/custom/selector/category/QueryGenCustomSelectorCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.custom.selector.category; + +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryGenCustomSelectorCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public QueryGenCustomSelectorCategoryBo() { + + } + + public QueryGenCustomSelectorCategoryBo(GenCustomSelectorCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/DataEntityGenerateBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/DataEntityGenerateBo.java new file mode 100644 index 0000000..2c13b7d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/DataEntityGenerateBo.java @@ -0,0 +1,114 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.lframework.starter.common.functions.SFunction; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.bo.gen.GenCreateColumnConfigBo; +import com.lframework.xingyun.template.gen.bo.gen.GenDetailColumnConfigBo; +import com.lframework.xingyun.template.gen.bo.gen.GenGenerateInfoBo; +import com.lframework.xingyun.template.gen.bo.gen.GenQueryColumnConfigBo; +import com.lframework.xingyun.template.gen.bo.gen.GenQueryParamsColumnConfigBo; +import com.lframework.xingyun.template.gen.bo.gen.GenUpdateColumnConfigBo; +import com.lframework.xingyun.template.gen.dto.data.entity.DataEntityGenerateDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class DataEntityGenerateBo extends BaseBo { + + /** + * 字段信息 + */ + @ApiModelProperty("字段信息") + private List columns; + + /** + * 基本设置 + */ + @ApiModelProperty("基本设置") + private GenGenerateInfoBo generateInfo; + + /** + * 新增配置 + */ + @ApiModelProperty("新增配置") + private List createConfigs; + + /** + * 修改配置 + */ + @ApiModelProperty("修改配置") + private List updateConfigs; + + /** + * 查询配置 + */ + @ApiModelProperty("查询配置") + private List queryConfigs; + + /** + * 查询参数配置 + */ + @ApiModelProperty("查询参数配置") + private List queryParamsConfigs; + + /** + * 详情配置 + */ + @ApiModelProperty("详情配置") + private List detailConfigs; + + public DataEntityGenerateBo(DataEntityGenerateDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(DataEntityGenerateDto dto) { + + return this; + } + + @Override + public BaseBo convert(DataEntityGenerateDto dto, + SFunction... columns) { + + return this; + } + + @Override + protected void afterInit(DataEntityGenerateDto dto) { + + this.columns = dto.getColumns().stream().map(GenDataEntityDetailGenerateBo::new) + .collect(Collectors.toList()); + this.generateInfo = + dto.getGenerateInfo() == null ? null : new GenGenerateInfoBo(dto.getGenerateInfo()); + if (!CollectionUtil.isEmpty(dto.getCreateConfigs())) { + this.createConfigs = dto.getCreateConfigs().stream().map(GenCreateColumnConfigBo::new) + .collect(Collectors.toList()); + } + + if (!CollectionUtil.isEmpty(dto.getUpdateConfigs())) { + this.updateConfigs = dto.getUpdateConfigs().stream().map(GenUpdateColumnConfigBo::new) + .collect(Collectors.toList()); + } + + if (!CollectionUtil.isEmpty(dto.getQueryConfigs())) { + this.queryConfigs = dto.getQueryConfigs().stream().map(GenQueryColumnConfigBo::new) + .collect(Collectors.toList()); + } + + if (!CollectionUtil.isEmpty(dto.getQueryParamsConfigs())) { + this.queryParamsConfigs = dto.getQueryParamsConfigs().stream() + .map(GenQueryParamsColumnConfigBo::new) + .collect(Collectors.toList()); + } + + if (!CollectionUtil.isEmpty(dto.getDetailConfigs())) { + this.detailConfigs = dto.getDetailConfigs().stream().map(GenDetailColumnConfigBo::new) + .collect(Collectors.toList()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailBo.java new file mode 100644 index 0000000..023915b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailBo.java @@ -0,0 +1,169 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntityDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 字段显示名称 + */ + @ApiModelProperty("字段显示名称") + private String name; + + /** + * 字段名称 + */ + @ApiModelProperty("字段名称") + private String columnName; + + /** + * 是否主键 + */ + @ApiModelProperty("是否主键") + private Boolean isKey; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer dataType; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer columnOrder; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private Integer viewType; + + /** + * 是否内置枚举 + */ + @ApiModelProperty("是否内置枚举") + private Boolean fixEnum; + + /** + * 后端枚举名 + */ + @ApiModelProperty("后端枚举名") + private String enumBack; + + /** + * 前端枚举名 + */ + @ApiModelProperty("前端枚举名") + private String enumFront; + + /** + * 正则表达式 + */ + @ApiModelProperty("正则表达式") + private String regularExpression; + + /** + * 是否排序字段 + */ + @ApiModelProperty("是否排序字段") + private Boolean isOrder; + + /** + * 排序类型 + */ + @ApiModelProperty("排序类型") + private String orderType; + + /** + * 数据字典ID + */ + private String dataDicId; + + /** + * 数据字典名称 + */ + private String dataDicName; + + /** + * 自定义选择器ID + */ + private String customSelectorId; + + /** + * 自定义选择器名称 + */ + private String customSelectorName; + + /** + * 长度 + */ + @ApiModelProperty("长度") + private Long len; + + /** + * 小数位数 + */ + @ApiModelProperty("小数位数") + private Integer decimals; + + public GenDataEntityDetailBo() { + + } + + public GenDataEntityDetailBo(GenDataEntityDetail dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenDataEntityDetail dto) { + + return super.convert(dto, GenDataEntityDetailBo::getDataType, + GenDataEntityDetailBo::getViewType, GenDataEntityDetailBo::getOrderType); + } + + @Override + protected void afterInit(GenDataEntityDetail dto) { + + this.dataType = dto.getDataType().getCode(); + this.viewType = dto.getViewType().getCode(); + this.orderType = dto.getOrderType() == null ? null : dto.getOrderType().getCode(); + + if (!StringUtil.isBlank(dto.getDataDicId())) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(dto.getDataDicId()); + this.dataDicName = dic.getName(); + } + + if (!StringUtil.isBlank(dto.getCustomSelectorId())) { + GenCustomSelectorService genCustomSelectorService = ApplicationUtil + .getBean(GenCustomSelectorService.class); + GenCustomSelector selector = genCustomSelectorService.findById(dto.getCustomSelectorId()); + this.customSelectorName = selector.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailGenerateBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailGenerateBo.java new file mode 100644 index 0000000..1206a1d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailGenerateBo.java @@ -0,0 +1,119 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntityDetailGenerateBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 字段显示名称 + */ + @ApiModelProperty("字段显示名称") + private String name; + + /** + * 字段名称 + */ + @ApiModelProperty("字段名称") + private String columnName; + + /** + * 是否主键 + */ + @ApiModelProperty("是否主键") + private Boolean isKey; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer dataType; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer columnOrder; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private Integer viewType; + + /** + * 是否内置枚举 + */ + @ApiModelProperty("是否内置枚举") + private Boolean fixEnum; + + /** + * 后端枚举名 + */ + @ApiModelProperty("后端枚举名") + private String enumBack; + + /** + * 前端枚举名 + */ + @ApiModelProperty("前端枚举名") + private String enumFront; + + /** + * 正则表达式 + */ + @ApiModelProperty("正则表达式") + private String regularExpression; + + /** + * 是否排序字段 + */ + @ApiModelProperty("是否排序字段") + private Boolean isOrder; + + /** + * 排序类型 + */ + @ApiModelProperty("排序类型") + private String orderType; + + public GenDataEntityDetailGenerateBo() { + + } + + public GenDataEntityDetailGenerateBo(GenDataEntityDetail dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenDataEntityDetail dto) { + + return super.convert(dto, GenDataEntityDetailGenerateBo::getDataType, + GenDataEntityDetailGenerateBo::getViewType, + GenDataEntityDetailGenerateBo::getOrderType); + } + + @Override + protected void afterInit(GenDataEntityDetail dto) { + + this.dataType = dto.getDataType().getCode(); + this.viewType = dto.getViewType().getCode(); + this.orderType = dto.getOrderType() == null ? null : dto.getOrderType().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailSelectorBo.java new file mode 100644 index 0000000..664ba46 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntityDetailSelectorBo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntityDetailSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public GenDataEntityDetailSelectorBo() { + } + + public GenDataEntityDetailSelectorBo(GenDataEntityDetail dto) { + super(dto); + } + + @Override + protected void afterInit(GenDataEntityDetail dto) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntitySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntitySelectorBo.java new file mode 100644 index 0000000..c86a2b5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GenDataEntitySelectorBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.service.GenDataEntityCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntitySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + public GenDataEntitySelectorBo() { + } + + public GenDataEntitySelectorBo(GenDataEntity dto) { + super(dto); + } + + @Override + protected void afterInit(GenDataEntity dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenDataEntityCategoryService genDataEntityCategoryService = ApplicationUtil.getBean( + GenDataEntityCategoryService.class); + GenDataEntityCategory category = genDataEntityCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GetDataEntityBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GetDataEntityBo.java new file mode 100644 index 0000000..0bb34a8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/GetDataEntityBo.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.service.GenDataEntityCategoryService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetDataEntityBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 数据表 + */ + @ApiModelProperty("数据表") + private String tableName; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 字段信息 + */ + @ApiModelProperty("字段信息") + private List columns; + + public GetDataEntityBo() { + + } + + public GetDataEntityBo(GenDataEntity dto) { + + super(dto); + } + + @Override + protected void afterInit(GenDataEntity dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenDataEntityCategoryService genDataEntityCategoryService = ApplicationUtil.getBean( + GenDataEntityCategoryService.class); + GenDataEntityCategory category = genDataEntityCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + + this.tableName = dto.getTableName(); + + GenDataEntityDetailService genDataEntityDetailService = ApplicationUtil.getBean( + GenDataEntityDetailService.class); + List details = genDataEntityDetailService.getByEntityId(dto.getId()); + this.columns = details.stream().map(GenDataEntityDetailBo::new).collect(Collectors.toList()); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/QueryDataEntityBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/QueryDataEntityBo.java new file mode 100644 index 0000000..dced7f6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/QueryDataEntityBo.java @@ -0,0 +1,104 @@ +package com.lframework.xingyun.template.gen.bo.data.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.service.GenDataEntityCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryDataEntityBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 生成状态 + */ + @ApiModelProperty("生成状态") + private Integer genStatus; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryDataEntityBo() { + } + + public QueryDataEntityBo(GenDataEntity dto) { + super(dto); + } + + @Override + protected void afterInit(GenDataEntity dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenDataEntityCategoryService genDataEntityCategoryService = ApplicationUtil.getBean( + GenDataEntityCategoryService.class); + GenDataEntityCategory category = genDataEntityCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + this.genStatus = dto.getGenStatus().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GenDataEntityCategorySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GenDataEntityCategorySelectorBo.java new file mode 100644 index 0000000..081db45 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GenDataEntityCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.bo.data.entity.category; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntityCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public GenDataEntityCategorySelectorBo() { + } + + public GenDataEntityCategorySelectorBo(GenDataEntityCategory dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GetGenDataEntityCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GetGenDataEntityCategoryBo.java new file mode 100644 index 0000000..aa00336 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/GetGenDataEntityCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.data.entity.category; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenDataEntityCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public GetGenDataEntityCategoryBo() { + + } + + public GetGenDataEntityCategoryBo(GenDataEntityCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/QueryGenDataEntityCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/QueryGenDataEntityCategoryBo.java new file mode 100644 index 0000000..7aaa0f0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/entity/category/QueryGenDataEntityCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.data.entity.category; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryGenDataEntityCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public QueryGenDataEntityCategoryBo() { + + } + + public QueryGenDataEntityCategoryBo(GenDataEntityCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjColumnBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjColumnBo.java new file mode 100644 index 0000000..f18b02d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjColumnBo.java @@ -0,0 +1,68 @@ +package com.lframework.xingyun.template.gen.bo.data.obj; + +import com.lframework.starter.web.bo.SuperBo; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; + +@Data +public class GenDataObjColumnBo implements SuperBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 数据对象名称 + */ + @ApiModelProperty("数据对象名称") + private String name; + + /** + * 列 + */ + @ApiModelProperty("列") + private List columns; + + @Data + public static class ColumnBo implements SuperBo { + + /** + * 数据实体明细ID + */ + @ApiModelProperty("数据实体明细ID") + private String id; + + /** + * 关联ID + */ + @ApiModelProperty("关联ID") + private String relaId; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + private String name; + + /** + * 类型 + */ + @ApiModelProperty("类型") + private Integer type; + + /** + * 数据类型 + */ + @ApiModelProperty("数据对象") + private Integer dataType; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private Integer viewType; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjDetailBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjDetailBo.java new file mode 100644 index 0000000..537cfe6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjDetailBo.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.template.gen.bo.data.obj; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataObjDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 主表字段 + */ + @ApiModelProperty("主表字段") + private String[] mainTableDetailIds; + + /** + * 关联类型 + */ + @ApiModelProperty("关联类型") + private Integer relaType; + + /** + * 关联方式 + */ + @ApiModelProperty("关联方式") + private Integer relaMode; + + /** + * 子表ID + */ + @ApiModelProperty("子表ID") + private String subTableId; + + /** + * 子表名称 + */ + @ApiModelProperty("子表名称") + private String subTableName; + + /** + * 子表别名 + */ + @ApiModelProperty("子表别名") + private String subTableAlias; + + /** + * 子表字段 + */ + @ApiModelProperty("子表字段") + private String[] subTableDetailIds; + + public GenDataObjDetailBo() { + + } + + public GenDataObjDetailBo(GenDataObjDetail dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenDataObjDetail dto) { + + return super.convert(dto, GenDataObjDetailBo::getRelaType, GenDataObjDetailBo::getRelaMode, + GenDataObjDetailBo::getMainTableDetailIds, GenDataObjDetailBo::getSubTableDetailIds); + } + + @Override + protected void afterInit(GenDataObjDetail dto) { + + this.relaType = dto.getRelaType().getCode(); + this.relaMode = dto.getRelaMode().getCode(); + this.mainTableDetailIds = dto.getMainTableDetailIds().split(StringPool.STR_SPLIT); + this.subTableDetailIds = dto.getSubTableDetailIds().split(StringPool.STR_SPLIT); + + GenDataEntityService genDataEntityService = ApplicationUtil.getBean( + GenDataEntityService.class); + GenDataEntity entity = genDataEntityService.findById(dto.getSubTableId()); + this.subTableName = entity.getName(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjQueryDetailBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjQueryDetailBo.java new file mode 100644 index 0000000..e000eee --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjQueryDetailBo.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.template.gen.bo.data.obj; + +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataObjQueryDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + private String customName; + + /** + * 自定义SQL + */ + @ApiModelProperty("自定义SQL") + private String customSql; + + /** + * 别名 + */ + @ApiModelProperty("别名") + private String customAlias; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer dataType; + + public GenDataObjQueryDetailBo() { + + } + + public GenDataObjQueryDetailBo(GenDataObjQueryDetail dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenDataObjQueryDetail dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(GenDataObjQueryDetail dto) { + this.dataType = dto.getDataType().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjSelectorBo.java new file mode 100644 index 0000000..1a5ea2f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GenDataObjSelectorBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.bo.data.obj; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.service.GenDataObjCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataObjSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + public GenDataObjSelectorBo() { + } + + public GenDataObjSelectorBo(GenDataObj dto) { + super(dto); + } + + @Override + protected void afterInit(GenDataObj dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenDataObjCategoryService genDataObjCategoryService = ApplicationUtil.getBean( + GenDataObjCategoryService.class); + GenDataObjCategory category = genDataObjCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GetGenDataObjBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GetGenDataObjBo.java new file mode 100644 index 0000000..52989ca --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/GetGenDataObjBo.java @@ -0,0 +1,131 @@ +package com.lframework.xingyun.template.gen.bo.data.obj; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDataObjCategoryService; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjQueryDetailService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetGenDataObjBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 主表ID + */ + @ApiModelProperty("主表ID") + private String mainTableId; + + /** + * 主表名称 + */ + @ApiModelProperty("主表名称") + private String mainTableName; + + /** + * 主表别名 + */ + @ApiModelProperty("主表别名") + private String mainTableAlias; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 关联字段 + */ + @ApiModelProperty("关联字段") + private List columns; + + /** + * 自定义查询 + */ + @ApiModelProperty("自定义查询") + private List queryColumns; + + public GetGenDataObjBo() { + + } + + public GetGenDataObjBo(GenDataObj dto) { + + super(dto); + } + + @Override + protected void afterInit(GenDataObj dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenDataObjCategoryService genDataObjCategoryService = ApplicationUtil.getBean( + GenDataObjCategoryService.class); + GenDataObjCategory category = genDataObjCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + + GenDataEntityService genDataEntityService = ApplicationUtil.getBean( + GenDataEntityService.class); + GenDataEntity entity = genDataEntityService.findById(dto.getMainTableId()); + this.mainTableName = entity.getName(); + + GenDataObjDetailService genDataObjDetailService = ApplicationUtil.getBean( + GenDataObjDetailService.class); + List details = genDataObjDetailService.getByObjId(dto.getId()); + if (!CollectionUtil.isEmpty(details)) { + this.columns = details.stream().map(GenDataObjDetailBo::new).collect(Collectors.toList()); + } + + GenDataObjQueryDetailService genDataObjQueryDetailService = ApplicationUtil.getBean( + GenDataObjQueryDetailService.class); + List queryDetails = genDataObjQueryDetailService.getByObjId(dto.getId()); + if (!CollectionUtil.isEmpty(queryDetails)) { + this.queryColumns = queryDetails.stream().map(GenDataObjQueryDetailBo::new) + .collect(Collectors.toList()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/QueryGenDataObjBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/QueryGenDataObjBo.java new file mode 100644 index 0000000..dd995c0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/QueryGenDataObjBo.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.template.gen.bo.data.obj; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.service.GenDataObjCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryGenDataObjBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人ID + */ + @ApiModelProperty("创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人ID + */ + @ApiModelProperty("修改人ID") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QueryGenDataObjBo() { + } + + public QueryGenDataObjBo(GenDataObj dto) { + super(dto); + } + + @Override + protected void afterInit(GenDataObj dto) { + + if (!StringUtil.isBlank(dto.getCategoryId())) { + GenDataObjCategoryService genDataObjCategoryService = ApplicationUtil.getBean( + GenDataObjCategoryService.class); + GenDataObjCategory category = genDataObjCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GenDataObjCategorySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GenDataObjCategorySelectorBo.java new file mode 100644 index 0000000..5d1e6a6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GenDataObjCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.bo.data.obj.category; + +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataObjCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public GenDataObjCategorySelectorBo() { + } + + public GenDataObjCategorySelectorBo(GenDataObjCategory dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GetGenDataObjCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GetGenDataObjCategoryBo.java new file mode 100644 index 0000000..fa1db89 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/GetGenDataObjCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.data.obj.category; + +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetGenDataObjCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public GetGenDataObjCategoryBo() { + + } + + public GetGenDataObjCategoryBo(GenDataObjCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/QueryGenDataObjCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/QueryGenDataObjCategoryBo.java new file mode 100644 index 0000000..98583de --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/data/obj/category/QueryGenDataObjCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.bo.data.obj.category; + +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryGenDataObjCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public QueryGenDataObjCategoryBo() { + + } + + public QueryGenDataObjCategoryBo(GenDataObjCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenCreateColumnConfigBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenCreateColumnConfigBo.java new file mode 100644 index 0000000..194cda5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenCreateColumnConfigBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.bo.gen; + +import com.lframework.xingyun.template.gen.dto.gen.GenCreateColumnConfigDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCreateColumnConfigBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 是否必填 + */ + @ApiModelProperty("是否必填") + private Boolean required; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer orderNo; + + public GenCreateColumnConfigBo() { + + } + + public GenCreateColumnConfigBo(GenCreateColumnConfigDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenCreateColumnConfigDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(GenCreateColumnConfigDto dto) { + + super.afterInit(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenDetailColumnConfigBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenDetailColumnConfigBo.java new file mode 100644 index 0000000..3ac614d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenDetailColumnConfigBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.bo.gen; + +import com.lframework.xingyun.template.gen.dto.gen.GenDetailColumnConfigDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDetailColumnConfigBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 列宽 + */ + @ApiModelProperty("列宽") + private Integer span; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer orderNo; + + public GenDetailColumnConfigBo() { + + } + + public GenDetailColumnConfigBo(GenDetailColumnConfigDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenDetailColumnConfigDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(GenDetailColumnConfigDto dto) { + + super.afterInit(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenGenerateInfoBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenGenerateInfoBo.java new file mode 100644 index 0000000..d0efaa2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenGenerateInfoBo.java @@ -0,0 +1,121 @@ +package com.lframework.xingyun.template.gen.bo.gen; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import lombok.Data; + +@Data +public class GenGenerateInfoBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 生成模板类型 + */ + private Integer templateType; + + /** + * 包名 + */ + private String packageName; + + /** + * 模块名 + */ + private String moduleName; + + /** + * 业务名 + */ + private String bizName; + + /** + * 类名 + */ + private String className; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 父级菜单ID + */ + private String parentMenuId; + + /** + * 父级菜单名称 + */ + private String parentMenuName; + + /** + * 主键类型 + */ + private Integer keyType; + + /** + * 作者 + */ + private String author; + + /** + * 本级菜单编号 + */ + private String menuCode; + + /** + * 本级菜单名称 + */ + private String menuName; + + /** + * 详情页Span总数量 + */ + private Integer detailSpan; + + /** + * 是否应用缓存 + */ + private Boolean isCache; + + /** + * 是否内置删除功能 + */ + private Boolean hasDelete; + + public GenGenerateInfoBo() { + + } + + public GenGenerateInfoBo(GenGenerateInfoDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenGenerateInfoDto dto) { + + return super.convert(dto, GenGenerateInfoBo::getTemplateType, GenGenerateInfoBo::getKeyType); + } + + @Override + protected void afterInit(GenGenerateInfoDto dto) { + + this.templateType = dto.getTemplateType().getCode(); + this.keyType = dto.getKeyType().getCode(); + + if (!StringUtil.isBlank(dto.getParentMenuId())) { + SysMenuService sysMenuService = ApplicationUtil.getBean(SysMenuService.class); + this.parentMenuName = sysMenuService.findById(dto.getParentMenuId()).getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryColumnConfigBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryColumnConfigBo.java new file mode 100644 index 0000000..db1a9cd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryColumnConfigBo.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.template.gen.bo.gen; + +import com.lframework.xingyun.template.gen.dto.gen.GenQueryColumnConfigDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenQueryColumnConfigBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 宽度类型 + */ + @ApiModelProperty("宽度类型") + private Integer widthType; + + /** + * 宽度 + */ + @ApiModelProperty("宽度") + private Integer width; + + /** + * 是否页面排序 + */ + @ApiModelProperty("是否页面排序") + private Boolean sortable; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer orderNo; + + public GenQueryColumnConfigBo() { + + } + + public GenQueryColumnConfigBo(GenQueryColumnConfigDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenQueryColumnConfigDto dto) { + + return super.convert(dto, GenQueryColumnConfigBo::getWidthType); + } + + @Override + protected void afterInit(GenQueryColumnConfigDto dto) { + + this.widthType = dto.getWidthType().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryParamsColumnConfigBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryParamsColumnConfigBo.java new file mode 100644 index 0000000..c117f8f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenQueryParamsColumnConfigBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.bo.gen; + +import com.lframework.xingyun.template.gen.dto.gen.GenQueryParamsColumnConfigDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenQueryParamsColumnConfigBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 查询类型 + */ + @ApiModelProperty("查询类型") + private Integer queryType; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer orderNo; + + public GenQueryParamsColumnConfigBo() { + + } + + public GenQueryParamsColumnConfigBo(GenQueryParamsColumnConfigDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenQueryParamsColumnConfigDto dto) { + + return super.convert(dto, GenQueryParamsColumnConfigBo::getQueryType); + } + + @Override + protected void afterInit(GenQueryParamsColumnConfigDto dto) { + + this.queryType = dto.getQueryType().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenUpdateColumnConfigBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenUpdateColumnConfigBo.java new file mode 100644 index 0000000..579c917 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/gen/GenUpdateColumnConfigBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.bo.gen; + +import com.lframework.xingyun.template.gen.dto.gen.GenUpdateColumnConfigDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenUpdateColumnConfigBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 是否必填 + */ + @ApiModelProperty("是否必填") + private Boolean required; + + /** + * 排序编号 + */ + @ApiModelProperty("排序编号") + private Integer orderNo; + + public GenUpdateColumnConfigBo() { + + } + + public GenUpdateColumnConfigBo(GenUpdateColumnConfigDto dto) { + + super(dto); + } + + @Override + public BaseBo convert(GenUpdateColumnConfigDto dto) { + + return super.convert(dto); + } + + @Override + protected void afterInit(GenUpdateColumnConfigDto dto) { + + super.afterInit(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/simpledb/SimpleDBSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/simpledb/SimpleDBSelectorBo.java new file mode 100644 index 0000000..2f6be82 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/bo/simpledb/SimpleDBSelectorBo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.bo.simpledb; + +import com.lframework.xingyun.template.gen.dto.simpledb.SimpleDBDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SimpleDBSelectorBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * 库名 + */ + @ApiModelProperty("库名") + private String tableSchema; + + /** + * 表名 + */ + @ApiModelProperty("表名") + private String tableName; + + public SimpleDBSelectorBo() { + + } + + public SimpleDBSelectorBo(SimpleDBDto dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomListBuilder.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomListBuilder.java new file mode 100644 index 0000000..4621fc5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomListBuilder.java @@ -0,0 +1,370 @@ +package com.lframework.xingyun.template.gen.builders; + +import cn.hutool.core.convert.Convert; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig.FieldConfig; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig.HandleColumn; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig.ListConfig; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig.QueryParam; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig.Toolbar; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryObj; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryParamObj; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.xingyun.template.gen.entity.GenCustomListHandleColumn; +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.xingyun.template.gen.entity.GenCustomListToolbar; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import com.lframework.xingyun.template.gen.service.GenCustomListDetailService; +import com.lframework.xingyun.template.gen.service.GenCustomListHandleColumnService; +import com.lframework.xingyun.template.gen.service.GenCustomListQueryParamsService; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.service.GenCustomListToolbarService; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjQueryDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +@Component +public class CustomListBuilder { + + @Autowired + private GenCustomListService genCustomListService; + + @Autowired + private GenCustomListDetailService genCustomListDetailService; + + @Autowired + private GenCustomListQueryParamsService genCustomListQueryParamsService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Autowired + private GenDataObjService genDataObjService; + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Autowired + private GenDataObjQueryDetailService genDataObjQueryDetailService; + + @Autowired + private DataObjectBuilder dataObjectBuilder; + + @Autowired + private GenCustomListToolbarService genCustomListToolbarService; + + @Autowired + private GenCustomListHandleColumnService genCustomListHandleColumnService; + + public DataObjectQueryObj buildQueryObj(String id, DataObjectQueryParamObj queryParamObj) { + GenCustomList customList = genCustomListService.findById(id); + if (customList == null) { + throw new DefaultClientException("自定义列表不存在!"); + } + + CustomListBuilder customListBuilder = ApplicationUtil.getBean(CustomListBuilder.class); + CustomListConfig config = customListBuilder.buildConfig(id); + + DataObjectQueryObj obj = dataObjectBuilder.buildQueryObj(customList.getDataObjId()); + obj.setQueryParamObj(this.buildQueryParamObj(queryParamObj, config)); + obj.setSuffixSql(customList.getSuffixSql()); + obj.setQueryPrefixSql(customList.getQueryPrefixSql()); + obj.setQuerySuffixSql(customList.getQuerySuffixSql()); + + return obj; + } + + @Cacheable(value = CustomListConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + public CustomListConfig buildConfig(String id) { + + // 先查询配置信息 + GenCustomList data = genCustomListService.findById(id); + + if (data == null) { + throw new DefaultClientException("自定义列表不存在!"); + } + + CustomListConfig result = new CustomListConfig(); + + List toolbars = genCustomListToolbarService + .getByCustomListId(data.getId()); + if (!CollectionUtil.isEmpty(toolbars)) { + result.setToolbars(toolbars.stream().map(t -> { + Toolbar toolbar = new Toolbar(); + toolbar.setId(t.getId()); + toolbar.setName(t.getName()); + toolbar.setViewType(t.getViewType().getCode()); + toolbar.setBtnType(t.getBtnType().getCode()); + toolbar.setBtnConfig(t.getBtnConfig()); + toolbar.setRequestParam(t.getRequestParam()); + toolbar.setIcon(t.getIcon()); + + return toolbar; + }).collect(Collectors.toList())); + } + + List handleColumns = genCustomListHandleColumnService + .getByCustomListId(data.getId()); + if (!CollectionUtil.isEmpty(handleColumns)) { + result.setHandleColumns(handleColumns.stream().map(t -> { + HandleColumn handleColumn = new HandleColumn(); + handleColumn.setId(t.getId()); + handleColumn.setName(t.getName()); + handleColumn.setViewType(t.getViewType().getCode()); + handleColumn.setBtnType(t.getBtnType().getCode()); + handleColumn.setBtnConfig(t.getBtnConfig()); + handleColumn.setRequestParam(t.getRequestParam()); + handleColumn.setIcon(t.getIcon()); + handleColumn.setWidth(t.getWidth()); + + return handleColumn; + }).collect(Collectors.toList())); + } + + List genCustomListQueryParamsList = genCustomListQueryParamsService + .getByCustomListId( + data.getId()); + List genCustomListDetailList = genCustomListDetailService + .getByCustomListId( + data.getId()); + + List queryParams = new ArrayList<>(); + + if (CollectionUtil.isNotEmpty(genCustomListQueryParamsList)) { + for (GenCustomListQueryParams genCustomListQueryParams : genCustomListQueryParamsList) { + GenDataEntityDetail entityDetail = genDataEntityDetailService.getById( + genCustomListQueryParams.getDataEntityId()); + + String relaId = genCustomListQueryParams.getRelaId(); + GenDataObj dataObj = null; + GenDataObjDetail dataObjDetail = null; + if (genCustomListQueryParams.getType() == GenCustomListDetailType.MAIN_TABLE) { + dataObj = genDataObjService.findById(relaId); + } else if (genCustomListQueryParams.getType() == GenCustomListDetailType.SUB_TALBE) { + dataObjDetail = genDataObjDetailService.getById(relaId); + } else { + throw new DefaultSysException("不支持的类型!"); + } + + QueryParam queryParam = new QueryParam(); + queryParam.setTableAlias( + genCustomListQueryParams.getType() == GenCustomListDetailType.SUB_TALBE + ? dataObjDetail.getSubTableAlias() : dataObj.getMainTableAlias()); + queryParam.setColumnName(entityDetail.getDbColumnName()); + queryParam.setName(entityDetail.getName()); + queryParam.setFrontShow(genCustomListQueryParams.getFrontShow()); + queryParam.setQueryType(genCustomListQueryParams.getQueryType().getCode()); + queryParam.setFormWidth(genCustomListQueryParams.getFormWidth()); + queryParam.setViewType(entityDetail.getViewType().getCode()); + queryParam.setDataType(entityDetail.getDataType().getCode()); + queryParam.setFixEnum(entityDetail.getFixEnum()); + queryParam.setFrontType(entityDetail.getEnumFront()); + if (StringUtil.isNotEmpty(genCustomListQueryParams.getDefaultValue())) { + queryParam.setDefaultValue(Convert.convert( + entityDetail.getViewType() == GenViewType.DATE_RANGE ? String.class + : entityDetail.getDataType().getClazz(), + genCustomListQueryParams.getDefaultValue())); + } + queryParam.setHasAvailableTag( + entityDetail.getViewType() == GenViewType.SELECT + && entityDetail.getDataType() == GenDataType.BOOLEAN + && "available".equals(entityDetail.getColumnName())); + + if (entityDetail.getViewType() == GenViewType.DATA_DIC) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(entityDetail.getDataDicId()); + queryParam.setDataDicCode(dic.getCode()); + } else if (entityDetail.getViewType() == GenViewType.CUSTOM_SELECTOR) { + GenCustomSelectorService genCustomSelectorService = ApplicationUtil + .getBean(GenCustomSelectorService.class); + GenCustomSelector selector = genCustomSelectorService + .findById(entityDetail.getCustomSelectorId()); + queryParam.setCustomSelectorId(selector.getId()); + } + + queryParams.add(queryParam); + } + } + + result.setQueryParams(queryParams); + + ListConfig listConfig = new ListConfig(); + listConfig.setId(data.getId()); + listConfig.setListType(data.getListType().getCode()); + listConfig.setLabelWidth(data.getLabelWidth()); + listConfig.setHasPage(data.getHasPage()); + listConfig.setTreeData(data.getTreeData()); + GenDataEntityDetail idColumnEntityDetail = genDataEntityDetailService + .getById(data.getIdColumn()); + GenDataObj idColumnDataObj = genDataObjService.findById(data.getIdColumnRelaId()); + GenDataObjDetail idColumnDataObjDetail = genDataObjDetailService + .getById(data.getIdColumnRelaId()); + + listConfig.setIdColumn( + (idColumnDataObj == null ? idColumnDataObjDetail.getSubTableAlias() + : idColumnDataObj.getMainTableAlias()) + "_" + + idColumnEntityDetail.getDbColumnName()); + listConfig.setAllowExport(data.getAllowExport()); + + if (data.getTreeData()) { + GenDataEntityDetail entityDetail = genDataEntityDetailService + .getById(data.getTreePidColumn()); + GenDataObj dataObj = genDataObjService.findById(data.getTreePidColumnRelaId()); + GenDataObjDetail dataObjDetail = genDataObjDetailService + .getById(data.getTreePidColumnRelaId()); + + listConfig.setTreePidColumn( + (dataObj == null ? dataObjDetail.getSubTableAlias() : dataObj.getMainTableAlias()) + "_" + + entityDetail.getDbColumnName()); + + entityDetail = genDataEntityDetailService.getById(data.getTreeNodeColumn()); + dataObj = genDataObjService.findById(data.getTreeNodeColumnRelaId()); + dataObjDetail = genDataObjDetailService + .getById(data.getTreeNodeColumnRelaId()); + + listConfig.setTreeNodeColumn( + (dataObj == null ? dataObjDetail.getSubTableAlias() : dataObj.getMainTableAlias()) + "_" + + entityDetail.getDbColumnName()); + + listConfig.setTreeChildrenKey(data.getTreeChildrenKey()); + } + + List fieldConfigs = new ArrayList<>(); + if (CollectionUtil.isNotEmpty(genCustomListDetailList)) { + for (GenCustomListDetail genCustomListDetail : genCustomListDetailList) { + String relaId = genCustomListDetail.getRelaId(); + GenDataEntityDetail entityDetail = null; + GenDataObjQueryDetail dataObjQueryDetail = null; + + GenDataObj dataObj = null; + GenDataObjDetail dataObjDetail = null; + if (genCustomListDetail.getType() == GenCustomListDetailType.MAIN_TABLE) { + entityDetail = genDataEntityDetailService.getById(genCustomListDetail.getDataEntityId()); + dataObj = genDataObjService.findById(relaId); + } else if (genCustomListDetail.getType() == GenCustomListDetailType.SUB_TALBE) { + entityDetail = genDataEntityDetailService.getById(genCustomListDetail.getDataEntityId()); + dataObjDetail = genDataObjDetailService.getById(relaId); + } else { + dataObjQueryDetail = genDataObjQueryDetailService.getById( + genCustomListDetail.getRelaId()); + } + FieldConfig fieldConfig = new FieldConfig(); + fieldConfig.setName((genCustomListDetail.getType() == GenCustomListDetailType.MAIN_TABLE + || genCustomListDetail.getType() == GenCustomListDetailType.SUB_TALBE) + ? entityDetail.getName() : dataObjQueryDetail.getCustomName()); + + if (genCustomListDetail.getType() == GenCustomListDetailType.MAIN_TABLE) { + fieldConfig.setColumnName( + dataObj.getMainTableAlias() + "_" + entityDetail.getDbColumnName()); + } else if (genCustomListDetail.getType() == GenCustomListDetailType.SUB_TALBE) { + fieldConfig.setColumnName( + dataObjDetail.getSubTableAlias() + "_" + entityDetail.getDbColumnName()); + } else { + fieldConfig.setColumnName("custom_" + dataObjQueryDetail.getCustomAlias()); + } + + fieldConfig.setWidthType(genCustomListDetail.getWidthType().getCode()); + fieldConfig.setWidth(genCustomListDetail.getWidth()); + fieldConfig.setSortable(genCustomListDetail.getSortable()); + fieldConfig.setFormatter(genCustomListDetail.getFormatter()); + if (genCustomListDetail.getType() == GenCustomListDetailType.MAIN_TABLE + || genCustomListDetail.getType() == GenCustomListDetailType.SUB_TALBE) { + fieldConfig.setIsNumberType(GenDataType.isNumberType(entityDetail.getDataType())); + fieldConfig.setHasAvailableTag( + entityDetail.getViewType() == GenViewType.SELECT + && entityDetail.getDataType() == GenDataType.BOOLEAN + && "available".equals(entityDetail.getColumnName())); + fieldConfig.setFrontType(entityDetail.getEnumFront()); + fieldConfig.setFixEnum(entityDetail.getFixEnum()); + fieldConfig.setDataType(entityDetail.getDataType().getCode()); + } else { + fieldConfig.setIsNumberType(GenDataType.isNumberType(dataObjQueryDetail.getDataType())); + fieldConfig.setHasAvailableTag(false); + fieldConfig.setFrontType(StringPool.EMPTY_STR); + fieldConfig.setFixEnum(false); + fieldConfig.setDataType(dataObjQueryDetail.getDataType().getCode()); + } + + fieldConfigs.add(fieldConfig); + } + } + + listConfig.setFields(fieldConfigs); + result.setListConfig(listConfig); + + return result; + } + + private DataObjectQueryParamObj buildQueryParamObj(DataObjectQueryParamObj queryParamObj, + CustomListConfig config) { + if (queryParamObj == null) { + return null; + } + + if (CollectionUtil.isNotEmpty(queryParamObj.getConditions())) { + for (DataObjectQueryParamObj.Condition condition : queryParamObj.getConditions()) { + FieldConfig fieldConfig = config.getListConfig().getFields().stream().filter( + t -> (condition.getTableAlias() + "_" + condition.getColumnName()) + .equals(t.getColumnName())).findFirst().orElse(null); + if (fieldConfig != null) { + if (condition.getValue() != null) { + condition.setValue(Convert.convert( + EnumUtil.getByCode(GenDataType.class, fieldConfig.getDataType()).getClazz(), + condition.getValue())); + } else if (CollectionUtil.isNotEmpty(condition.getValues())) { + condition.setValues(condition.getValues().stream().map(t -> Convert.convert( + EnumUtil.getByCode(GenDataType.class, fieldConfig.getDataType()).getClazz(), t)) + .collect(Collectors.toList())); + } + } + GenQueryType queryType = EnumUtil.getByCode(GenQueryType.class, condition.getQueryType()); + if (queryType == GenQueryType.IN) { + condition.setValuePrefix("("); + condition.setValueSuffix(")"); + } else if (queryType == GenQueryType.NOT_IN) { + condition.setValuePrefix("("); + condition.setValueSuffix(")"); + } else if (queryType == GenQueryType.LEFT_LIKE) { + condition.setValuePrefix("CONCAT('%',"); + condition.setValueSuffix(")"); + } else if (queryType == GenQueryType.RIGHT_LIKE) { + condition.setValuePrefix("CONCAT("); + condition.setValueSuffix(", '%')"); + } else if (queryType == GenQueryType.AROUND_LIKE) { + condition.setValuePrefix("CONCAT('%',"); + condition.setValueSuffix(", '%')"); + } else { + condition.setValuePrefix(StringPool.EMPTY_STR); + condition.setValueSuffix(StringPool.EMPTY_STR); + } + } + } + return queryParamObj; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomPageBuilder.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomPageBuilder.java new file mode 100644 index 0000000..6a8d82c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomPageBuilder.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.builders; + +import cn.hutool.json.JSONObject; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.xingyun.template.gen.components.custom.page.CustomPageConfig; +import com.lframework.xingyun.template.gen.service.GenCustomPageService; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.starter.web.utils.JsonUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CustomPageBuilder { + + @Autowired + private GenCustomPageService genCustomPageService; + + //@Cacheable(value = CustomPageConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + public CustomPageConfig buildConfig(Integer id) { + + GenCustomPage page = genCustomPageService.findById(id); + if (page == null) { + throw new DefaultClientException("自定义页面不存在!"); + } + + CustomPageConfig config = new CustomPageConfig(); + config.setId(page.getId()); + JSONObject obj = new JSONObject(); + obj.set("template", page.getPageCode()); + String templateStr = JsonUtil.toJsonStr(obj); + templateStr = templateStr.substring("{\"template\":".length(), templateStr.length() - 1); + + String scriptStr = page.getScriptCode(); + String componentConfig = scriptStr.substring(0, scriptStr.indexOf("{") + 1) + "template:" + templateStr + "," + scriptStr.substring(scriptStr.indexOf("{") + 1); + componentConfig = "return " + componentConfig.substring("export default".length()); + config.setComponentConfig(componentConfig); + + return config; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomSelectorBuilder.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomSelectorBuilder.java new file mode 100644 index 0000000..d5866b5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/CustomSelectorBuilder.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.template.gen.builders; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.xingyun.template.gen.components.custom.selector.CustomSelectorConfig; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +@Component +public class CustomSelectorBuilder { + + @Autowired + private GenCustomSelectorService genCustomSelectorService; + + @Autowired + private GenDataObjService genDataObjService; + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Cacheable(value = CustomSelectorConfig.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + public CustomSelectorConfig buildConfig(String id) { + + // 先查询配置信息 + GenCustomSelector data = genCustomSelectorService.findById(id); + + if (data == null) { + throw new DefaultClientException("自定义选择器不存在!"); + } + + GenDataObj dataObj = genDataObjService.findById(data.getIdColumnRelaId()); + GenDataObjDetail dataObjDetail = genDataObjDetailService.getById(data.getIdColumnRelaId()); + GenDataEntityDetail entityDetail = genDataEntityDetailService.getById(data.getIdColumn()); + + CustomSelectorConfig result = new CustomSelectorConfig(); + result.setCustomListId(data.getCustomListId()); + result.setIdColumn( + (dataObj == null ? dataObjDetail.getSubTableAlias() : dataObj.getMainTableAlias()) + "_" + + entityDetail.getDbColumnName()); + + dataObj = genDataObjService.findById(data.getNameColumnRelaId()); + dataObjDetail = genDataObjDetailService.getById(data.getNameColumnRelaId()); + entityDetail = genDataEntityDetailService.getById(data.getNameColumn()); + + result.setNameColumn( + (dataObj == null ? dataObjDetail.getSubTableAlias() : dataObj.getMainTableAlias()) + "_" + + entityDetail.getDbColumnName()); + result.setPlaceholder(data.getPlaceholder()); + result.setDialogTittle(data.getDialogTittle()); + result.setDialogWidth(data.getDialogWidth()); + + return result; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataEntityBuilder.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataEntityBuilder.java new file mode 100644 index 0000000..5698d29 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataEntityBuilder.java @@ -0,0 +1,117 @@ +package com.lframework.xingyun.template.gen.builders; + +import com.lframework.xingyun.template.gen.components.DataEntity; +import com.lframework.xingyun.template.gen.components.DataEntityColumn; +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.service.GenCreateColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDetailColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenQueryColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenQueryParamsColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenUpdateColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenerateInfoService; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 数据实体Builder + */ +@Component +public class DataEntityBuilder { + + @Autowired + private GenDataEntityService genDataEntityService; + + @Autowired + private GenerateInfoService generateInfoService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Autowired + private GenCreateColumnConfigService genCreateColumnConfigService; + + @Autowired + private GenUpdateColumnConfigService genUpdateColumnConfigService; + + @Autowired + private GenQueryColumnConfigService genQueryColumnConfigService; + + @Autowired + private GenQueryParamsColumnConfigService genQueryParamsColumnConfigService; + + @Autowired + private GenDetailColumnConfigService genDetailColumnConfigService; + + /** + * 根据数据对象ID构建 + * + * @param id + * @return + */ + public DataEntity build(String id) { + + // 根据ID查询数据对象 + GenDataEntity dataEntity = genDataEntityService.findById(id); + DataEntity result = new DataEntity(); + result.setId(dataEntity.getId()); + result.setName(dataEntity.getName()); + result.setDescription(dataEntity.getDescription()); + result.setTable(dataEntity); + result.setColumns(this.buildColumns(dataEntity.getId())); + result.setGenerateInfo(this.buildGenerateInfo(dataEntity.getId())); + + return result; + } + + private GenGenerateInfoDto buildGenerateInfo(String dataObjId) { + + return generateInfoService.getByEntityId(dataObjId); + } + + private List buildColumns(String entityId) { + + List results = new ArrayList<>(); + + List columns = genDataEntityDetailService.getByEntityId(entityId); + for (GenDataEntityDetail column : columns) { + DataEntityColumn result = new DataEntityColumn(); + result.setId(column.getId()); + result.setName(column.getName()); + result.setColumnName(column.getColumnName()); + result.setIsKey(column.getIsKey()); + result.setDataType(column.getDataType()); + result.setColumnOrder(column.getColumnOrder()); + result.setDescription(column.getDescription()); + result.setViewType(column.getViewType()); + result.setTableColumn(column); + result.setFixEnum(column.getFixEnum()); + result.setEnumBack(column.getEnumBack()); + result.setEnumFront(column.getEnumFront()); + result.setRegularExpression(column.getRegularExpression()); + result.setIsOrder(column.getIsOrder()); + if (result.getIsOrder()) { + result.setOrderType(column.getOrderType()); + } + + result.setCreateConfig(genCreateColumnConfigService.findById(column.getId())); + result.setUpdateConfig(genUpdateColumnConfigService.findById(column.getId())); + result.setQueryConfig(genQueryColumnConfigService.findById(column.getId())); + result.setQueryParamsConfig(genQueryParamsColumnConfigService.findById(column.getId())); + result.setDetailConfig(genDetailColumnConfigService.findById(column.getId())); + result.setLen(column.getLen()); + result.setDataDicId(column.getDataDicId()); + result.setCustomSelectorId(column.getCustomSelectorId()); + result.setDecimals(column.getDecimals()); + + results.add(result); + } + + return results; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataObjectBuilder.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataObjectBuilder.java new file mode 100644 index 0000000..3287708 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/builders/DataObjectBuilder.java @@ -0,0 +1,151 @@ +package com.lframework.xingyun.template.gen.builders; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryObj; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryObj.QuerySubTableCondition; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjQueryDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +/** + * 数据对象Builder + */ +@Component +public class DataObjectBuilder { + + @Autowired + private GenDataObjService genDataObjService; + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Autowired + private GenDataObjQueryDetailService genDataObjQueryDetailService; + + @Autowired + private GenDataEntityService genDataEntityService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Cacheable(value = DataObjectQueryObj.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + public DataObjectQueryObj buildQueryObj(String id) { + // 先查询配置信息 + GenDataObj data = genDataObjService.findById(id); + + if (data == null) { + throw new DefaultClientException("数据对象不存在!"); + } + + List details = genDataObjDetailService.getByObjId(data.getId()); + List queryDetails = genDataObjQueryDetailService.getByObjId(data.getId()); + + String mainTableId = data.getMainTableId(); + GenDataEntity dataEntity = genDataEntityService.findById(mainTableId); + if (dataEntity == null) { + throw new DefaultClientException("数据实体不存在!"); + } + + List entityDetails = genDataEntityDetailService.getByEntityId(dataEntity.getId()); + + DataObjectQueryObj queryObj = new DataObjectQueryObj(); + List fields = new ArrayList<>(); + + // 主表字段 + if (CollectionUtil.isNotEmpty(entityDetails)) { + for (GenDataEntityDetail entityDetail : entityDetails) { + DataObjectQueryObj.QueryField field = new DataObjectQueryObj.QueryField(); + field.setTableAlias(data.getMainTableAlias()); + field.setColumnName(entityDetail.getDbColumnName()); + field.setColumnAlias(data.getMainTableAlias() + "_" + entityDetail.getDbColumnName()); + field.setDataType(entityDetail.getDataType()); + + fields.add(field); + } + } + + // 子表字段 + if (CollectionUtil.isNotEmpty(details)) { + for (GenDataObjDetail detail : details) { + GenDataEntity subTable = genDataEntityService.findById(detail.getSubTableId()); + List subTableDetails = genDataEntityDetailService.getByEntityId(subTable.getId()); + for (GenDataEntityDetail subTableDetail : subTableDetails) { + DataObjectQueryObj.QueryField field = new DataObjectQueryObj.QueryField(); + field.setTableAlias(detail.getSubTableAlias()); + field.setColumnName(subTableDetail.getDbColumnName()); + field.setColumnAlias(detail.getSubTableAlias() + "_" + subTableDetail.getDbColumnName()); + field.setDataType(subTableDetail.getDataType()); + + fields.add(field); + } + } + } + + // 自定义查询字段 + if (CollectionUtil.isNotEmpty(queryDetails)) { + for (GenDataObjQueryDetail queryDetail : queryDetails) { + DataObjectQueryObj.QueryField field = new DataObjectQueryObj.QueryField(); + field.setColumnName(queryDetail.getCustomSql()); + field.setColumnAlias("custom_" + queryDetail.getCustomAlias()); + field.setDataType(queryDetail.getDataType()); + + fields.add(field); + } + } + + + queryObj.setFields(fields); + queryObj.setMainTable(dataEntity.getTableName()); + queryObj.setMainTableAlias(data.getMainTableAlias()); + + // 关联字表 + List subTables = new ArrayList<>(); + for (GenDataObjDetail detail : details) { + GenDataEntity subTable= genDataEntityService.getById(detail.getSubTableId()); + + DataObjectQueryObj.QuerySubTable querySubTable = new DataObjectQueryObj.QuerySubTable(); + querySubTable.setSubTable(subTable.getTableName()); + querySubTable.setSubTableAlias(detail.getSubTableAlias()); + querySubTable.setJoinType(detail.getRelaMode().getSql()); + + String[] mainTableDetailIds = detail.getMainTableDetailIds().split(StringPool.STR_SPLIT); + String[] subTableDetailIds = detail.getSubTableDetailIds().split(StringPool.STR_SPLIT); + + querySubTable.setJoinCondition(new ArrayList<>()); + + for (int i = 0; i < mainTableDetailIds.length; i++) { + String mainTableDetailId = mainTableDetailIds[i]; + String subTableDetailId = subTableDetailIds[i]; + + GenDataEntityDetail mainTableDetail = genDataEntityDetailService.getById(mainTableDetailId); + GenDataEntityDetail subTableDetail = genDataEntityDetailService.getById(subTableDetailId); + + QuerySubTableCondition condition = new QuerySubTableCondition(); + condition.setKey(mainTableDetail.getDbColumnName()); + condition.setValue(subTableDetail.getDbColumnName()); + querySubTable.getJoinCondition().add(condition); + } + + + + subTables.add(querySubTable); + } + queryObj.setSubTables(subTables); + + return queryObj; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/CreateColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/CreateColumnConfig.java new file mode 100644 index 0000000..d8a2875 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/CreateColumnConfig.java @@ -0,0 +1,19 @@ +package com.lframework.xingyun.template.gen.components; + +public interface CreateColumnConfig { + + /** + * 是否必填 + * + * @return + */ + Boolean getRequired(); + + /** + * 排序 + * + * @return + */ + Integer getOrderNo(); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntity.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntity.java new file mode 100644 index 0000000..f3b9abb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntity.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.template.gen.components; + +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import java.util.List; +import lombok.Data; + +/** + * 数据对象 + */ +@Data +public class DataEntity { + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 备注 + */ + private String description; + + /** + * 数据表信息 + */ + private Table table; + + /** + * 字段信息 + */ + private List columns; + + /** + * 配置信息 + */ + private GenGenerateInfoDto generateInfo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntityColumn.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntityColumn.java new file mode 100644 index 0000000..5b21b27 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DataEntityColumn.java @@ -0,0 +1,130 @@ +package com.lframework.xingyun.template.gen.components; + +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenOrderType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import lombok.Data; + +@Data +public class DataEntityColumn { + + /** + * ID + */ + private String id; + + /** + * 字段显示名称 + */ + private String name; + + /** + * 字段名称 + */ + private String columnName; + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 数据类型 + */ + private GenDataType dataType; + + /** + * 排序编号 + */ + private Integer columnOrder; + + /** + * 备注 + */ + private String description; + + /** + * 显示类型 + */ + private GenViewType viewType; + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 后端枚举名 + */ + private String enumBack; + + /** + * 前端枚举名 + */ + private String enumFront; + + /** + * 正则表达式 + */ + private String regularExpression; + + /** + * 是否排序字段 + */ + private Boolean isOrder; + + /** + * 排序类型 + */ + private GenOrderType orderType; + + /** + * 数据表字段信息 + */ + private TableColumn tableColumn; + + /** + * 新增配置 + */ + private CreateColumnConfig createConfig; + + /** + * 修改配置 + */ + private UpdateColumnConfig updateConfig; + + /** + * 查询配置 + */ + private QueryColumnConfig queryConfig; + + /** + * 查询参数配置 + */ + private QueryParamsColumnConfig queryParamsConfig; + + /** + * 详情配置 + */ + private DetailColumnConfig detailConfig; + + /** + * 数据字典ID + */ + private String dataDicId; + + /** + * 自定义选择器ID + */ + private String customSelectorId; + + /** + * 长度 + */ + private Long len; + + /** + * 小数点位数 + */ + private Integer decimals; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DetailColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DetailColumnConfig.java new file mode 100644 index 0000000..da8d43d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/DetailColumnConfig.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.template.gen.components; + +public interface DetailColumnConfig { + + /** + * 列宽 + * + * @return + */ + Integer getSpan(); + + /** + * 排序 + * + * @return + */ + Integer getOrderNo(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryColumnConfig.java new file mode 100644 index 0000000..f91fbcc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryColumnConfig.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.components; + +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; + +public interface QueryColumnConfig { + + /** + * 宽度类型 + * + * @return + */ + GenQueryWidthType getWidthType(); + + /** + * 宽度 + * + * @return + */ + Integer getWidth(); + + /** + * 页面是否排序 + * + * @return + */ + Boolean getSortable(); + + /** + * 排序 + * + * @return + */ + Integer getOrderNo(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryParamsColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryParamsColumnConfig.java new file mode 100644 index 0000000..4d9e9d0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/QueryParamsColumnConfig.java @@ -0,0 +1,20 @@ +package com.lframework.xingyun.template.gen.components; + +import com.lframework.xingyun.template.gen.enums.GenQueryType; + +public interface QueryParamsColumnConfig { + + /** + * 查询类型 + * + * @return + */ + GenQueryType getQueryType(); + + /** + * 排序 + * + * @return + */ + Integer getOrderNo(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/Table.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/Table.java new file mode 100644 index 0000000..b477a7c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/Table.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.components; + +import com.lframework.xingyun.template.gen.enums.GenConvertType; + +public interface Table { + + /** + * 获取数据库名 + * + * @return + */ + String getSchema(); + + /** + * 获取数据表名 + * + * @return + */ + String getTableName(); + + /** + * 获取数据表备注 + * + * @return + */ + String getComment(); + + /** + * 获取转换方式 + * + * @return + */ + GenConvertType getConvertType(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/TableColumn.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/TableColumn.java new file mode 100644 index 0000000..f5d23c9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/TableColumn.java @@ -0,0 +1,11 @@ +package com.lframework.xingyun.template.gen.components; + +public interface TableColumn { + + /** + * 获取数据表中的字段名称 + * + * @return + */ + String getDbColumnName(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/UpdateColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/UpdateColumnConfig.java new file mode 100644 index 0000000..511eb06 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/UpdateColumnConfig.java @@ -0,0 +1,18 @@ +package com.lframework.xingyun.template.gen.components; + +public interface UpdateColumnConfig { + + /** + * 是否必填 + * + * @return + */ + Boolean getRequired(); + + /** + * 排序 + * + * @return + */ + Integer getOrderNo(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/list/CustomListConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/list/CustomListConfig.java new file mode 100644 index 0000000..b88836a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/list/CustomListConfig.java @@ -0,0 +1,377 @@ +package com.lframework.xingyun.template.gen.components.custom.list; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class CustomListConfig extends BaseBo implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "CustomListConfig"; + + /** + * 工具栏 + */ + @ApiModelProperty("工具栏") + private List toolbars; + + /** + * 查询参数 + */ + @ApiModelProperty("查询参数") + private List queryParams; + + /** + * 操作列 + */ + @ApiModelProperty("操作列") + private List handleColumns; + + /** + * 列表配置 + */ + @ApiModelProperty("列表配置") + private ListConfig listConfig; + + + @Data + public static class QueryParam implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 表别名 + */ + @ApiModelProperty("表别名") + private String tableAlias; + + /** + * 字段名称 + */ + @ApiModelProperty("字段名称") + private String columnName; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + private String name; + + /** + * 前端显示 + */ + @ApiModelProperty("前端显示") + private Boolean frontShow; + + /** + * 查询类型 + */ + @ApiModelProperty("查询类型") + private Integer queryType; + + /** + * 表单宽度 + */ + @ApiModelProperty("表单宽度") + private Integer formWidth; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private Integer viewType; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer dataType; + + /** + * 是否内置枚举 + */ + @ApiModelProperty("是否内置枚举") + private Boolean fixEnum; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + @ApiModelProperty("前端字段类型 只有字段是枚举时生效,此值为前端枚举类型") + private String frontType; + + /** + * 是否包含状态Tag + */ + @ApiModelProperty("是否包含状态Tag") + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 数据字典Code + */ + @ApiModelProperty("数据字典Code") + private String dataDicCode; + + /** + * 自定义选择器ID + */ + @ApiModelProperty("自定义选择器ID") + private String customSelectorId; + + /** + * 默认值 + */ + @ApiModelProperty("默认值") + private Object defaultValue; + } + + @Data + public static class ListConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 列表类型 + */ + @ApiModelProperty("列表类型") + private Integer listType; + + /** + * 表单宽度列表 + */ + @ApiModelProperty("表单宽度列表") + private Integer labelWidth; + + /** + * 是否分页 + */ + @ApiModelProperty("是否分页") + private Boolean hasPage; + + /** + * 是否树形列表 + */ + @ApiModelProperty("是否树形列表") + private Boolean treeData; + + /** + * ID字段 + */ + @ApiModelProperty("ID字段") + private String idColumn; + + /** + * 父级ID字段 + */ + @ApiModelProperty("父级ID字段") + private String treePidColumn; + + /** + * 树形节点字段 + */ + @ApiModelProperty("树形节点字段") + private String treeNodeColumn; + + /** + * 子节点Key值 + */ + @ApiModelProperty("子节点Key值") + private String treeChildrenKey; + + /** + * 是否允许导出 + */ + @ApiModelProperty("是否允许导出") + private Boolean allowExport; + + /** + * 字段 + */ + @ApiModelProperty("字段") + private List fields; + } + + @Data + public static class FieldConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + private String name; + + /** + * 字段名称 + */ + @ApiModelProperty("字段名称") + private String columnName; + + /** + * 宽度类型 + */ + @ApiModelProperty("宽度类型") + private Integer widthType; + + /** + * 宽度 + */ + @ApiModelProperty("宽度") + private Integer width; + + /** + * 是否页面排序 + */ + @ApiModelProperty("是否页面排序") + private Boolean sortable; + + /** + * 是否数字类型 + */ + @ApiModelProperty("是否数字类型") + private Boolean isNumberType = Boolean.FALSE; + + /** + * 是否包含状态Tag + */ + @ApiModelProperty("是否包含状态Tag") + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 是否内置枚举 + */ + @ApiModelProperty("是否内置枚举") + private Boolean fixEnum; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + @ApiModelProperty("前端字段类型 只有字段是枚举时生效,此值为前端枚举类型") + private String frontType; + + /** + * 数据类型 + */ + @ApiModelProperty("数据类型") + private Integer dataType; + + /** + * 格式化脚本 + */ + @ApiModelProperty("格式化脚本") + private String formatter; + } + + @Data + public static class Toolbar implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + private String name; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private String viewType; + + /** + * 按钮类型 + */ + @ApiModelProperty("按钮类型") + private Integer btnType; + + /** + * 按钮配置 + */ + @ApiModelProperty("按钮配置") + private String btnConfig; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 请求参数 + */ + @ApiModelProperty("请求参数") + private String requestParam; + } + + @Data + public static class HandleColumn implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + private String name; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + private String viewType; + + /** + * 按钮类型 + */ + @ApiModelProperty("按钮类型") + private Integer btnType; + + /** + * 按钮配置 + */ + @ApiModelProperty("按钮配置") + private String btnConfig; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 宽度 + */ + @ApiModelProperty("宽度") + private Integer width; + + /** + * 请求参数 + */ + @ApiModelProperty("请求参数") + private String requestParam; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/page/CustomPageConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/page/CustomPageConfig.java new file mode 100644 index 0000000..9feb8d2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/page/CustomPageConfig.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.components.custom.page; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class CustomPageConfig extends BaseBo implements Serializable { + + public static final String CACHE_NAME = "CustomPageConfig"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private Integer id; + + /** + * 组件配置 + */ + @ApiModelProperty("组件配置") + private String componentConfig; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/selector/CustomSelectorConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/selector/CustomSelectorConfig.java new file mode 100644 index 0000000..7d8be96 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/custom/selector/CustomSelectorConfig.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.template.gen.components.custom.selector; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class CustomSelectorConfig extends BaseBo implements Serializable { + + public static final String CACHE_NAME = "CustomSelectorConfig"; + + private static final long serialVersionUID = 1L; + + /** + * 自定义列表ID + */ + @ApiModelProperty("自定义列表ID") + private String customListId; + + /** + * ID字段 + */ + @ApiModelProperty("ID字段") + private String idColumn; + + /** + * 名称字段 + */ + @ApiModelProperty("名称字段") + private String nameColumn; + + /** + * 占位符 + */ + @ApiModelProperty("占位符") + private String placeholder; + + /** + * 对话框标题 + */ + @ApiModelProperty("对话框标题") + private String dialogTittle; + + /** + * 对话框宽度 + */ + @ApiModelProperty("对话框宽度") + private String dialogWidth; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryObj.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryObj.java new file mode 100644 index 0000000..381488b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryObj.java @@ -0,0 +1,122 @@ +package com.lframework.xingyun.template.gen.components.data.obj; + +import com.lframework.xingyun.template.gen.enums.GenDataType; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class DataObjectQueryObj implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "DataObjectQueryObj"; + + /** + * SQL的SELECT部分 + */ + private List fields; + + /** + * 主表 FROM部分 + */ + private String mainTable; + + /** + * 主表别名 + */ + private String mainTableAlias; + + /** + * 关联的子表 + */ + private List subTables; + + /** + * 查询参数 + */ + private DataObjectQueryParamObj queryParamObj; + + /** + * 查询前置SQL + */ + private String queryPrefixSql; + + /** + * 查询后置SQL + */ + private String querySuffixSql; + + /** + * 后置SQL + */ + private String suffixSql; + + @Data + public static class QueryField implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 表别名 如果此值为空,代表为自定义查询字段 + */ + private String tableAlias; + + /** + * 字段名 + */ + private String columnName; + + /** + * 字段别名 + */ + private String columnAlias; + + /** + * 数据类型 + */ + private GenDataType dataType; + } + + @Data + public static class QuerySubTable implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 子表 + */ + private String subTable; + + /** + * 子表别名 + */ + private String subTableAlias; + + /** + * 关联方式 + */ + private String joinType; + + /** + * 关联条件 key:主表字段 value:子表字段 + */ + private List joinCondition; + } + + @Data + public static class QuerySubTableCondition implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 左侧字段 + */ + private String key; + + /** + * 右侧字段 + */ + private String value; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryParamObj.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryParamObj.java new file mode 100644 index 0000000..cfa7bec --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/data/obj/DataObjectQueryParamObj.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.template.gen.components.data.obj; + +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.vo.PageVo; +import java.util.List; +import lombok.Data; + +@Data +public class DataObjectQueryParamObj extends PageVo { + + /** + * 条件 + */ + private List conditions; + + @Data + public static class Condition { + /** + * 表别名 + */ + private String tableAlias; + + /** + * 字段名 + */ + private String columnName; + + /** + * 查询类型 + */ + private Integer queryType; + + /** + * 值前缀 + */ + private String valuePrefix; + + /** + * 值 + */ + private Object value; + + /** + * 值集合 + */ + private List values; + + /** + * 值后缀 + */ + private String valueSuffix; + + public String getQueryTypeSql() { + return EnumUtil.getByCode(GenQueryType.class, this.queryType).getOperation(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomAuthorizationInterceptor.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomAuthorizationInterceptor.java new file mode 100644 index 0000000..6f422a8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomAuthorizationInterceptor.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.gen.components.magic; + +import com.lframework.starter.common.utils.ArrayUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.security.CheckPermissionHandler; +import com.lframework.starter.web.components.security.PermissionCalcType; +import com.lframework.xingyun.template.gen.utils.WebUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.core.context.MagicUser; +import org.ssssssss.magicapi.core.exception.MagicLoginException; +import org.ssssssss.magicapi.core.interceptor.Authorization; +import org.ssssssss.magicapi.core.interceptor.AuthorizationInterceptor; +import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest; + +/** + * 自定义用户名密码登录 + */ +@Component //注入到Spring容器中 +public class MagicCustomAuthorizationInterceptor implements AuthorizationInterceptor { + + @Autowired + private CheckPermissionHandler checkPermissionHandler; + + /** + * 配置是否需要登录 + */ + @Override + public boolean requireLogin() { + return false; + } + + /** + * 根据Token获取User + */ + @Override + public MagicUser getUserByToken(String token) throws MagicLoginException { + AbstractUserDetails currentUser = SecurityUtil.getUserByToken(token); + if (currentUser == null) { + throw new MagicLoginException("请重新登录!请求地址:" + WebUtils.getRequestPath()); + } + + return new MagicUser(currentUser.getId(), currentUser.getName(), token); + } + + @Override + public MagicUser login(String username, String password) throws MagicLoginException { + throw new MagicLoginException("不支持手动登录,请先登录主系统!"); + } + + @Override + public boolean allowVisit(MagicUser magicUser, MagicHttpServletRequest request, + Authorization authorization) { + + String[] profiles = ApplicationUtil.getEnv().getActiveProfiles(); + if (ArrayUtil.isNotEmpty(profiles) && ArrayUtil.contains(profiles, "demo")) { + return authorization == Authorization.VIEW; + } + return checkPermissionHandler.valid(PermissionCalcType.OR, "system:online-code:config"); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomJsonValueProvider.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomJsonValueProvider.java new file mode 100644 index 0000000..5842a29 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomJsonValueProvider.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.components.magic; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import java.util.List; +import java.util.Map; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.core.context.RequestEntity; +import org.ssssssss.magicapi.core.interceptor.ResultProvider; +import org.ssssssss.magicapi.modules.db.model.Page; + +@Component +public class MagicCustomJsonValueProvider implements ResultProvider { + + /** + * 定义返回结果,默认返回JsonBean + */ + @Override + public Object buildResult(RequestEntity requestEntity, int code, String message, Object data) { + if (code >= 200 && code <= 299) { + return InvokeResultBuilder.success(data); + } else { + throw new DefaultClientException(message); + } + } + + /** + * 定义分页返回结果,该项会被封装在Json结果内, 此方法可以不覆盖,默认返回PageResult + */ + @Override + public Object buildPageResult(RequestEntity requestEntity, Page page, long total, + List> data) { + + return PageResultUtil.newInstance(page.getOffset() / page.getLimit() + 1, page.getLimit(), + total, data); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomMagicFunction.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomMagicFunction.java new file mode 100644 index 0000000..a7333cd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomMagicFunction.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.components.magic; + +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.core.config.MagicFunction; +import org.ssssssss.script.annotation.Comment; +import org.ssssssss.script.annotation.Function; + +@Component +public class MagicCustomMagicFunction implements MagicFunction { + + @Function + @Comment("获取登录人ID") + public static AbstractUserDetails current_user() { + AbstractUserDetails user = SecurityUtil.getCurrentUser(); + return user; + } + + @Function + @Comment("获取租户ID") + public static String current_tenant_id() { + return TenantContextHolder.getTenantId() == null ? null + : TenantContextHolder.getTenantId().toString(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomSqlCache.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomSqlCache.java new file mode 100644 index 0000000..0dd1d2b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/components/magic/MagicCustomSqlCache.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.components.magic; + +import com.lframework.starter.web.components.redis.RedisHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.modules.db.cache.SqlCache; + +@Component +public class MagicCustomSqlCache implements SqlCache { + + @Autowired + private RedisHandler redisHandler; + + @Override + public void put(String name, String key, Object value) { + redisHandler.hset(name, key, value); + } + + @Override + public void put(String name, String key, Object value, long ttl) { + redisHandler.hset(name, key, value, ttl); + } + + @Override + public T get(String name, String key) { + return (T) redisHandler.hget(name, key); + } + + @Override + public void delete(String name) { + redisHandler.hdel(name); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/config/MagicCustomConfiguration.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/config/MagicCustomConfiguration.java new file mode 100644 index 0000000..db4ae72 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/config/MagicCustomConfiguration.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.template.gen.config; + +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.web.config.properties.SecretProperties; +import com.lframework.starter.web.utils.DataSourceUtil; +import com.lframework.starter.web.utils.EncryptUtil; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.xingyun.template.inner.service.TenantService; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource; + +@Configuration +public class MagicCustomConfiguration { + + @Autowired + private DynamicDataSourceProperties dynamicDataSourceProperties; + + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setPoolSize(10); + taskScheduler.initialize(); + return taskScheduler; + } + + @Bean + public MagicDynamicDataSource magicDynamicDataSource(DynamicRoutingDataSource dataSource, + TenantService tenantService, BasicDataSourceCreator basicDataSourceCreator, SecretProperties secretProperties) { + Map dataSourceMap = dataSource.getDataSources(); + MagicDynamicDataSource dynamicDataSource = new MagicDynamicDataSource(); + dynamicDataSource.setDefault(dataSourceMap.get("master")); + + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource() + .get("master"); + // 这里只加载启用的租户 + Wrapper queryWrapper = Wrappers.lambdaQuery(Tenant.class) + .eq(Tenant::getAvailable, Boolean.TRUE); + List tenants = tenantService.list(queryWrapper); + + for (Tenant tenant : tenants) { + dynamicDataSource.add(String.valueOf(tenant.getId()), + basicDataSourceCreator.createDataSource( + DataSourceUtil.createDataSourceProperty(dataSourceProperty, tenant.getJdbcUrl(), + tenant.getJdbcUsername(), EncryptUtil.decrypt(tenant.getJdbcPassword(), secretProperties)))); + } + + return dynamicDataSource; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/constants/GenStringPool.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/constants/GenStringPool.java new file mode 100644 index 0000000..fc10d8d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/constants/GenStringPool.java @@ -0,0 +1,5 @@ +package com.lframework.xingyun.template.gen.constants; + +public interface GenStringPool { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenController.java new file mode 100644 index 0000000..46ccd9c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenController.java @@ -0,0 +1,174 @@ +package com.lframework.xingyun.template.gen.controller; + +import cn.hutool.core.convert.Convert; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.gen.builders.CustomListBuilder; +import com.lframework.xingyun.template.gen.builders.CustomPageBuilder; +import com.lframework.xingyun.template.gen.builders.CustomSelectorBuilder; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig; +import com.lframework.xingyun.template.gen.components.custom.page.CustomPageConfig; +import com.lframework.xingyun.template.gen.components.custom.selector.CustomSelectorConfig; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryObj; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryParamObj; +import com.lframework.xingyun.template.gen.mappers.GenMapper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 提供低代码相关功能所需的接口 + */ +@Slf4j +@Api(tags = "低代码接口") +@Validated +@RestController +@RequestMapping("/gen/api") +public class GenController extends DefaultBaseController { + + @Autowired + private CustomListBuilder customListBuilder; + + @Autowired + private CustomSelectorBuilder customSelectorBuilder; + + @Autowired + private GenMapper genMapper; + + @Autowired + private CustomPageBuilder customPageBuilder; + + @ApiOperation("自定义列表配置") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping("/custom/list/config") + public InvokeResult getCustomListConfig( + @NotBlank(message = "ID不能为空!") String id) { + + CustomListConfig config = customListBuilder.buildConfig(id); + + return InvokeResultBuilder.success(config); + } + + @ApiOperation("查询自定义列表数据(分页)") + @PostMapping("/custom/list/query") + public InvokeResult>> customListQueryPage( + @NotBlank(message = "ID不能为空!") String id, + @RequestBody DataObjectQueryParamObj vo) { + + DataObjectQueryObj queryObj = customListBuilder.buildQueryObj(id, vo); + + PageHelperUtil.startPage(vo); + List> datas = genMapper.findList(queryObj); + PageResult> pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + + for (DataObjectQueryObj.QueryField field : queryObj.getFields()) { + for (Map data : datas) { + Object oriValue = data.get(field.getColumnAlias()); + Object newValue = Convert.convert(field.getDataType().getClazz(), + data.get(field.getColumnAlias())); + data.put(field.getColumnAlias(), newValue == null ? oriValue : newValue); + } + } + + return InvokeResultBuilder.success(pageResult); + } + + @ApiOperation("查询自定义列表数据(不分页)") + @PostMapping("/custom/list/query/list") + public InvokeResult>> customListQueryList( + @NotBlank(message = "ID不能为空!") String id, + @RequestBody DataObjectQueryParamObj vo) { + + DataObjectQueryObj queryObj = customListBuilder.buildQueryObj(id, vo); + + List> datas = genMapper.findList(queryObj); + + for (DataObjectQueryObj.QueryField field : queryObj.getFields()) { + for (Map data : datas) { + Object oriValue = data.get(field.getColumnAlias()); + Object newValue = Convert.convert(field.getDataType().getClazz(), + data.get(field.getColumnAlias())); + data.put(field.getColumnAlias(), newValue == null ? oriValue : newValue); + } + } + + return InvokeResultBuilder.success(datas); + } + + @ApiOperation("查询自定义列表数据(树形)") + @PostMapping("/custom/list/query/tree") + public InvokeResult>> customListQueryTree( + @NotBlank(message = "ID不能为空!") String id, + @RequestBody DataObjectQueryParamObj vo) { + + // 查询全量数据 + DataObjectQueryObj queryObj = customListBuilder.buildQueryObj(id, null); + + List> datas = genMapper.findList(queryObj); + + for (DataObjectQueryObj.QueryField field : queryObj.getFields()) { + for (Map data : datas) { + Object oriValue = data.get(field.getColumnAlias()); + Object newValue = Convert.convert(field.getDataType().getClazz(), + data.get(field.getColumnAlias())); + data.put(field.getColumnAlias(), newValue == null ? oriValue : newValue); + } + } + + if (CollectionUtil.isEmpty(datas)) { + return InvokeResultBuilder.success(datas); + } + + DataObjectQueryObj filterQueryObj = customListBuilder.buildQueryObj(id, vo); + List> filterDatas = genMapper.findList(filterQueryObj); + + CustomListConfig config = customListBuilder.buildConfig(id); + String idColumn = config.getListConfig().getIdColumn(); + List ids = filterDatas.stream().map(t -> String.valueOf(t.get(idColumn))).collect( + Collectors.toList()); + datas.stream().filter(t -> ids.contains(String.valueOf(t.get(idColumn)))) + .forEach(t -> t.put("id@show", true)); + + return InvokeResultBuilder.success(datas); + } + + @ApiOperation("自定义选择器配置") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping("/custom/selector/config") + public InvokeResult getCustomSelectorConfig( + @NotBlank(message = "ID不能为空!") String id) { + + CustomSelectorConfig config = customSelectorBuilder.buildConfig(id); + + return InvokeResultBuilder.success(config); + } + + @ApiOperation("获取自定义页面配置") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping("/custom/page/config") + public InvokeResult get(@NotNull(message = "ID不能为空!") Integer id) { + + CustomPageConfig config = customPageBuilder.buildConfig(id); + + return InvokeResultBuilder.success(config); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListCategoryController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListCategoryController.java new file mode 100644 index 0000000..1ab5118 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListCategoryController.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.service.GenCustomListCategoryService; +import com.lframework.xingyun.template.gen.vo.custom.list.category.CreateGenCustomListCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.list.category.UpdateGenCustomListCategoryVo; +import com.lframework.xingyun.template.gen.bo.custom.list.category.GetGenCustomListCategoryBo; +import com.lframework.xingyun.template.gen.bo.custom.list.category.QueryGenCustomListCategoryBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 自定义列表分类 + * + * @author zmj + */ +@Api(tags = "自定义列表分类") +@Validated +@RestController +@RequestMapping("/gen/custom/list/category") +public class GenCustomListCategoryController extends DefaultBaseController { + + @Autowired + private GenCustomListCategoryService genCustomListCategoryService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List datas = genCustomListCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryGenCustomListCategoryBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenCustomListCategory data = genCustomListCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("自定义列表分类不存在!"); + } + + GetGenCustomListCategoryBo result = new GetGenCustomListCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增自定义列表分类 + */ + @ApiOperation("新增自定义列表分类") + @PostMapping + public InvokeResult create(@Valid CreateGenCustomListCategoryVo vo) { + + genCustomListCategoryService.create(vo); + + genCustomListCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改自定义列表分类 + */ + @ApiOperation("修改自定义列表分类") + @PutMapping + public InvokeResult update(@Valid UpdateGenCustomListCategoryVo vo) { + + genCustomListCategoryService.update(vo); + + genCustomListCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("删除自定义列表分类") + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genCustomListCategoryService.deleteById(id); + + genCustomListCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListController.java new file mode 100644 index 0000000..bb0fcb8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomListController.java @@ -0,0 +1,140 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.vo.custom.list.CreateGenCustomListVo; +import com.lframework.xingyun.template.gen.vo.custom.list.QueryGenCustomListVo; +import com.lframework.xingyun.template.gen.vo.custom.list.UpdateGenCustomListVo; +import com.lframework.xingyun.template.gen.bo.custom.list.GetGenCustomListBo; +import com.lframework.xingyun.template.gen.bo.custom.list.QueryGenCustomListBo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "自定义列表") +@Slf4j +@Validated +@RestController +@RequestMapping("/gen/custom/list") +public class GenCustomListController extends DefaultBaseController { + + @Autowired + private GenCustomListService genCustomListService; + + @ApiOperation("查询自定义列表") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryGenCustomListVo vo) { + + PageResult pageResult = genCustomListService.query(getPageIndex(vo), + getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QueryGenCustomListBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenCustomList data = genCustomListService.findById(id); + + return InvokeResultBuilder.success(new GetGenCustomListBo(data)); + } + + @ApiOperation("新增") + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateGenCustomListVo vo) { + + genCustomListService.create(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateGenCustomListVo vo) { + + genCustomListService.update(vo); + + genCustomListService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genCustomListService.delete(id); + + genCustomListService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomListService.batchDelete(ids); + + genCustomListService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量启用") + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomListService.batchEnable(ids); + + genCustomListService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量停用") + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomListService.batchUnable(ids); + + genCustomListService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageCategoryController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageCategoryController.java new file mode 100644 index 0000000..61aca3c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageCategoryController.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.bo.custom.page.category.GetGenCustomPageCategoryBo; +import com.lframework.xingyun.template.gen.bo.custom.page.category.QueryGenCustomPageCategoryBo; +import com.lframework.xingyun.template.gen.service.GenCustomPageCategoryService; +import com.lframework.xingyun.template.gen.vo.custom.page.category.CreateGenCustomPageCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.page.category.UpdateGenCustomPageCategoryVo; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 自定义页面分类 + * + * @author zmj + */ +@Api(tags = "自定义页面分类") +@Validated +@RestController +@RequestMapping("/gen/custom/page/category") +public class GenCustomPageCategoryController extends DefaultBaseController { + + @Autowired + private GenCustomPageCategoryService genCustomPageCategoryService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List datas = genCustomPageCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryGenCustomPageCategoryBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get( + @NotBlank(message = "ID不能为空!") String id) { + + GenCustomPageCategory data = genCustomPageCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("自定义页面分类不存在!"); + } + + GetGenCustomPageCategoryBo result = new GetGenCustomPageCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增自定义页面分类 + */ + @ApiOperation("新增自定义页面分类") + @PostMapping + public InvokeResult create(@Valid CreateGenCustomPageCategoryVo vo) { + + genCustomPageCategoryService.create(vo); + + genCustomPageCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改自定义页面分类 + */ + @ApiOperation("修改自定义页面分类") + @PutMapping + public InvokeResult update(@Valid UpdateGenCustomPageCategoryVo vo) { + + genCustomPageCategoryService.update(vo); + + genCustomPageCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("删除自定义页面分类") + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genCustomPageCategoryService.deleteById(id); + + genCustomPageCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageController.java new file mode 100644 index 0000000..db2d087 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomPageController.java @@ -0,0 +1,114 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.bo.custom.page.GetGenCustomPageBo; +import com.lframework.xingyun.template.gen.bo.custom.page.QueryGenCustomPageBo; +import com.lframework.xingyun.template.gen.service.GenCustomPageService; +import com.lframework.xingyun.template.gen.vo.custom.page.CreateGenCustomPageVo; +import com.lframework.xingyun.template.gen.vo.custom.page.QueryGenCustomPageVo; +import com.lframework.xingyun.template.gen.vo.custom.page.UpdateGenCustomPageVo; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "自定义页面") +@Slf4j +@Validated +@RestController +@RequestMapping("/gen/custom/page") +public class GenCustomPageController extends DefaultBaseController { + + @Autowired + private GenCustomPageService genCustomPageService; + + @ApiOperation("查询自定义页面") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryGenCustomPageVo vo) { + + PageResult pageResult = genCustomPageService.query(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QueryGenCustomPageBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult getConfig(@NotNull(message = "ID不能为空!") Integer id) { + + GenCustomPage data = genCustomPageService.findById(id); + + return InvokeResultBuilder.success(new GetGenCustomPageBo(data)); + } + + @ApiOperation("新增") + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateGenCustomPageVo vo) { + + genCustomPageService.create(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateGenCustomPageVo vo) { + + genCustomPageService.update(vo); + + genCustomPageService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @DeleteMapping + public InvokeResult delete(@NotNull(message = "ID不能为空!") Integer id) { + + genCustomPageService.delete(id); + + genCustomPageService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomPageService.batchDelete(ids); + + genCustomPageService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorCategoryController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorCategoryController.java new file mode 100644 index 0000000..5975d1e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorCategoryController.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorCategoryService; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.CreateGenCustomSelectorCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.UpdateGenCustomSelectorCategoryVo; +import com.lframework.xingyun.template.gen.bo.custom.selector.category.GetGenCustomSelectorCategoryBo; +import com.lframework.xingyun.template.gen.bo.custom.selector.category.QueryGenCustomSelectorCategoryBo; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 自定义选择器分类 + * + * @author zmj + */ +@Api(tags = "自定义选择器分类") +@Validated +@RestController +@RequestMapping("/gen/custom/selector/category") +public class GenCustomSelectorCategoryController extends DefaultBaseController { + + @Autowired + private GenCustomSelectorCategoryService genCustomSelectorCategoryService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List datas = genCustomSelectorCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryGenCustomSelectorCategoryBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get( + @NotBlank(message = "ID不能为空!") String id) { + + GenCustomSelectorCategory data = genCustomSelectorCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("自定义选择器分类不存在!"); + } + + GetGenCustomSelectorCategoryBo result = new GetGenCustomSelectorCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增自定义选择器分类 + */ + @ApiOperation("新增自定义选择器分类") + @PostMapping + public InvokeResult create(@Valid CreateGenCustomSelectorCategoryVo vo) { + + genCustomSelectorCategoryService.create(vo); + + genCustomSelectorCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改自定义选择器分类 + */ + @ApiOperation("修改自定义选择器分类") + @PutMapping + public InvokeResult update(@Valid UpdateGenCustomSelectorCategoryVo vo) { + + genCustomSelectorCategoryService.update(vo); + + genCustomSelectorCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("删除自定义选择器分类") + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genCustomSelectorCategoryService.deleteById(id); + + genCustomSelectorCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorController.java new file mode 100644 index 0000000..88da8f8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenCustomSelectorController.java @@ -0,0 +1,141 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.vo.custom.selector.CreateGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.QueryGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.UpdateGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.bo.custom.selector.GetGenCustomSelectorBo; +import com.lframework.xingyun.template.gen.bo.custom.selector.QueryGenCustomSelectorBo; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "自定义选择器") +@Slf4j +@Validated +@RestController +@RequestMapping("/gen/custom/selector") +public class GenCustomSelectorController extends DefaultBaseController { + + @Autowired + private GenCustomSelectorService genCustomSelectorService; + + @ApiOperation("查询自定义选择器") + @GetMapping("/query") + public InvokeResult> query( + @Valid QueryGenCustomSelectorVo vo) { + + PageResult pageResult = genCustomSelectorService.query(getPageIndex(vo), + getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QueryGenCustomSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenCustomSelector data = genCustomSelectorService.findById(id); + + return InvokeResultBuilder.success(new GetGenCustomSelectorBo(data)); + } + + @ApiOperation("新增") + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateGenCustomSelectorVo vo) { + + genCustomSelectorService.create(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateGenCustomSelectorVo vo) { + + genCustomSelectorService.update(vo); + + genCustomSelectorService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genCustomSelectorService.delete(id); + + genCustomSelectorService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomSelectorService.batchDelete(ids); + + genCustomSelectorService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量启用") + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomSelectorService.batchEnable(ids); + + genCustomSelectorService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量停用") + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genCustomSelectorService.batchUnable(ids); + + genCustomSelectorService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityCategoryController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityCategoryController.java new file mode 100644 index 0000000..263be1f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityCategoryController.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.service.GenDataEntityCategoryService; +import com.lframework.xingyun.template.gen.vo.data.entity.category.CreateGenDataEntityCategoryVo; +import com.lframework.xingyun.template.gen.vo.data.entity.category.UpdateGenDataEntityCategoryVo; +import com.lframework.xingyun.template.gen.bo.data.entity.category.GetGenDataEntityCategoryBo; +import com.lframework.xingyun.template.gen.bo.data.entity.category.QueryGenDataEntityCategoryBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据实体分类 + * + * @author zmj + */ +@Api(tags = "数据实体分类") +@Validated +@RestController +@RequestMapping("/gen/data/entity/category") +public class GenDataEntityCategoryController extends DefaultBaseController { + + @Autowired + private GenDataEntityCategoryService genDataEntityCategoryService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List datas = genDataEntityCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryGenDataEntityCategoryBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenDataEntityCategory data = genDataEntityCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("数据实体分类不存在!"); + } + + GetGenDataEntityCategoryBo result = new GetGenDataEntityCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增数据实体分类 + */ + @ApiOperation("新增数据实体分类") + @PostMapping + public InvokeResult create(@Valid CreateGenDataEntityCategoryVo vo) { + + genDataEntityCategoryService.create(vo); + + genDataEntityCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据实体分类 + */ + @ApiOperation("修改数据实体分类") + @PutMapping + public InvokeResult update(@Valid UpdateGenDataEntityCategoryVo vo) { + + genDataEntityCategoryService.update(vo); + + genDataEntityCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("删除数据实体分类") + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genDataEntityCategoryService.deleteById(id); + + genDataEntityCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityController.java new file mode 100644 index 0000000..e4b66ef --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataEntityController.java @@ -0,0 +1,307 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.FileUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.common.utils.ZipUtil; +import com.lframework.xingyun.template.gen.converters.GenStringConverter; +import com.lframework.xingyun.template.gen.converters.GenViewTypeConverter; +import com.lframework.xingyun.template.gen.dto.data.entity.DataEntityGenerateDto; +import com.lframework.xingyun.template.gen.dto.generate.GenerateDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.generate.Generator; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import com.lframework.xingyun.template.gen.service.SimpleTableColumnService; +import com.lframework.xingyun.template.gen.vo.data.entity.CreateDataEntityVo; +import com.lframework.xingyun.template.gen.vo.data.entity.QueryDataEntityVo; +import com.lframework.xingyun.template.gen.vo.data.entity.UpdateDataEntityGenerateVo; +import com.lframework.xingyun.template.gen.vo.data.entity.UpdateDataEntityVo; +import com.lframework.xingyun.template.gen.vo.simpledb.QuerySimpleTableColumnVo; +import com.lframework.xingyun.template.gen.bo.data.entity.DataEntityGenerateBo; +import com.lframework.xingyun.template.gen.bo.data.entity.GenDataEntityDetailBo; +import com.lframework.xingyun.template.gen.bo.data.entity.GetDataEntityBo; +import com.lframework.xingyun.template.gen.bo.data.entity.QueryDataEntityBo; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.ResponseUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "数据实体") +@Slf4j +@Validated +@RestController +@RequestMapping("/gen/data/entity") +public class GenDataEntityController extends DefaultBaseController { + + @Autowired + private GenDataEntityService genDataEntityService; + + @Autowired + private SimpleTableColumnService simpleTableColumnService; + + @Autowired + private GenViewTypeConverter genViewTypeConverter; + + /** + * 上传文件的临时文件目录 + */ + @Value("${spring.servlet.multipart.location}") + private String location; + + @ApiOperation("查询数据对象列表") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryDataEntityVo vo) { + + PageResult pageResult = genDataEntityService.query(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QueryDataEntityBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @ApiOperation("查询列信息") + @GetMapping("/query/columns") + public InvokeResult> getColumns(@Valid QuerySimpleTableColumnVo vo) { + List datas = simpleTableColumnService.query(vo); + if (CollectionUtil.isEmpty(datas)) { + throw new DefaultClientException("数据表不存在,请检查!"); + } + List details = datas.stream().map(t -> { + GenDataEntityDetail detail = new GenDataEntityDetail(); + detail.setId(t.getDbColumnName()); + detail.setName(t.getColumnComment()); + detail.setColumnName(GenStringConverter.convertToCamelCase(GenConvertType.UNDERLINE_TO_CAMEL, + t.getDbColumnName())); + detail.setIsKey(t.getIsKey()); + detail.setDataType(t.getDataType()); + detail.setColumnOrder(t.getOrdinalPosition()); + List viewTypes = genViewTypeConverter.convert(t.getDataType()); + if (CollectionUtil.isEmpty(viewTypes)) { + throw new DefaultClientException("字段:" + t.getDbColumnName() + "类型暂不支持!"); + } + detail.setViewType(viewTypes.get(0)); + detail.setFixEnum(Boolean.FALSE); + detail.setIsOrder(Boolean.FALSE); + detail.setLen(t.getLen()); + detail.setDecimals(t.getDecimals()); + + return detail; + }).collect(Collectors.toList()); + + List results = details.stream().map(GenDataEntityDetailBo::new).collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenDataEntity data = genDataEntityService.findById(id); + + return InvokeResultBuilder.success(new GetDataEntityBo(data)); + } + + @ApiOperation("新增") + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateDataEntityVo vo) { + + genDataEntityService.create(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateDataEntityVo vo) { + + genDataEntityService.update(vo); + + this.evictRelaCache(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genDataEntityService.delete(id); + + this.evictRelaCache(id); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genDataEntityService.batchDelete(ids); + + for (String id : ids) { + this.evictRelaCache(id); + } + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量启用") + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genDataEntityService.batchEnable(ids); + + for (String id : ids) { + this.evictRelaCache(id); + } + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量停用") + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genDataEntityService.batchUnable(ids); + + for (String id : ids) { + this.evictRelaCache(id); + } + + return InvokeResultBuilder.success(); + } + + @ApiOperation("获取生成代码配置") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping("/generate") + public InvokeResult getGenerate(@NotNull(message = "ID不能为空!") String id) { + + DataEntityGenerateDto data = genDataEntityService.getGenerateById(id); + + DataEntityGenerateBo result = new DataEntityGenerateBo(data); + + return InvokeResultBuilder.success(result); + } + + @ApiOperation("修改生成代码配置") + @PatchMapping("/generate") + public InvokeResult updateGenerate(@Valid @RequestBody UpdateDataEntityGenerateVo vo) { + + genDataEntityService.updateGenerate(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("预览") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping("/preview") + public InvokeResult> preView(@NotNull(message = "ID不能为空!") String id) { + + Generator generator = Generator.getInstance(id); + List datas = generator.generateAll(); + Map result = new LinkedHashMap<>(); + for (GenerateDto data : datas) { + result.put(data.getFileName(), data.getContent()); + } + + return InvokeResultBuilder.success(result); + } + + @ApiOperation("下载") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping("/download") + public void download(@NotNull(message = "ID不能为空!") String id) { + + String fileLocation = location.endsWith(File.separator) ? location : location + File.separator; + String filePath = fileLocation + IdUtil.getUUID() + File.separator; + + Generator generator = Generator.getInstance(id); + + List datas = generator.generateAll(); + for (GenerateDto data : datas) { + + File file = FileUtil.file(filePath + data.getPath() + File.separator + data.getFileName()); + FileUtil.writeString(data.getContent(), file, StandardCharsets.UTF_8); + } + + File zipFile = ZipUtil.zip(filePath, fileLocation + IdUtil.getUUID() + ".zip", false); + + ResponseUtil.download(zipFile); + } + + @ApiOperation("同步数据表") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @PutMapping("/sync/table") + public InvokeResult syncTable(@NotNull(message = "ID不能为空!") String id) { + genDataEntityService.syncTable(id); + + this.evictRelaCache(id); + + return InvokeResultBuilder.success(); + } + + // 失效关联数据的缓存 + private void evictRelaCache(String entityId) { + ThreadUtil.execAsync(() -> { + GenDataObjService genDataObjService = ApplicationUtil.getBean(GenDataObjService.class); + List ids = genDataObjService.getRelaGenDataEntityIds(entityId); + if (CollectionUtil.isNotEmpty(ids)) { + genDataObjService.cleanCacheByKeys(ids); + } + + GenCustomListService genCustomListService = ApplicationUtil.getBean(GenCustomListService.class); + ids = genCustomListService.getRelaGenDataEntityIds(entityId); + if (CollectionUtil.isNotEmpty(ids)) { + genCustomListService.cleanCacheByKeys(ids); + } + }); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjCategoryController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjCategoryController.java new file mode 100644 index 0000000..7b403f3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjCategoryController.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.bo.data.obj.category.GetGenDataObjCategoryBo; +import com.lframework.xingyun.template.gen.bo.data.obj.category.QueryGenDataObjCategoryBo; +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.service.GenDataObjCategoryService; +import com.lframework.xingyun.template.gen.vo.data.obj.category.CreateGenDataObjCategoryVo; +import com.lframework.xingyun.template.gen.vo.data.obj.category.UpdateGenDataObjCategoryVo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据对象分类 + * + * @author zmj + */ +@Api(tags = "数据对象分类") +@Validated +@RestController +@RequestMapping("/gen/data/obj/category") +public class GenDataObjCategoryController extends DefaultBaseController { + + @Autowired + private GenDataObjCategoryService genDataObjCategoryService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @GetMapping("/query") + public InvokeResult> query() { + List datas = genDataObjCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryGenDataObjCategoryBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenDataObjCategory data = genDataObjCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("数据对象分类不存在!"); + } + + GetGenDataObjCategoryBo result = new GetGenDataObjCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增数据对象分类 + */ + @ApiOperation("新增数据对象分类") + @PostMapping + public InvokeResult create(@Valid CreateGenDataObjCategoryVo vo) { + + genDataObjCategoryService.create(vo); + + genDataObjCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据对象分类 + */ + @ApiOperation("修改数据对象分类") + @PutMapping + public InvokeResult update(@Valid UpdateGenDataObjCategoryVo vo) { + + genDataObjCategoryService.update(vo); + + genDataObjCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("删除数据对象分类") + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genDataObjCategoryService.deleteById(id); + + genDataObjCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjController.java new file mode 100644 index 0000000..f24804b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenDataObjController.java @@ -0,0 +1,259 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.bo.data.obj.GenDataObjColumnBo; +import com.lframework.xingyun.template.gen.bo.data.obj.GenDataObjColumnBo.ColumnBo; +import com.lframework.xingyun.template.gen.bo.data.obj.GetGenDataObjBo; +import com.lframework.xingyun.template.gen.bo.data.obj.QueryGenDataObjBo; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjQueryDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import com.lframework.xingyun.template.gen.vo.data.obj.CreateGenDataObjVo; +import com.lframework.xingyun.template.gen.vo.data.obj.QueryGenDataObjVo; +import com.lframework.xingyun.template.gen.vo.data.obj.UpdateGenDataObjVo; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "数据对象") +@Slf4j +@Validated +@RestController +@RequestMapping("/gen/data/obj") +public class GenDataObjController extends DefaultBaseController { + + @Autowired + private GenDataObjService genDataObjService; + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Autowired + private GenDataObjQueryDetailService genDataObjQueryDetailService; + + @Autowired + private GenDataEntityService genDataEntityService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @ApiOperation("查询数据对象列表") + @GetMapping("/query") + public InvokeResult> query(@Valid QueryGenDataObjVo vo) { + + PageResult pageResult = genDataObjService.query(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QueryGenDataObjBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + @ApiOperation("查询数据对象列") + @ApiImplicitParam(value = "数据对象ID", name = "id", paramType = "query", required = true) + @GetMapping("/columns") + public InvokeResult> queryColumns( + @NotBlank(message = "ID不能为空!") String id) { + + GenDataObj dataObj = genDataObjService.findById(id); + if (dataObj == null) { + throw new DefaultClientException("数据对象不存在!"); + } + + List dataObjDetails = genDataObjDetailService.getByObjId(dataObj.getId()); + + List dataObjQueryDetails = genDataObjQueryDetailService.getByObjId( + dataObj.getId()); + + List results = new ArrayList<>(); + // 先查主表 + GenDataEntity dataEntity = genDataEntityService.findById(dataObj.getMainTableId()); + if (dataEntity == null) { + throw new DefaultClientException("主表已被删除,请检查!"); + } + + List dataEntityDetails = genDataEntityDetailService.getByEntityId( + dataEntity.getId()); + + GenDataObjColumnBo mainTable = new GenDataObjColumnBo(); + mainTable.setColumns(new ArrayList<>()); + mainTable.setId(dataEntity.getId()); + mainTable.setName("【主表】" + dataEntity.getName()); + for (GenDataEntityDetail dataEntityDetail : dataEntityDetails) { + ColumnBo column = new ColumnBo(); + column.setId(dataEntityDetail.getId()); + column.setRelaId(dataObj.getId()); + column.setName(dataEntityDetail.getName()); + column.setType(GenCustomListDetailType.MAIN_TABLE.getCode()); + column.setDataType(dataEntityDetail.getDataType().getCode()); + column.setViewType(dataEntityDetail.getViewType().getCode()); + mainTable.getColumns().add(column); + } + + results.add(mainTable); + + // 再查子表 + if (!CollectionUtil.isEmpty(dataObjDetails)) { + for (GenDataObjDetail dataObjDetail : dataObjDetails) { + GenDataEntity subDataEntity = genDataEntityService.findById(dataObjDetail.getSubTableId()); + if (subDataEntity == null) { + throw new DefaultClientException("子表已被删除,请检查!"); + } + + List subDataEntityDetails = genDataEntityDetailService.getByEntityId( + subDataEntity.getId()); + + GenDataObjColumnBo subTable = new GenDataObjColumnBo(); + subTable.setColumns(new ArrayList<>()); + subTable.setId(subDataEntity.getId()); + subTable.setName("【子表】" + subDataEntity.getName()); + for (GenDataEntityDetail dataEntityDetail : subDataEntityDetails) { + ColumnBo column = new ColumnBo(); + column.setId(dataEntityDetail.getId()); + column.setRelaId(dataObjDetail.getId()); + column.setName(dataEntityDetail.getName()); + column.setType(GenCustomListDetailType.SUB_TALBE.getCode()); + column.setDataType(dataEntityDetail.getDataType().getCode()); + column.setViewType(dataEntityDetail.getViewType().getCode()); + subTable.getColumns().add(column); + } + + results.add(subTable); + } + } + + // 最后查附加字段 + if (!CollectionUtil.isEmpty(dataObjQueryDetails)) { + GenDataObjColumnBo customQuery = new GenDataObjColumnBo(); + customQuery.setColumns(new ArrayList<>()); + customQuery.setId("customQuery"); + customQuery.setName("自定义查询"); + for (GenDataObjQueryDetail genDataObjDetail : dataObjQueryDetails) { + ColumnBo column = new ColumnBo(); + column.setId(genDataObjDetail.getId()); + column.setRelaId(genDataObjDetail.getId()); + column.setName(genDataObjDetail.getCustomName()); + column.setType(GenCustomListDetailType.CUSTOM.getCode()); + column.setDataType(genDataObjDetail.getDataType().getCode()); + customQuery.getColumns().add(column); + } + + results.add(customQuery); + } + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + GenDataObj data = genDataObjService.findById(id); + + return InvokeResultBuilder.success(new GetGenDataObjBo(data)); + } + + @ApiOperation("新增") + @PostMapping + public InvokeResult create(@RequestBody @Valid CreateGenDataObjVo vo) { + + genDataObjService.create(vo); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("修改") + @PutMapping + public InvokeResult update(@RequestBody @Valid UpdateGenDataObjVo vo) { + + genDataObjService.update(vo); + + genDataObjService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + genDataObjService.delete(id); + + genDataObjService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public InvokeResult batchDelete( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genDataObjService.batchDelete(ids); + + genDataObjService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量启用") + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genDataObjService.batchEnable(ids); + + genDataObjService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("批量停用") + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "ID", required = true) @RequestBody @NotEmpty(message = "ID不能为空!") List ids) { + + genDataObjService.batchUnable(ids); + + genDataObjService.cleanCacheByKeys(ids); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenSelectorController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenSelectorController.java new file mode 100644 index 0000000..68d7b74 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/controller/GenSelectorController.java @@ -0,0 +1,523 @@ +package com.lframework.xingyun.template.gen.controller; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.gen.bo.custom.list.GenCustomListSelectorBo; +import com.lframework.xingyun.template.gen.bo.custom.list.category.GenCustomListCategorySelectorBo; +import com.lframework.xingyun.template.gen.bo.custom.page.GenCustomPageSelectorBo; +import com.lframework.xingyun.template.gen.bo.custom.page.category.GenCustomPageCategorySelectorBo; +import com.lframework.xingyun.template.gen.bo.custom.selector.GenCustomSelectorSelectorBo; +import com.lframework.xingyun.template.gen.bo.custom.selector.category.GenCustomSelectorCategorySelectorBo; +import com.lframework.xingyun.template.gen.bo.data.entity.GenDataEntityDetailSelectorBo; +import com.lframework.xingyun.template.gen.bo.data.entity.GenDataEntitySelectorBo; +import com.lframework.xingyun.template.gen.bo.data.entity.category.GenDataEntityCategorySelectorBo; +import com.lframework.xingyun.template.gen.bo.data.obj.GenDataObjSelectorBo; +import com.lframework.xingyun.template.gen.bo.data.obj.category.GenDataObjCategorySelectorBo; +import com.lframework.xingyun.template.gen.bo.simpledb.SimpleDBSelectorBo; +import com.lframework.xingyun.template.gen.dto.simpledb.SimpleDBDto; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.service.GenCustomListCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.service.GenCustomPageCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomPageService; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.service.GenDataEntityCategoryService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDataObjCategoryService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import com.lframework.xingyun.template.gen.service.SimpleDBService; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.list.category.GenCustomListCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.page.GenCustomPageSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.GenCustomSelectorSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.GenCustomSelectorCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntityDetailSelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntitySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.category.GenDataEntityCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.GenDataObjSelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.category.GenDataObjCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.simpledb.SimpleTableSelectorVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "代码生成-选择器") +@Slf4j +@Validated +@RestController +@RequestMapping("/selector/gen") +public class GenSelectorController extends DefaultBaseController { + + @Autowired + private GenDataEntityCategoryService genDataEntityCategoryService; + + @Autowired + private GenDataObjCategoryService genDataObjCategoryService; + + @Autowired + private SimpleDBService simpleDBService; + + @Autowired + private GenDataEntityService genDataEntityService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Autowired + private GenDataObjService genDataObjService; + + @Autowired + private GenCustomListCategoryService genCustomListCategoryService; + + @Autowired + private GenCustomListService genCustomListService; + + @Autowired + private GenCustomSelectorCategoryService genCustomSelectorCategoryService; + + @Autowired + private GenCustomSelectorService genCustomSelectorService; + + @Autowired + private GenCustomPageCategoryService genCustomPageCategoryService; + + @Autowired + private GenCustomPageService genCustomPageService; + + @ApiOperation("数据实体分类") + @GetMapping("/data/entity/category") + public InvokeResult> dataEntityCategory( + @Valid GenDataEntityCategorySelectorVo vo) { + + PageResult pageResult = genDataEntityCategoryService.selector( + getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenDataEntityCategorySelectorBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据实体分类 + */ + @ApiOperation("加载数据实体分类") + @PostMapping("/data/entity/category/load") + public InvokeResult> loadDataEntityCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genDataEntityCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenDataEntityCategorySelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据对象分类") + @GetMapping("/data/obj/category") + public InvokeResult> dataObjCategory( + @Valid GenDataObjCategorySelectorVo vo) { + + PageResult pageResult = genDataObjCategoryService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenDataObjCategorySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据对象分类 + */ + @ApiOperation("加载数据对象分类") + @PostMapping("/data/obj/category/load") + public InvokeResult> loadDataObjCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genDataObjCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenDataObjCategorySelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据表") + @GetMapping("/table") + public InvokeResult> table(@Valid SimpleTableSelectorVo vo) { + PageResult pageResult = simpleDBService.selector(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SimpleDBSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据表 + */ + @ApiOperation("加载数据表") + @PostMapping("/table/load") + public InvokeResult> loadTable( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = simpleDBService.listByIds(ids); + List results = datas.stream().map(SimpleDBSelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据实体") + @GetMapping("/data/entity") + public InvokeResult> dataEntity( + @Valid GenDataEntitySelectorVo vo) { + PageResult pageResult = genDataEntityService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenDataEntitySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据实体 + */ + @ApiOperation("加载数据实体") + @PostMapping("/data/entity/load") + public InvokeResult> loadDataEntity( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = genDataEntityService.listByIds(ids); + List results = datas.stream().map(GenDataEntitySelectorBo::new) + .collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据实体明细") + @GetMapping("/data/entity/detail") + public InvokeResult> dataEntityDetail( + @Valid GenDataEntityDetailSelectorVo vo) { + List datas = genDataEntityDetailService.selector(vo); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenDataEntityDetailSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据对象") + @GetMapping("/data/obj") + public InvokeResult> dataObj(@Valid GenDataObjSelectorVo vo) { + PageResult pageResult = genDataObjService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenDataObjSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据对象 + */ + @ApiOperation("加载数据对象") + @PostMapping("/data/obj/load") + public InvokeResult> loadDataObj( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genDataObjService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(GenDataObjSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("自定义列表分类") + @GetMapping("/custom/list/category") + public InvokeResult> customListCategory( + @Valid GenCustomListCategorySelectorVo vo) { + PageResult pageResult = genCustomListCategoryService.selector( + getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenCustomListCategorySelectorBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载自定义列表分类 + */ + @ApiOperation("加载自定义列表分类") + @PostMapping("/custom/list/category/load") + public InvokeResult> loadCustomListCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genCustomListCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenCustomListCategorySelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("自定义列表") + @GetMapping("/custom/list") + public InvokeResult> customList( + @Valid GenCustomListSelectorVo vo) { + PageResult pageResult = genCustomListService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenCustomListSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载自定义列表 + */ + @ApiOperation("加载自定义列表") + @PostMapping("/custom/list/load") + public InvokeResult> loadCustomList( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genCustomListService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenCustomListSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("自定义选择器分类") + @GetMapping("/custom/selector/category") + public InvokeResult> customSelectorCategory( + @Valid GenCustomSelectorCategorySelectorVo vo) { + PageResult pageResult = genCustomSelectorCategoryService.selector( + getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenCustomSelectorCategorySelectorBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载自定义选择器分类 + */ + @ApiOperation("加载自定义选择器分类") + @PostMapping("/custom/selector/category/load") + public InvokeResult> loadCustomSelectorCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genCustomSelectorCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenCustomSelectorCategorySelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("自定义选择器") + @GetMapping("/custom/selector") + public InvokeResult> customList( + @Valid GenCustomSelectorSelectorVo vo) { + PageResult pageResult = genCustomSelectorService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenCustomSelectorSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载自定义选择器 + */ + @ApiOperation("加载自定义选择器") + @PostMapping("/custom/selector/load") + public InvokeResult> loadCustomSelector( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genCustomSelectorService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenCustomSelectorSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("自定义页面分类") + @GetMapping("/custom/page/category") + public InvokeResult> customPageCategory() { + List datas = genCustomPageCategoryService.queryList(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenCustomPageCategorySelectorBo::new) + .collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 加载自定义表单分类 + */ + @ApiOperation("加载自定义页面分类") + @PostMapping("/custom/page/category/load") + public InvokeResult> loadCustomPageCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> genCustomPageCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenCustomPageCategorySelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } + + @ApiOperation("自定义页面") + @GetMapping("/custom/page") + public InvokeResult> customPage( + @Valid GenCustomPageSelectorVo vo) { + PageResult pageResult = genCustomPageService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(GenCustomPageSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载自定义表单 + */ + @ApiOperation("加载自定义页面") + @PostMapping("/custom/page/load") + public InvokeResult> loadCustomPage( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(Objects::nonNull) + .map(t -> genCustomPageService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(GenCustomPageSelectorBo::new).collect( + Collectors.toList()); + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenMysqlDataTypeConverter.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenMysqlDataTypeConverter.java new file mode 100644 index 0000000..f513559 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenMysqlDataTypeConverter.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.template.gen.converters; + +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenMySqlDataType; +import org.springframework.stereotype.Component; + +@Component +public class GenMysqlDataTypeConverter { + + public GenMySqlDataType convert(GenDataType dataType) { + + GenMySqlDataType[] mySqlDataTypes = GenMySqlDataType.values(); + for (GenMySqlDataType mySqlDataType : mySqlDataTypes) { + if (mySqlDataType.getDataType() == dataType) { + return mySqlDataType; + } + } + + return null; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenStringConverter.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenStringConverter.java new file mode 100644 index 0000000..efe88b8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenStringConverter.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.template.gen.converters; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.enums.GenConvertType; + +/** + * @author zmj + * @since 2022/8/18 + */ +public class GenStringConverter { + + /** + * 转换 + * + * @param type + * @param oriStr + * @return + */ + public static String convert(GenConvertType type, String oriStr) { + if (StringUtil.isBlank(oriStr)) { + return oriStr; + } + + if (type == GenConvertType.UNDERLINE_TO_CAMEL) { + return StringUtil.toCamelCase(oriStr); + } + + return null; + } + + /** + * 强制转换成驼峰 + * + * @param type + * @param oriStr + * @return + */ + public static String convertToCamelCase(GenConvertType type, String oriStr) { + + if (type == GenConvertType.UNDERLINE_TO_CAMEL) { + return StringUtil.toCamelCase(oriStr); + } + + return null; + } + + /** + * 强制转换成普通小写 即为:不含分割线的小写字符 + * + * @param type + * @param oriStr + * @return + */ + public static String convertToNormalLowerCase(GenConvertType type, String oriStr) { + if (type == GenConvertType.UNDERLINE_TO_CAMEL) { + return StringUtil.toCamelCase(oriStr).toLowerCase(); + } + + return null; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenViewTypeConverter.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenViewTypeConverter.java new file mode 100644 index 0000000..3b1f4d5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/converters/GenViewTypeConverter.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.template.gen.converters; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class GenViewTypeConverter { + + public boolean canConvert(GenViewType viewType, GenDataType dataType) { + + List viewTypes = convert(dataType); + if (CollectionUtil.isEmpty(viewTypes)) { + return false; + } + + return viewTypes.contains(viewType); + } + + public List convert(GenDataType dataType) { + + if (dataType == null) { + return null; + } + + List results = new ArrayList<>(); + if (dataType == GenDataType.STRING) { + results.addAll(Arrays.asList(GenViewType.values())); + } else if (dataType == GenDataType.INTEGER) { + results.addAll(Arrays.asList(GenViewType.INPUT, GenViewType.SELECT)); + } else if (dataType == GenDataType.SHORT) { + results.addAll(Arrays.asList(GenViewType.INPUT, GenViewType.SELECT)); + } else if (dataType == GenDataType.LONG) { + results.addAll(Arrays.asList(GenViewType.INPUT)); + } else if (dataType == GenDataType.DOUBLE) { + results.addAll(Arrays.asList(GenViewType.INPUT)); + } else if (dataType == GenDataType.LOCAL_DATE) { + results.addAll(Arrays.asList(GenViewType.INPUT, GenViewType.DATE, GenViewType.DATE_RANGE)); + } else if (dataType == GenDataType.LOCAL_DATE_TIME) { + results.addAll( + Arrays.asList(GenViewType.INPUT, GenViewType.DATETIME, GenViewType.DATE_RANGE)); + } else if (dataType == GenDataType.LOCAL_TIME) { + results.addAll(Arrays.asList(GenViewType.INPUT, GenViewType.TIME)); + } else if (dataType == GenDataType.BOOLEAN) { + results.addAll(Arrays.asList(GenViewType.INPUT, GenViewType.SELECT)); + } else if (dataType == GenDataType.BIG_DECIMAL) { + results.addAll(Arrays.asList(GenViewType.INPUT)); + } else { + log.error("未知的GenDataType={}", dataType); + throw new DefaultSysException("未知的GenDataType"); + } + + return results; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/directives/FormatDirective.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/directives/FormatDirective.java new file mode 100644 index 0000000..78d30ca --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/directives/FormatDirective.java @@ -0,0 +1,117 @@ +package com.lframework.xingyun.template.gen.directives; + +import com.lframework.starter.common.utils.CollectionUtil; +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class FormatDirective implements TemplateDirectiveModel { + + public static final String DIRECTIVE_NAME = "format"; + + private static final char NEWLINE = '\n'; + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, + TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + + FormatWriter writer = new FormatWriter(env.getOut(), + env.getCurrentDirectiveCallPlace().getBeginColumn()); + body.render(writer); + + List chars = writer.getWriteChars(); + char[] space = writer.getSpace(); + + if (!CollectionUtil.isEmpty(chars)) { + List checkList = chars.subList(chars.size() - space.length, chars.size()); + if (checkList.stream().allMatch(t -> t == ' ')) { + chars = chars.subList(0, chars.size() - space.length); + } + + char[] newChars = new char[chars.size()]; + for (int i = 0; i < chars.size(); i++) { + newChars[i] = chars.get(i); + } + env.getOut().write(newChars); + } + } + + private static class FormatWriter extends Writer { + + private final Writer out; + + private final char[] space; + private final List writeChars = new ArrayList<>(); + private boolean newLine = true; + + public FormatWriter(Writer out, int column) { + + this.out = out; + this.space = new char[column]; + Arrays.fill(this.space, ' '); + } + + public char[] getSpace() { + + return space; + } + + public List getWriteChars() { + + return writeChars; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + + List chars = new ArrayList<>(); + for (int i = off; i < len; i++) { + char c = cbuf[i]; + if (newLine) { + for (char s : space) { + chars.add(s); + } + newLine = false; + } + + if (c == NEWLINE) { + newLine = true; + } + + chars.add(c); + + if (newLine) { + for (char s : space) { + chars.add(s); + } + newLine = false; + } + } + + writeChars.addAll(chars); + } + + @Override + public void flush() throws IOException { + + out.flush(); + } + + @Override + public void close() throws IOException { + + out.close(); + } + + } + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/DataEntityGenerateDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/DataEntityGenerateDto.java new file mode 100644 index 0000000..546c17b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/DataEntityGenerateDto.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.template.gen.dto.data.entity; + +import com.lframework.xingyun.template.gen.dto.gen.GenCreateColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenDetailColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.gen.dto.gen.GenQueryColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenQueryParamsColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenUpdateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class DataEntityGenerateDto implements BaseDto, Serializable { + + /** + * 字段信息 + */ + private List columns; + + /** + * 基本设置 + */ + private GenGenerateInfoDto generateInfo; + + /** + * 新增配置 + */ + private List createConfigs; + + /** + * 修改配置 + */ + private List updateConfigs; + + /** + * 查询配置 + */ + private List queryConfigs; + + /** + * 查询参数配置 + */ + private List queryParamsConfigs; + + /** + * 详情配置 + */ + private List detailConfigs; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/GenDataEntityDetailDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/GenDataEntityDetailDto.java new file mode 100644 index 0000000..76b22a5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/data/entity/GenDataEntityDetailDto.java @@ -0,0 +1,84 @@ +package com.lframework.xingyun.template.gen.dto.data.entity; + +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenOrderType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenDataEntityDetailDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 字段显示名称 + */ + private String name; + + /** + * 字段名称 + */ + private String columnName; + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 数据类型 + */ + private GenDataType dataType; + + /** + * 排序编号 + */ + private Integer columnOrder; + + /** + * 备注 + */ + private String description; + + /** + * 显示类型 + */ + private GenViewType viewType; + + /** + * 是否内置枚举 + */ + private Boolean fixEnum = Boolean.FALSE; + + /** + * 后端枚举名 + */ + private String enumBack; + + /** + * 前端枚举名 + */ + private String enumFront; + + /** + * 正则表达式 + */ + private String regularExpression; + + /** + * 是否排序字段 + */ + private Boolean isOrder = Boolean.FALSE; + + /** + * 排序类型 + */ + private GenOrderType orderType; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenCreateColumnConfigDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenCreateColumnConfigDto.java new file mode 100644 index 0000000..661e151 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenCreateColumnConfigDto.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.dto.gen; + +import com.lframework.xingyun.template.gen.components.CreateColumnConfig; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenCreateColumnConfigDto implements BaseDto, CreateColumnConfig, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenDetailColumnConfigDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenDetailColumnConfigDto.java new file mode 100644 index 0000000..28681ab --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenDetailColumnConfigDto.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.dto.gen; + +import com.lframework.xingyun.template.gen.components.DetailColumnConfig; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenDetailColumnConfigDto implements BaseDto, DetailColumnConfig, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 列宽 + */ + private Integer span; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenGenerateInfoDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenGenerateInfoDto.java new file mode 100644 index 0000000..a513c7a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenGenerateInfoDto.java @@ -0,0 +1,88 @@ +package com.lframework.xingyun.template.gen.dto.gen; + +import com.lframework.xingyun.template.gen.enums.GenKeyType; +import com.lframework.xingyun.template.gen.enums.GenTemplateType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenGenerateInfoDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 生成模板类型 + */ + private GenTemplateType templateType; + + /** + * 包名 + */ + private String packageName; + + /** + * 模块名 + */ + private String moduleName; + + /** + * 业务名 + */ + private String bizName; + + /** + * 类名 + */ + private String className; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 父级菜单ID + */ + private String parentMenuId; + + /** + * 主键类型 + */ + private GenKeyType keyType; + + /** + * 作者 + */ + private String author; + + /** + * 本级菜单编号 + */ + private String menuCode; + + /** + * 本级菜单名称 + */ + private String menuName; + + /** + * 详情页Span总数量 + */ + private Integer detailSpan; + + /** + * 是否应用缓存 + */ + private Boolean isCache; + + /** + * 是否内置删除功能 + */ + private Boolean hasDelete; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryColumnConfigDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryColumnConfigDto.java new file mode 100644 index 0000000..5378571 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryColumnConfigDto.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.dto.gen; + +import com.lframework.xingyun.template.gen.components.QueryColumnConfig; +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenQueryColumnConfigDto implements BaseDto, QueryColumnConfig, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 宽度类型 + */ + private GenQueryWidthType widthType; + + /** + * 宽度 + */ + private Integer width; + + /** + * 是否页面排序 + */ + private Boolean sortable; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryParamsColumnConfigDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryParamsColumnConfigDto.java new file mode 100644 index 0000000..5bc65e3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenQueryParamsColumnConfigDto.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.dto.gen; + +import com.lframework.xingyun.template.gen.components.QueryParamsColumnConfig; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenQueryParamsColumnConfigDto implements BaseDto, QueryParamsColumnConfig, + Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 查询类型 + */ + private GenQueryType queryType; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenUpdateColumnConfigDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenUpdateColumnConfigDto.java new file mode 100644 index 0000000..68abfa2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/gen/GenUpdateColumnConfigDto.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.dto.gen; + +import com.lframework.xingyun.template.gen.components.UpdateColumnConfig; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenUpdateColumnConfigDto implements BaseDto, UpdateColumnConfig, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/generate/GenerateDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/generate/GenerateDto.java new file mode 100644 index 0000000..be7b3c4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/generate/GenerateDto.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.template.gen.dto.generate; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class GenerateDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 文件路径 + */ + private String path; + + /** + * 文件名 + */ + private String fileName; + + /** + * 文件内容 + */ + private String content; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableColumnDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableColumnDto.java new file mode 100644 index 0000000..aded388 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableColumnDto.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.template.gen.dto.simpledb; + +import com.lframework.xingyun.template.gen.enums.GenMySqlDataType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class OriSimpleTableColumnDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 表ID + */ + private String tableId; + + /** + * 字段名 + */ + private String columnName; + + /** + * 字段数据类型 + */ + private GenMySqlDataType dataType; + + /** + * 是否允许为空 + */ + private Boolean isNullable; + + /** + * 列主键类型 + */ + private Boolean isKey; + + /** + * 默认值 + */ + private String columnDefault; + + /** + * 字段排序 + */ + private Integer ordinalPosition; + + /** + * 字段类型 + */ + private String columnType; + + /** + * 字段备注 + */ + private String columnComment; + + /** + * 长度 + */ + private Long len; + + /** + * 小数位数 + */ + private Integer decimals; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableDto.java new file mode 100644 index 0000000..d3ad6d3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/OriSimpleTableDto.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.template.gen.dto.simpledb; + +import com.lframework.xingyun.template.gen.components.Table; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class OriSimpleTableDto implements BaseDto, Table, Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 数据表所属的数据库名 + */ + private String tableSchema; + + /** + * 数据库表名 + */ + private String tableName; + + /** + * 字段信息 + */ + private List columns; + + /** + * 数据库引擎 + */ + private String engine; + + /** + * 字符校验编码集 + */ + private String tableCollation; + + /** + * 备注 + */ + private String tableComment; + + /** + * 转换方式 + */ + private GenConvertType convertType; + + @Override + public String getSchema() { + + return this.tableSchema; + } + + @Override + public String getComment() { + + return this.tableComment; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleDBDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleDBDto.java new file mode 100644 index 0000000..6f27387 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleDBDto.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.template.gen.dto.simpledb; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SimpleDBDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 库名 + */ + private String tableSchema; + + /** + * 表名 + */ + private String tableName; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleTableDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleTableDto.java new file mode 100644 index 0000000..0f1015e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/dto/simpledb/SimpleTableDto.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.template.gen.dto.simpledb; + +import com.lframework.xingyun.template.gen.components.Table; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class SimpleTableDto implements BaseDto, Table, Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 数据表所属的数据库名 + */ + private String tableSchema; + + /** + * 数据库表名 + */ + private String tableName; + + /** + * 字段信息 + */ + private List columns; + + /** + * 数据库引擎 + */ + private String engine; + + /** + * 字符校验编码集 + */ + private String tableCollation; + + /** + * 备注 + */ + private String tableComment; + + /** + * 转换方式 + */ + private GenConvertType convertType; + + @Override + public String getSchema() { + + return this.tableSchema; + } + + @Override + public String getComment() { + + return this.tableComment; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCreateColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCreateColumnConfig.java new file mode 100644 index 0000000..705b6c6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCreateColumnConfig.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_create_column_config") +public class GenCreateColumnConfig extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomList.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomList.java new file mode 100644 index 0000000..882e3fc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomList.java @@ -0,0 +1,168 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenCustomListType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 自定义列表 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_custom_list") +public class GenCustomList extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "GenCustomList"; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 数据对象ID + */ + private String dataObjId; + + /** + * 列表类型 + */ + private GenCustomListType listType; + + /** + * 表单Label宽度 + */ + private Integer labelWidth; + + /** + * 是否分页 + */ + private Boolean hasPage; + + /** + * 是否树形列表 + */ + private Boolean treeData; + + /** + * ID字段 + */ + private String idColumn; + + /** + * ID字段关联ID + */ + private String idColumnRelaId; + + /** + * 父级ID字段 + */ + private String treePidColumn; + + /** + * 父级ID字段关联ID + */ + private String treePidColumnRelaId; + + /** + * 树形节点字段 + */ + private String treeNodeColumn; + + /** + * 树形节点字段关联ID + */ + private String treeNodeColumnRelaId; + + /** + * 子节点Key值 + */ + private String treeChildrenKey; + + /** + * 是否允许导出 + */ + private Boolean allowExport; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 查询前置SQL + */ + private String queryPrefixSql; + + /** + * 查询后置SQL + */ + private String querySuffixSql; + + /** + * 后置SQL + */ + private String suffixSql; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListCategory.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListCategory.java new file mode 100644 index 0000000..a2a7bff --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListCategory.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 自定义列表分类 + *

+ * + * @author zmj + */ +@Data +@TableName("gen_custom_list_category") +public class GenCustomListCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomListCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListDetail.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListDetail.java new file mode 100644 index 0000000..0c69d96 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListDetail.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_custom_list_detail") +public class GenCustomListDetail extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 自定义列表ID + */ + private String customListId; + + /** + * 关联ID 当type为主表时,此值为数据对象ID 当type为子表时,此值为数据对象明细ID 当type为自定义查询时,此值为GenDataObjQueryDetail的ID + */ + private String relaId; + + /** + * 数据实体ID + */ + private String dataEntityId; + + /** + * 宽度类型 + */ + private GenQueryWidthType widthType; + + /** + * 宽度 + */ + private Integer width; + + /** + * 是否页面排序 + */ + private Boolean sortable; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 类型 + */ + private GenCustomListDetailType type; + + /** + * 格式化脚本 + */ + private String formatter; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListHandleColumn.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListHandleColumn.java new file mode 100644 index 0000000..89c806f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListHandleColumn.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnType; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnViewType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * 自定义列表操作列 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_custom_list_handle_column") +public class GenCustomListHandleColumn extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomListHandleColumn"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 自定义列表ID + */ + private String customListId; + + /** + * 显示名称 + */ + private String name; + + /** + * 显示类型 + */ + private GenCustomListBtnViewType viewType; + + /** + * 按钮类型 + */ + private GenCustomListBtnType btnType; + + /** + * 按钮配置 + */ + private String btnConfig; + + /** + * 图标 + */ + private String icon; + + /** + * 请求参数 + */ + private String requestParam; + + /** + * 宽度 + */ + private Integer width; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListQueryParams.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListQueryParams.java new file mode 100644 index 0000000..8bc96c6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListQueryParams.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.starter.web.entity.BaseEntity; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_custom_list_query_params") +public class GenCustomListQueryParams extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 自定义列表ID + */ + private String customListId; + + /** + * 关联ID 当type为主表时,此值为数据对象ID 当type为子表时,此值为数据对象明细ID + */ + private String relaId; + + /** + * 数据实体ID + */ + private String dataEntityId; + + /** + * 前端显示 + */ + private Boolean frontShow; + + /** + * 查询类型 + */ + private GenQueryType queryType; + + /** + * 表单宽度 + */ + private Integer formWidth; + + /** + * 默认值 + */ + private String defaultValue; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 类型 + */ + private GenCustomListDetailType type; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListToolbar.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListToolbar.java new file mode 100644 index 0000000..78b406d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomListToolbar.java @@ -0,0 +1,70 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnType; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnViewType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * 自定义列表工具栏 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_custom_list_toolbar") +public class GenCustomListToolbar extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomListToolbar"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 自定义列表ID + */ + private String customListId; + + /** + * 显示名称 + */ + private String name; + + /** + * 显示类型 + */ + private GenCustomListBtnViewType viewType; + + /** + * 按钮类型 + */ + private GenCustomListBtnType btnType; + + /** + * 按钮配置 + */ + private String btnConfig; + + /** + * 图标 + */ + private String icon; + + /** + * 请求参数 + */ + private String requestParam; + + /** + * 排序编号 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPage.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPage.java new file mode 100644 index 0000000..ed50a3f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPage.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 自定义页面 + *

+ * + * @author zmj + * @since 2023-06-20 + */ +@Data +@TableName("gen_custom_page") +public class GenCustomPage extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomPage"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 页面代码 + */ + private String pageCode; + + /** + * 脚本代码 + */ + private String scriptCode; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPageCategory.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPageCategory.java new file mode 100644 index 0000000..f3c35bb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomPageCategory.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 自定义页面分类 + *

+ * + * @author zmj + */ +@Data +@TableName("gen_custom_page_category") +public class GenCustomPageCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomPageCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 父级ID + */ + private String parentId; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelector.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelector.java new file mode 100644 index 0000000..35b2976 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelector.java @@ -0,0 +1,126 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 自定义选择器 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_custom_selector") +public class GenCustomSelector extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomSelector"; + + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 自定义列表ID + */ + private String customListId; + + /** + * 对话框标题 + */ + private String dialogTittle; + + /** + * 对话框宽度 + */ + private String dialogWidth; + + /** + * 占位符 + */ + private String placeholder; + + /** + * ID字段 + */ + private String idColumn; + + /** + * ID字段关联ID + */ + private String idColumnRelaId; + + /** + * 名称字段 + */ + private String nameColumn; + + /** + * 名称字段关联ID + */ + private String nameColumnRelaId; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelectorCategory.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelectorCategory.java new file mode 100644 index 0000000..c29f3d4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenCustomSelectorCategory.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 自定义选择器分类 + *

+ * + * @author zmj + */ +@Data +@TableName("gen_custom_selector_category") +public class GenCustomSelectorCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenCustomSelectorCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntity.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntity.java new file mode 100644 index 0000000..702989e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntity.java @@ -0,0 +1,135 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.components.Table; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.xingyun.template.gen.enums.GenStatus; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据实体 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +@Data +@TableName("gen_data_entity") +public class GenDataEntity extends BaseEntity implements BaseDto, Table { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "GenDataEntity"; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 生成状态 + */ + private GenStatus genStatus; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 数据表所属的数据库名 + */ + private String tableSchema; + + /** + * 数据库表名 + */ + private String tableName; + + /** + * 数据库引擎 + */ + private String engine; + + /** + * 字符校验编码集 + */ + private String tableCollation; + + /** + * 备注 + */ + private String tableComment; + + /** + * 转换方式 + */ + private GenConvertType convertType; + + @Override + public String getSchema() { + return this.tableSchema; + } + + @Override + public String getComment() { + return this.tableComment; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityCategory.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityCategory.java new file mode 100644 index 0000000..bce1d58 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityCategory.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据实体分类 + *

+ * + * @author zmj + */ +@Data +@TableName("gen_data_entity_category") +public class GenDataEntityCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenDataEntityCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityDetail.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityDetail.java new file mode 100644 index 0000000..2276e03 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataEntityDetail.java @@ -0,0 +1,160 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.components.TableColumn; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenOrderType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * 数据实体明细 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +@Data +@TableName("gen_data_entity_detail") +public class GenDataEntityDetail extends BaseEntity implements BaseDto, TableColumn { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 数据对象ID + */ + private String entityId; + + /** + * 字段显示名称 + */ + private String name; + + /** + * 字段名称 + */ + private String columnName; + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 数据类型 + */ + private GenDataType dataType; + + /** + * 排序编号 + */ + private Integer columnOrder; + + /** + * 备注 + */ + private String description; + + /** + * 显示类型 + */ + private GenViewType viewType; + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 后端枚举名 + */ + private String enumBack; + + /** + * 前端枚举名 + */ + private String enumFront; + + /** + * 正则表达式 + */ + private String regularExpression; + + /** + * 是否排序字段 + */ + private Boolean isOrder; + + /** + * 排序类型 + */ + private GenOrderType orderType; + + /** + * 数据字典ID + */ + private String dataDicId; + + /** + * 自定义选择器ID + */ + private String customSelectorId; + + /** + * 长度 + */ + private Long len; + + /** + * 小数位数 + */ + private Integer decimals; + + /** + * 字段名称 + */ + private String dbColumnName; + + /** + * 字段数据类型 + */ + private GenDataType dbDataType; + + /** + * 是否允许为空 + */ + private Boolean isNullable; + + /** + * 默认值 + */ + private String columnDefault; + + /** + * 字段排序 + */ + private Integer ordinalPosition; + + /** + * 字段备注 + */ + private String columnComment; + + /** + * 长度 + */ + private Long dbLen; + + /** + * 小数位数 + */ + private Integer dbDecimals; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObj.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObj.java new file mode 100644 index 0000000..1655d88 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObj.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据对象 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_data_obj") +public class GenDataObj extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "GenDataObj"; + + /** + * ID + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 主表ID + */ + private String mainTableId; + + /** + * 主表别名 + */ + private String mainTableAlias; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjCategory.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjCategory.java new file mode 100644 index 0000000..8efe884 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjCategory.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据对象分类 + *

+ * + * @author zmj + */ +@Data +@TableName("gen_data_obj_category") +public class GenDataObjCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "GenDataObjCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjDetail.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjDetail.java new file mode 100644 index 0000000..4110ee1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjDetail.java @@ -0,0 +1,70 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenRelaMode; +import com.lframework.xingyun.template.gen.enums.GenRelaType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * 数据对象明细 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_data_obj_detail") +public class GenDataObjDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "GenDataObjDetail"; + + /** + * ID + */ + private String id; + + /** + * 数据对象ID + */ + private String dataObjId; + + /** + * 主表字段 + */ + private String mainTableDetailIds; + + /** + * 关联类型 + */ + private GenRelaType relaType; + + /** + * 关联方式 + */ + private GenRelaMode relaMode; + + /** + * 子表ID + */ + private String subTableId; + + /** + * 子表别名 + */ + private String subTableAlias; + + /** + * 主表字段 + */ + private String subTableDetailIds; + + /** + * 排序 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjQueryDetail.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjQueryDetail.java new file mode 100644 index 0000000..0e4e46b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDataObjQueryDetail.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * 数据对象自定义查询明细 + *

+ * + * @author zmj + * @since 2022-09-24 + */ +@Data +@TableName("gen_data_obj_query_detail") +public class GenDataObjQueryDetail extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "GenDataObjQueryDetail"; + + /** + * ID + */ + private String id; + + /** + * 数据对象ID + */ + private String dataObjId; + + /** + * 显示名称 + */ + private String customName; + + /** + * 自定义SQL + */ + private String customSql; + + /** + * 别名 + */ + private String customAlias; + + /** + * 数据类型 + */ + private GenDataType dataType; + + /** + * 排序 + */ + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDetailColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDetailColumnConfig.java new file mode 100644 index 0000000..260a8a9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenDetailColumnConfig.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_detail_column_config") +public class GenDetailColumnConfig extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 列宽 + */ + private Integer span; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenGenerateInfo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenGenerateInfo.java new file mode 100644 index 0000000..c9ec41c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenGenerateInfo.java @@ -0,0 +1,98 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenKeyType; +import com.lframework.xingyun.template.gen.enums.GenTemplateType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-08 + */ +@Data +@TableName("gen_generate_info") +public class GenGenerateInfo extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 生成模板类型 + */ + private GenTemplateType templateType; + + /** + * 包名 + */ + private String packageName; + + /** + * 模块名 + */ + private String moduleName; + + /** + * 业务名 + */ + private String bizName; + + /** + * 类名 + */ + private String className; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 父级菜单ID + */ + private String parentMenuId; + + /** + * 主键类型 + */ + private GenKeyType keyType; + + /** + * 作者 + */ + private String author; + + /** + * 本级菜单编号 + */ + private String menuCode; + + /** + * 本级菜单名称 + */ + private String menuName; + + /** + * 详情页Span总数量 + */ + private Integer detailSpan; + + /** + * 是否应用缓存 + */ + private Boolean isCache; + + /** + * 是否内置删除功能 + */ + private Boolean hasDelete; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryColumnConfig.java new file mode 100644 index 0000000..1395f7c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryColumnConfig.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_query_column_config") +public class GenQueryColumnConfig extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 宽度类型 + */ + private GenQueryWidthType widthType; + + /** + * 宽度 + */ + private Integer width; + + /** + * 是否页面排序 + */ + private Boolean sortable; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryParamsColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryParamsColumnConfig.java new file mode 100644 index 0000000..eb9cc76 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenQueryParamsColumnConfig.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_query_params_column_config") +public class GenQueryParamsColumnConfig extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 查询类型 + */ + private GenQueryType queryType; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTable.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTable.java new file mode 100644 index 0000000..f278819 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTable.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-05-28 + */ +@Data +@TableName("gen_simple_table") +public class GenSimpleTable extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 数据表所属的数据库名 + */ + private String tableSchema; + + /** + * 数据库表名 + */ + private String tableName; + + /** + * 数据库引擎 + */ + private String engine; + + /** + * 字符校验编码集 + */ + private String tableCollation; + + /** + * 备注 + */ + private String tableComment; + + /** + * 转换方式 + */ + private GenConvertType convertType; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTableColumn.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTableColumn.java new file mode 100644 index 0000000..65731b4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenSimpleTableColumn.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.xingyun.template.gen.components.TableColumn; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-05-28 + */ +@Data +@TableName("gen_simple_table_column") +public class GenSimpleTableColumn extends BaseEntity implements BaseDto, TableColumn { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 表ID + */ + private String tableId; + + /** + * 字段名 + */ + private String columnName; + + /** + * 字段数据类型 + */ + private GenDataType dataType; + + /** + * 是否允许为空 + */ + private Boolean isNullable; + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 默认值 + */ + private String columnDefault; + + /** + * 字段排序 + */ + private Integer ordinalPosition; + + /** + * 字段备注 + */ + private String columnComment; + + /** + * 长度 + */ + private Long len; + + /** + * 小数位数 + */ + private Integer decimals; + + @Override + public String getDbColumnName() { + return this.columnName; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenUpdateColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenUpdateColumnConfig.java new file mode 100644 index 0000000..e9a3d6f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenUpdateColumnConfig.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-12-10 + */ +@Data +@TableName("gen_update_column_config") +public class GenUpdateColumnConfig extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 排序编号 + */ + private Integer orderNo; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateColumnConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateColumnConfig.java new file mode 100644 index 0000000..0f808f3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateColumnConfig.java @@ -0,0 +1,5 @@ +package com.lframework.xingyun.template.gen.entity; + +public class GenerateColumnConfig { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateConfig.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateConfig.java new file mode 100644 index 0000000..bc73389 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/entity/GenerateConfig.java @@ -0,0 +1,13 @@ +package com.lframework.xingyun.template.gen.entity; + +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + * 代码生成信息 + */ +@Data +public class GenerateConfig extends BaseEntity implements BaseDto { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenConvertType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenConvertType.java new file mode 100644 index 0000000..c14385c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenConvertType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenConvertType implements BaseEnum { + UNDERLINE_TO_CAMEL(1, "下划线转驼峰"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenConvertType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnType.java new file mode 100644 index 0000000..d9de35d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnType.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenCustomListBtnType implements BaseEnum { + + EXTERNAL(0, "外部链接"), + ROUTE(1, "路由跳转"), + EXCUTE_SCRIPT(3, "自定义表单"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenCustomListBtnType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnViewType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnViewType.java new file mode 100644 index 0000000..6bc8a84 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListBtnViewType.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenCustomListBtnViewType implements BaseEnum { + + PRIMARY("primary", "primary"), + DEFAULT("default", "default"), + DASHED("dashed", "dashed"), + DANGER("danger", "danger"), + LINK("link", "link"), + LINK_DANGER("link-danger", "link-danger"); + + @EnumValue + private final String code; + + private final String desc; + + GenCustomListBtnViewType(String code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListDetailType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListDetailType.java new file mode 100644 index 0000000..7fc4a6c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListDetailType.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenCustomListDetailType implements BaseEnum { + MAIN_TABLE(1, "主表"), + SUB_TALBE(2, "子表"), + CUSTOM(3, "自定义查询"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenCustomListDetailType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListType.java new file mode 100644 index 0000000..d1962e6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenCustomListType.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenCustomListType implements BaseEnum { + SEQ(0, "序列"), + SINGLE(1, "单选"), + MULTIPLE(2, "多选"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenCustomListType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenDataType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenDataType.java new file mode 100644 index 0000000..ec3fa81 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenDataType.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +public enum GenDataType implements BaseEnum { + + STRING(0, String.class, "String", "string"), INTEGER(1, Integer.class, "Integer", + "number"), SHORT(2, Short.class, "Short", "number"), LONG(3, Long.class, "Long", "number"), DOUBLE(4, + Double.class, "Double", "number"), LOCAL_DATE(5, LocalDate.class, "LocalDate", "string"), LOCAL_DATE_TIME(6, + LocalDateTime.class, "LocalDateTime", "string"), LOCAL_TIME(7, + LocalTime.class, "LocalTime", "string"), BOOLEAN(8, Boolean.class, "Boolean", "boolean"), BIG_DECIMAL(9, + BigDecimal.class, "BigDecimal", "number"), + ; + + @EnumValue + private final Integer code; + + private final Class clazz; + + private final String desc; + + private final String frontDesc; + + GenDataType(Integer code, Class clazz, String desc, String frontDesc) { + + this.code = code; + this.clazz = clazz; + this.desc = desc; + this.frontDesc = frontDesc; + } + + /** + * 是否是数字类型 + * + * @param type + * @return + */ + public static Boolean isNumberType(GenDataType type) { + + if (type == null) { + return false; + } + + return type == INTEGER || type == SHORT || type == LONG || type == DOUBLE + || type == BIG_DECIMAL; + } + + /** + * 是否是小数类型 + * + * @param type + * @return + */ + public static Boolean isDecimalType(GenDataType type) { + if (type == null) { + return false; + } + + return type == DOUBLE || type == BIG_DECIMAL; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public Class getClazz() { + return clazz; + } + + public String getFrontDesc() { + return frontDesc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenKeyType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenKeyType.java new file mode 100644 index 0000000..68c8de4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenKeyType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenKeyType implements BaseEnum { + AUTO(0, "自增ID"), UUID(1, "UUID"), SNOW_FLAKE(2, "雪花算法ID"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenKeyType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenMySqlDataType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenMySqlDataType.java new file mode 100644 index 0000000..da1e85c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenMySqlDataType.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +/** + * MySql列类型枚举 dataType为null时表示该类型暂不支持 + */ +public enum GenMySqlDataType implements BaseEnum { + TINYINT("tinyint", GenDataType.INTEGER, "tinyint"), SMALLINT("smallint", GenDataType.INTEGER, + "smallint"), MEDIUMINT("mediumint", GenDataType.INTEGER, "mediumint"), INT("int", + GenDataType.INTEGER, + "int"), INTEGER("integer", GenDataType.INTEGER, "integer"), BIGINT("bigint", GenDataType.LONG, + "bigint"), BIT("bit", GenDataType.BOOLEAN, "bit"), REAL("real", GenDataType.DOUBLE, + "real"), DOUBLE( + "double", GenDataType.BIG_DECIMAL, "double"), FLOAT("float", GenDataType.BIG_DECIMAL, + "float"), DECIMAL( + "decimal", GenDataType.BIG_DECIMAL, "decimal"), NUMERIC("numeric", GenDataType.BIG_DECIMAL, + "numeric"), CHAR("char", GenDataType.STRING, "char"), VARCHAR("varchar", GenDataType.STRING, + "varchar"), DATE("date", GenDataType.LOCAL_DATE, "date"), TIME("time", GenDataType.LOCAL_TIME, + "time"), YEAR("year", null, "year"), TIMESTAMP("timestamp", GenDataType.LOCAL_DATE_TIME, + "timestamp"), DATETIME("datetime", GenDataType.LOCAL_DATE_TIME, "datetime"), TINYBLOB( + "tinyblob", null, + "tinyblob"), BLOB("blob", null, "blob"), MEDIUMBLOB("mediumblob", null, + "mediumblob"), LONGBLOB("longblob", + null, "longblob"), TINYTEXT("tinytext", GenDataType.STRING, "tinytext"), MEDIUMTEXT( + "mediumtext", + GenDataType.STRING, "mediumtext"), TEXT("text", GenDataType.STRING, "text"), LONGTEXT( + "longtext", + GenDataType.STRING, "longtext"), ENUM("enum", GenDataType.STRING, "enum"), SET("set", + GenDataType.STRING, + "set"), BINARY("binary", null, "binary"), VARBINARY("varbinary", null, "varbinary"), POINT( + "point", null, + "point"), LINESTRING("linestring", null, "linestring"), POLYGON("polygon", null, + "polygon"), GEOMETRY( + "geometry", null, "geometry"), MULTIPOINT("multipoint", null, "multipoint"), MULTILINESTRING( + "multilinestring", null, "multilinestring"), MULTIPOLYGON("multipolygon", null, + "multipolygon"), GEOMETRYCOLLECTION("geometrycollection", null, "geometrycollection"), JSON( + "json", null, + "json"); + + @EnumValue + private final String code; + + private final GenDataType dataType; + + private final String desc; + + GenMySqlDataType(String code, GenDataType dataType, String desc) { + + this.code = code; + this.dataType = dataType; + this.desc = desc; + } + + @Override + public String getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public GenDataType getDataType() { + + return dataType; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenOrderType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenOrderType.java new file mode 100644 index 0000000..e49afe2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenOrderType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenOrderType implements BaseEnum { + ASC("ASC", "升序"), DESC("DESC", "降序"); + + @EnumValue + private final String code; + + private final String desc; + + GenOrderType(String code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryType.java new file mode 100644 index 0000000..893ba4d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryType.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenQueryType implements BaseEnum { + EQ(0, "=", "="), GT(1, ">", ">"), GE(2, ">=", ">="), LT(3, "<", "<"), LE(4, "<=", "<="), NE(5, "!=", "!="), IN(6, "IN", "IN"), NOT_IN(7, + "NOT IN", "NOT IN"), LEFT_LIKE(8, "LIKE", "LIKE %?"), RIGHT_LIKE(9, "LIKE", "LIKE ?%"), AROUND_LIKE(10, "LIKE", "LIKE %?%"); + + @EnumValue + private final Integer code; + + private final String operation; + + private final String desc; + + GenQueryType(Integer code, String operation, String desc) { + + this.code = code; + this.operation = operation; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } + + public String getOperation() { + return operation; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryWidthType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryWidthType.java new file mode 100644 index 0000000..78d86a5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenQueryWidthType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenQueryWidthType implements BaseEnum { + FIX(0, "固定宽度"), MIN(1, "最小宽度"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenQueryWidthType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaMode.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaMode.java new file mode 100644 index 0000000..9b5374e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaMode.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenRelaMode implements BaseEnum { + LEFT_JOIN(0, "LEFT", "左连接"), + RIGHT_JOIN(1, "RIGHT", "右连接"), + INNER_JOIN(2, "INNER", "全连接"); + + @EnumValue + private final Integer code; + + private final String sql; + + private final String desc; + + GenRelaMode(Integer code, String sql, String desc) { + this.code = code; + this.sql = sql; + this.desc = desc; + } + + @Override + public Integer getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } + + public String getSql() { + return sql; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaType.java new file mode 100644 index 0000000..2ab7a79 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenRelaType.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenRelaType implements BaseEnum { + ONE_RELA_ONE(0, "一对一"), + ONE_RELA_MANY(1, "一对多"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenRelaType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenStatus.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenStatus.java new file mode 100644 index 0000000..a5cad86 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenStatus.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenStatus implements BaseEnum { + CREATED(0, "已生成"), SET_TABLE(1, "已设置数据表"), SET_GEN(2, "已设置生成配置"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenStatus(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenTemplateType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenTemplateType.java new file mode 100644 index 0000000..bf0584d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenTemplateType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenTemplateType implements BaseEnum { + LIST(1, "列表"), TREE(2, "树形表"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenTemplateType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenType.java new file mode 100644 index 0000000..3798efd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenType.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenType implements BaseEnum { + SIMPLE_DB(1, "数据库单表"); + + @EnumValue + private final Integer code; + + private final String desc; + + GenType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenViewType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenViewType.java new file mode 100644 index 0000000..a9fdefc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/enums/GenViewType.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum GenViewType implements BaseEnum { + INPUT(0, "输入框"), TEXTATREA(1, "文本域"), DATETIME(2, "日期时间选择器"), DATE(3, "日期选择器"), TIME(4, + "时间选择器"), SELECT(5, + "选择器"), DATE_RANGE(6, "日期范围选择器"), DATA_DIC(7, "数据字典"), CUSTOM_SELECTOR(8, "自定义选择器"); + + @EnumValue + private final Integer code; + + + private final String desc; + + GenViewType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/CustomListDeleteEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/CustomListDeleteEvent.java new file mode 100644 index 0000000..e5f7f66 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/CustomListDeleteEvent.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.template.gen.events; + +import org.springframework.context.ApplicationEvent; + +public class CustomListDeleteEvent extends ApplicationEvent { + + /** + * 自定义列表ID + */ + private String id; + + /** + * 自定义列表名称 + */ + private String name; + + public CustomListDeleteEvent(Object source) { + super(source); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDeleteEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDeleteEvent.java new file mode 100644 index 0000000..0225e3c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDeleteEvent.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.template.gen.events; + +import java.util.List; +import org.springframework.context.ApplicationEvent; + +public class DataEntityDeleteEvent extends ApplicationEvent { + + /** + * 数据实体ID + */ + private String id; + + /** + * 数据实体名称 + */ + private String name; + + private List columnIds; + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public DataEntityDeleteEvent(Object source) { + + super(source); + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getColumnIds() { + + return columnIds; + } + + public void setColumnIds(List columnIds) { + + this.columnIds = columnIds; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDetailDeleteEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDetailDeleteEvent.java new file mode 100644 index 0000000..7225e1a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataEntityDetailDeleteEvent.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.template.gen.events; + +import org.springframework.context.ApplicationEvent; + +public class DataEntityDetailDeleteEvent extends ApplicationEvent { + + /** + * 数据实体明细ID + */ + private String id; + + /** + * 显示名称 + */ + private String name; + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public DataEntityDetailDeleteEvent(Object source) { + + super(source); + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjDeleteEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjDeleteEvent.java new file mode 100644 index 0000000..a6b3ce6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjDeleteEvent.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.gen.events; + +import java.util.List; +import org.springframework.context.ApplicationEvent; + +public class DataObjDeleteEvent extends ApplicationEvent { + + /** + * 数据对象ID + */ + private String id; + + /** + * 数据对象名称 + */ + private String name; + + private List detailIds; + + private List queryDetailIds; + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public DataObjDeleteEvent(Object source) { + super(source); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getDetailIds() { + return detailIds; + } + + public void setDetailIds(List detailIds) { + this.detailIds = detailIds; + } + + public List getQueryDetailIds() { + return queryDetailIds; + } + + public void setQueryDetailIds(List queryDetailIds) { + this.queryDetailIds = queryDetailIds; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjQueryDetailDeleteEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjQueryDetailDeleteEvent.java new file mode 100644 index 0000000..81be25c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/events/DataObjQueryDetailDeleteEvent.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.template.gen.events; + +import org.springframework.context.ApplicationEvent; + +public class DataObjQueryDetailDeleteEvent extends ApplicationEvent { + + /** + * 数据对象明细ID + */ + private String id; + + /** + * 显示名称 + */ + private String name; + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public DataObjQueryDetailDeleteEvent(Object source) { + + super(source); + } + + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/Generator.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/Generator.java new file mode 100644 index 0000000..34dfb3d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/Generator.java @@ -0,0 +1,1658 @@ +package com.lframework.xingyun.template.gen.generate; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.IsNumberPrecision; +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.constants.MyBatisStringPool; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.JsonUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.gen.builders.DataEntityBuilder; +import com.lframework.xingyun.template.gen.components.DataEntity; +import com.lframework.xingyun.template.gen.components.DataEntityColumn; +import com.lframework.xingyun.template.gen.directives.FormatDirective; +import com.lframework.xingyun.template.gen.dto.generate.GenerateDto; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenKeyType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import com.lframework.xingyun.template.gen.generate.templates.ControllerTemplate; +import com.lframework.xingyun.template.gen.generate.templates.CreateTemplate; +import com.lframework.xingyun.template.gen.generate.templates.DetailTemplate; +import com.lframework.xingyun.template.gen.generate.templates.EntityTemplate; +import com.lframework.xingyun.template.gen.generate.templates.MapperTemplate; +import com.lframework.xingyun.template.gen.generate.templates.QueryParamsTemplate; +import com.lframework.xingyun.template.gen.generate.templates.QueryTemplate; +import com.lframework.xingyun.template.gen.generate.templates.ServiceTemplate; +import com.lframework.xingyun.template.gen.generate.templates.SqlTemplate; +import com.lframework.xingyun.template.gen.generate.templates.UpdateTemplate; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.service.system.SysDataDicItemService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.TemplateHashModel; +import freemarker.template.TemplateModelException; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.validator.constraints.Length; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.DeleteMapping; + +@Slf4j +public class Generator { + + private DataEntity dataEntity; + + private Generator() { + + } + + public static Generator getInstance(String entityId) { + + DataEntityBuilder builder = ApplicationUtil.getBean(DataEntityBuilder.class); + Generator generator = new Generator(); + + generator.setDataEntity(builder.build(entityId)); + + return generator; + } + + private void setDataEntity(DataEntity dataEntity) { + + this.dataEntity = dataEntity; + } + + public List generateAll() { + + List results = new ArrayList<>(); + // Java代码 + GenerateDto entityJava = this.generateEntity(); + GenerateDto mapperJava = this.generateMapper(); + GenerateDto mapperXml = this.generateListMapperXml(); + GenerateDto queryVoJava = this.generateQueryVo(); + GenerateDto createVoJava = this.generateCreateVo(); + GenerateDto updateVoJava = this.generateUpdateVo(); + GenerateDto serviceJava = this.generateService(); + GenerateDto serviceImplJava = this.generateServiceImpl(); + GenerateDto queryBoJava = this.generateQueryBo(); + GenerateDto getBoJava = this.generateGetBo(); + GenerateDto controllerJava = this.generateController(); + + results.add(entityJava); + if (queryVoJava != null) { + results.add(queryVoJava); + } + results.add(mapperJava); + results.add(mapperXml); + if (createVoJava != null) { + results.add(createVoJava); + } + if (updateVoJava != null) { + results.add(updateVoJava); + } + results.add(serviceJava); + results.add(serviceImplJava); + if (queryBoJava != null) { + results.add(queryBoJava); + } + if (getBoJava != null) { + results.add(getBoJava); + } + results.add(controllerJava); + + // Vue代码 + GenerateDto apiJs = this.generateApiJs(); + GenerateDto indexVue = this.generateIndexVue(); + GenerateDto addVue = this.generateAddVue(); + GenerateDto modifyVue = this.generateModifyVue(); + GenerateDto detailVue = this.generateDetailVue(); + GenerateDto createVoVue = this.generateCreateVoVue(); + GenerateDto queryVoVue = this.generateQueryVoVue(); + GenerateDto updateVoVue = this.generateUpdateVoVue(); + GenerateDto queryBoVue = this.generateQueryBoVue(); + GenerateDto getBoVue = this.generateGetBoVue(); + + results.add(apiJs); + results.add(indexVue); + if (addVue != null) { + results.add(addVue); + } + if (modifyVue != null) { + results.add(modifyVue); + } + if (detailVue != null) { + results.add(detailVue); + } + if (createVoVue != null) { + results.add(createVoVue); + } + if (queryVoVue != null) { + results.add(queryVoVue); + } + if (updateVoVue != null) { + results.add(updateVoVue); + } + if (queryBoVue != null) { + results.add(queryBoVue); + } + if (getBoVue != null) { + results.add(getBoVue); + } + + // sql + GenerateDto sql = this.generateSql(); + results.add(sql); + + return results; + } + + /** + * 生成Entity.java代码 + * + * @return + */ + public GenerateDto generateEntity() { + + EntityTemplate template = this.getEntityTemplate(); + + String content = this.generate("entity.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "entity", template.getClassName() + ".java", content); + } + + /** + * 生成Mapper.java代码 + * + * @return + */ + public GenerateDto generateMapper() { + + MapperTemplate template = this.getMapperTemplate(); + + String content = this.generate("mapper.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "mappers", template.getClassName() + "Mapper.java", content); + } + + /** + * 生成Mapper.xml代码 + * + * @return + */ + public GenerateDto generateListMapperXml() { + + MapperTemplate template = this.getMapperTemplate(); + + String content = this.generate("mapper.list.xml.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "resources" + + File.separator + "mappers" + File.separator + template.getModuleName(), + template.getClassName() + "Mapper.xml", content); + } + + /** + * 生成QueryVo.java代码 + * + * @return + */ + public GenerateDto generateQueryVo() { + + QueryParamsTemplate template = this.getQueryParamsTemplate(); + if (template == null) { + return null; + } + + String content = this.generate("queryvo.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "vo" + + File.separator + template.getModuleName() + File.separator + template.getBizName(), + "Query" + template.getClassName() + "Vo.java", content); + } + + /** + * 生成Service.java代码 + * + * @return + */ + public GenerateDto generateService() { + + ServiceTemplate template = this.getServiceTemplate(); + + String content = this.generate("service.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "service" + File.separator + template.getModuleName(), + template.getClassName() + "Service.java", content); + } + + /** + * 生成ServiceImpl.java代码 + * + * @return + */ + public GenerateDto generateServiceImpl() { + + ServiceTemplate template = this.getServiceTemplate(); + + String content = this.generate("serviceimpl.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "impl" + + File.separator + template.getModuleName(), + template.getClassName() + "ServiceImpl.java", + content); + } + + /** + * 生成CreateVo.java代码 + * + * @return + */ + public GenerateDto generateCreateVo() { + + CreateTemplate template = this.getCreateTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("createvo.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "vo" + + File.separator + template.getModuleName() + File.separator + template.getBizName(), + "Create" + template.getClassName() + "Vo.java", content); + } + + /** + * 生成UpdateVo.java代码 + * + * @return + */ + public GenerateDto generateUpdateVo() { + + UpdateTemplate template = this.getUpdateTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("updatevo.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "vo" + + File.separator + template.getModuleName() + File.separator + template.getBizName(), + "Update" + template.getClassName() + "Vo.java", content); + } + + /** + * 生成QueryBo.java代码 + * + * @return + */ + public GenerateDto generateQueryBo() { + + QueryTemplate template = this.getQueryTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("querybo.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "bo" + + File.separator + template.getModuleName() + File.separator + template.getBizName(), + "Query" + template.getClassName() + "Bo.java", content); + } + + /** + * 生成GetBo.java代码 + * + * @return + */ + public GenerateDto generateGetBo() { + + DetailTemplate template = this.getDetailTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("getbo.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "bo" + + File.separator + template.getModuleName() + File.separator + template.getBizName(), + "Get" + template.getClassName() + "Bo.java", content); + } + + /** + * 生成Controller.java代码 + * + * @return + */ + public GenerateDto generateController() { + + ControllerTemplate template = this.getControllerTemplate(); + + String content = this.generate("controller.java.ftl", template); + + return this.buildGenerateResult( + "java" + File.separator + "src" + File.separator + "main" + File.separator + "java" + + File.separator + + template.getPackageName().replaceAll("\\.", "\\" + File.separator) + File.separator + + "controller" + File.separator + template.getModuleName(), + template.getClassName() + "Controller.java", content); + } + + /** + * 生成api.js代码 + * + * @return + */ + public GenerateDto generateApiJs() { + + ControllerTemplate template = this.getControllerTemplate(); + + String content = this.generate("api.ts.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "api" + File.separator + + template.getModuleName() + File.separator + template.getBizName(), "index.ts", + content); + } + + /** + * 生成index.vue代码 + * + * @return + */ + public GenerateDto generateIndexVue() { + + ControllerTemplate template = this.getControllerTemplate(); + String content = this.generate("index.vue.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "views" + File.separator + + template.getModuleName() + + File.separator + template.getBizName(), "index.vue", content); + } + + /** + * add.vue代码 + * + * @return + */ + public GenerateDto generateAddVue() { + + CreateTemplate template = this.getCreateTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("add.vue.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "views" + File.separator + + template.getModuleName() + + File.separator + template.getBizName(), "add.vue", content); + } + + /** + * modify.vue代码 + * + * @return + */ + public GenerateDto generateModifyVue() { + + UpdateTemplate template = this.getUpdateTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("modify.vue.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "views" + File.separator + + template.getModuleName() + + File.separator + template.getBizName(), "modify.vue", content); + } + + /** + * detail.vue代码 + * + * @return + */ + public GenerateDto generateDetailVue() { + + DetailTemplate template = this.getDetailTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("detail.vue.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "views" + File.separator + + template.getModuleName() + + File.separator + template.getBizName(), "detail.vue", content); + } + + /** + * detail.vue代码 + * + * @return + */ + public GenerateDto generateSql() { + + SqlTemplate template = this.getSqlTemplate(); + + String content = this.generate("sql.ftl", template); + + return this.buildGenerateResult(StringPool.EMPTY_STR, "sql.sql", content); + } + + /** + * 获取freeMarker Template + * + * @param templateName + * @return + */ + private Template getTemplate(String templateName) { + + Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); + cfg.setClassForTemplateLoading(Generator.class, "/templates"); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + cfg.setSharedVariable(FormatDirective.DIRECTIVE_NAME, new FormatDirective()); + try { + return cfg.getTemplate(templateName); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + } + + /** + * Entity.java模板数据 + * + * @return + */ + private EntityTemplate getEntityTemplate() { + + EntityTemplate entityTemplate = new EntityTemplate(); + entityTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + entityTemplate.setTableName(dataEntity.getTable().getTableName()); + entityTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + entityTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + entityTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + entityTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + entityTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + + Set importPackages = new HashSet<>(); + importPackages.add(BaseEntity.class.getName()); + importPackages.add(BaseDto.class.getName()); + List columns = new ArrayList<>(); + for (DataEntityColumn column : dataEntity.getColumns()) { + EntityTemplate.Column columnObj = new EntityTemplate.Column(); + columnObj.setIsKey(column.getIsKey()); + if (columnObj.getIsKey()) { + // 如果是主键,判断是否是自增主键 + columnObj.setAutoIncrKey(dataEntity.getGenerateInfo().getKeyType() == GenKeyType.AUTO); + if (columnObj.getAutoIncrKey()) { + importPackages.add(TableId.class.getName()); + importPackages.add(IdType.class.getName()); + } + } + if (column.getFixEnum()) { + // 如果是枚举类型 + columnObj.setDataType( + column.getEnumBack().substring(column.getEnumBack().lastIndexOf(".") + 1)); + columnObj.setFrontType(column.getEnumFront()); + importPackages.add(column.getEnumBack()); + } else { + columnObj.setDataType(column.getDataType().getDesc()); + } + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + columnObj.setName(column.getColumnName()); + // MybatisPlus默认命名规则是下划线转驼峰,所以如果不是这个规则的话,需要单独指定TableField和TableId + columnObj.setColumnName(column.getTableColumn().getDbColumnName()); + columnObj.setDefaultConvertType( + dataEntity.getTable().getConvertType() == GenConvertType.UNDERLINE_TO_CAMEL); + if (!columnObj.getDefaultConvertType()) { + importPackages.add(TableId.class.getName()); + importPackages.add(TableField.class.getName()); + } + columnObj.setDescription(column.getName()); + if (!columnObj.getIsKey()) { + // 如果不是主键,需要判断是否需要字段填充 + if (MyBatisStringPool.COLUMN_CREATE_BY.equals(columnObj.getName()) + || MyBatisStringPool.COLUMN_CREATE_BY_ID.equals(columnObj.getName()) + || MyBatisStringPool.COLUMN_CREATE_TIME.equals(columnObj.getName())) { + columnObj.setFill(Boolean.TRUE); + columnObj.setFillStrategy(FieldFill.INSERT.name()); + importPackages.add(TableField.class.getName()); + importPackages.add(FieldFill.class.getName()); + } else if (MyBatisStringPool.COLUMN_UPDATE_BY.equals(columnObj.getName()) + || MyBatisStringPool.COLUMN_UPDATE_BY_ID.equals(columnObj.getName()) + || MyBatisStringPool.COLUMN_UPDATE_TIME.equals(columnObj.getName())) { + columnObj.setFill(Boolean.TRUE); + columnObj.setFillStrategy(FieldFill.INSERT_UPDATE.name()); + importPackages.add(TableField.class.getName()); + importPackages.add(FieldFill.class.getName()); + } + } + + columns.add(columnObj); + } + entityTemplate.setColumns(columns); + + entityTemplate.setImportPackages(importPackages); + + return entityTemplate; + } + + /** + * 生成CreateVo.ts代码 + * + * @return + */ + public GenerateDto generateCreateVoVue() { + + CreateTemplate template = this.getCreateTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("createvo.ts.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "api" + File.separator + + template.getModuleName() + File.separator + template.getBizName() + File.separator + + "model", "create" + template.getClassName() + "Vo.ts", + content); + } + + /** + * 生成QueryVo.ts代码 + * + * @return + */ + public GenerateDto generateQueryVoVue() { + + QueryParamsTemplate template = this.getQueryParamsTemplate(); + if (template == null) { + return null; + } + + String content = this.generate("queryvo.ts.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "api" + File.separator + + template.getModuleName() + File.separator + template.getBizName() + File.separator + + "model", "query" + template.getClassName() + "Vo.ts", + content); + } + + /** + * 生成UpdateVo.ts代码 + * + * @return + */ + public GenerateDto generateUpdateVoVue() { + + UpdateTemplate template = this.getUpdateTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("updatevo.ts.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "api" + File.separator + + template.getModuleName() + File.separator + template.getBizName() + File.separator + + "model", "update" + template.getClassName() + "Vo.ts", + content); + } + + /** + * 生成QueryBo.ts代码 + * + * @return + */ + public GenerateDto generateQueryBoVue() { + + QueryTemplate template = this.getQueryTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("querybo.ts.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "api" + File.separator + + template.getModuleName() + File.separator + template.getBizName() + File.separator + + "model", "query" + template.getClassName() + "Bo.ts", + content); + } + + /** + * 生成GetBo.ts代码 + * + * @return + */ + public GenerateDto generateGetBoVue() { + + DetailTemplate template = this.getDetailTemplate(); + + if (template == null) { + return null; + } + + String content = this.generate("getbo.ts.ftl", template); + + return this.buildGenerateResult( + "vue" + File.separator + "src" + File.separator + "api" + File.separator + + template.getModuleName() + File.separator + template.getBizName() + File.separator + + "model", "get" + template.getClassName() + "Bo.ts", + content); + } + + /** + * Mapper.java模板数据 + * + * @return + */ + private MapperTemplate getMapperTemplate() { + + MapperTemplate mapperTemplate = new MapperTemplate(); + mapperTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + mapperTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + mapperTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + mapperTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + mapperTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + mapperTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + Set importPackages = new HashSet<>(); + importPackages.add(BaseMapper.class.getName()); + List keys = new ArrayList<>(); + for (DataEntityColumn column : dataEntity.getColumns()) { + if (column.getIsKey()) { + MapperTemplate.Key key = new MapperTemplate.Key(); + // 主键不允许是枚举,所以直接取desc + key.setDataType(column.getDataType().getDesc()); + key.setName(column.getColumnName()); + key.setColumnName(column.getTableColumn().getDbColumnName()); + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + keys.add(key); + } + } + + mapperTemplate.setKeys(keys); + List orderColumns = new ArrayList<>(); + for (DataEntityColumn column : dataEntity.getColumns()) { + if (!column.getIsOrder()) { + continue; + } + MapperTemplate.OrderColumn orderColumn = new MapperTemplate.OrderColumn(); + orderColumn.setColumnName(column.getTableColumn().getDbColumnName()); + orderColumn.setOrderType(column.getOrderType().getCode()); + orderColumns.add(orderColumn); + } + mapperTemplate.setOrderColumns(orderColumns); + mapperTemplate.setEntity(this.getEntityTemplate()); + mapperTemplate.setImportPackages(importPackages); + mapperTemplate.setQueryParams(this.getQueryParamsTemplate()); + if (mapperTemplate.getQueryParams() != null) { + mapperTemplate.getImportPackages() + .addAll(mapperTemplate.getQueryParams().getImportPackages()); + } + + return mapperTemplate; + } + + private ServiceTemplate getServiceTemplate() { + + ServiceTemplate serviceTemplate = new ServiceTemplate(); + serviceTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + serviceTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + serviceTemplate.setClassNameProperty( + dataEntity.getGenerateInfo().getClassName().substring(0, 1).toLowerCase() + + dataEntity.getGenerateInfo() + .getClassName().substring(1)); + serviceTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + serviceTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + serviceTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + serviceTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + serviceTemplate.setIsCache(dataEntity.getGenerateInfo().getIsCache()); + serviceTemplate.setHasDelete(dataEntity.getGenerateInfo().getHasDelete()); + Set importPackages = new HashSet<>(); + importPackages.add(PageResult.class.getName()); + importPackages.add(BaseMpService.class.getName()); + importPackages.add(StringUtil.class.getName()); + importPackages.add(BaseMpServiceImpl.class.getName()); + importPackages.add(DefaultClientException.class.getName()); + importPackages.add(Assert.class.getName()); + importPackages.add(ObjectUtil.class.getName()); + importPackages.add(OpLog.class.getName()); + importPackages.add(DefaultOpLogType.class.getName()); + importPackages.add(OpLogUtil.class.getName()); + importPackages.add(PageHelperUtil.class.getName()); + importPackages.add(PageResultUtil.class.getName()); + importPackages.add(EnumUtil.class.getName()); + if (serviceTemplate.getHasDelete()) { + importPackages.add(Transactional.class.getName()); + } + List keys = new ArrayList<>(); + for (DataEntityColumn column : dataEntity.getColumns()) { + if (column.getIsKey()) { + ServiceTemplate.Key key = new ServiceTemplate.Key(); + // 主键不允许是枚举,所以直接取desc + key.setDataType(column.getDataType().getDesc()); + key.setName(column.getColumnName()); + key.setNameProperty( + column.getColumnName().substring(0, 1).toUpperCase() + column.getColumnName() + .substring(1)); + key.setColumnName(column.getTableColumn().getDbColumnName()); + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + keys.add(key); + } + } + + serviceTemplate.setKeys(keys); + serviceTemplate.setImportPackages(importPackages); + serviceTemplate.setQueryParams(this.getQueryParamsTemplate()); + serviceTemplate.setCreate(this.getCreateTemplate()); + serviceTemplate.setUpdate(this.getUpdateTemplate()); + if (serviceTemplate.getIsCache()) { + importPackages.add(Serializable.class.getName()); + } + if (serviceTemplate.getQueryParams() != null) { + serviceTemplate.getImportPackages() + .addAll(serviceTemplate.getQueryParams().getImportPackages()); + } + if (serviceTemplate.getCreate() != null) { + serviceTemplate.getImportPackages().addAll(serviceTemplate.getCreate().getImportPackages()); + } + if (serviceTemplate.getUpdate() != null) { + serviceTemplate.getImportPackages().addAll(serviceTemplate.getUpdate().getImportPackages()); + } + + return serviceTemplate; + } + + private QueryParamsTemplate getQueryParamsTemplate() { + + List targetColumns = dataEntity.getColumns().stream() + .filter(t -> t.getQueryParamsConfig() != null) + .sorted(Comparator.comparing(t -> t.getQueryParamsConfig().getOrderNo())) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(targetColumns)) { + return null; + } + QueryParamsTemplate queryParamsTemplate = new QueryParamsTemplate(); + queryParamsTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + queryParamsTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + queryParamsTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + queryParamsTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + queryParamsTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + queryParamsTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + Set importPackages = new HashSet<>(); + importPackages.add(BaseVo.class.getName()); + importPackages.add(PageVo.class.getName()); + importPackages.add(TypeMismatch.class.getName()); + importPackages.add(ApiModelProperty.class.getName()); + List columns = new ArrayList<>(); + for (DataEntityColumn column : targetColumns) { + QueryParamsTemplate.Column columnObj = new QueryParamsTemplate.Column(); + if (column.getFixEnum()) { + // 如果是枚举类型 + columnObj.setDataType( + column.getEnumBack().substring(column.getEnumBack().lastIndexOf(".") + 1)); + columnObj.setFrontType(column.getEnumFront()); + columnObj.setFrontDataType("number"); + columnObj.setViewType(column.getViewType().getCode()); + columnObj.setEnumCodeType(column.getDataType().getDesc()); + importPackages.add(column.getEnumBack()); + importPackages.add(IsEnum.class.getName()); + } else { + columnObj.setDataType(column.getDataType().getDesc()); + columnObj.setFrontDataType(column.getDataType().getFrontDesc()); + columnObj.setViewType(column.getViewType().getCode()); + } + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + columnObj.setName(column.getColumnName()); + columnObj.setColumnName(column.getTableColumn().getDbColumnName()); + columnObj.setQueryType(column.getQueryParamsConfig().getQueryType().getCode()); + columnObj.setNameProperty( + column.getColumnName().substring(0, 1).toUpperCase() + column.getColumnName() + .substring(1)); + columnObj.setDescription(column.getName()); + columnObj.setHasAvailableTag( + column.getViewType() == GenViewType.SELECT && column.getDataType() == GenDataType.BOOLEAN + && "available".equals(column.getColumnName())); + columnObj.setFixEnum(column.getFixEnum()); + if (!StringUtil.isBlank(column.getRegularExpression())) { + columnObj.setRegularExpression(column.getRegularExpression()); + importPackages.add(Pattern.class.getName()); + } + if (column.getViewType() == GenViewType.DATA_DIC) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(column.getDataDicId()); + columnObj.setDataDicCode(dic.getCode()); + } else if (column.getViewType() == GenViewType.CUSTOM_SELECTOR) { + columnObj.setCustomSelectorId(column.getCustomSelectorId()); + } + + columns.add(columnObj); + } + queryParamsTemplate.setColumns(columns); + queryParamsTemplate.setImportPackages(importPackages); + + return queryParamsTemplate; + } + + private CreateTemplate getCreateTemplate() { + + List targetColumns = dataEntity.getColumns().stream() + .filter(t -> t.getCreateConfig() != null) + .sorted(Comparator.comparing(t -> t.getCreateConfig().getOrderNo())) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(targetColumns)) { + return null; + } + Set importPackages = new HashSet<>(); + importPackages.add(ApiModelProperty.class.getName()); + CreateTemplate createTemplate = new CreateTemplate(); + createTemplate.setAppointId(dataEntity.getGenerateInfo().getKeyType() != GenKeyType.AUTO); + if (dataEntity.getGenerateInfo().getKeyType() == GenKeyType.UUID) { + // 如果是UUID,则引入IdUtil包 + importPackages.add(IdUtil.class.getName()); + createTemplate.setIdCode(IdUtil.class.getSimpleName() + ".getUUID()"); + } else if (dataEntity.getGenerateInfo().getKeyType() == GenKeyType.SNOW_FLAKE) { + // 如果是雪花算法,则引入IdWorker包 + importPackages.add(IdUtil.class.getName()); + createTemplate.setIdCode(IdUtil.class.getSimpleName() + ".getId()"); + } + createTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + createTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + createTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + createTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + createTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + createTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + importPackages.add(TypeMismatch.class.getName()); + importPackages.add(BaseVo.class.getName()); + + List columns = new ArrayList<>(); + for (DataEntityColumn column : targetColumns) { + CreateTemplate.Column columnObj = new CreateTemplate.Column(); + columnObj.setIsKey(column.getIsKey()); + columnObj.setRequired(column.getCreateConfig().getRequired()); + if (column.getFixEnum()) { + // 如果是枚举类型 + columnObj.setDataType( + column.getEnumBack().substring(column.getEnumBack().lastIndexOf(".") + 1)); + columnObj.setFrontType(column.getEnumFront()); + columnObj.setFrontDataType("number"); + columnObj.setViewType(column.getViewType().getCode()); + importPackages.add(column.getEnumBack()); + importPackages.add(EnumUtil.class.getName()); + } else { + columnObj.setDataType(column.getDataType().getDesc()); + columnObj.setViewType(column.getViewType().getCode()); + columnObj.setFrontDataType(column.getDataType().getFrontDesc()); + } + if (column.getViewType() == GenViewType.DATE_RANGE) { + if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + columnObj.setViewType(GenViewType.DATETIME.getCode()); + } else { + columnObj.setViewType(GenViewType.DATE.getCode()); + } + } + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + columnObj.setFixEnum(column.getFixEnum()); + if (columnObj.getFixEnum()) { + columnObj.setEnumCodeType(column.getDataType().getDesc()); + } + if (columnObj.getRequired()) { + // 如果必填,那么需要引Validation注解包 + if (column.getDataType() == GenDataType.STRING) { + // 如果是String,则引@NotBlank注解 + columnObj.setValidateAnno(NotBlank.class.getSimpleName()); + importPackages.add(NotBlank.class.getName()); + } else { + // 否则引@NotNull注解 + columnObj.setValidateAnno(NotNull.class.getSimpleName()); + importPackages.add(NotNull.class.getName()); + } + + if (column.getViewType() == GenViewType.SELECT + || column.getViewType() == GenViewType.DATA_DIC) { + columnObj.setValidateMsg("请选择"); + } else { + columnObj.setValidateMsg("请输入"); + } + + if (columnObj.getFixEnum()) { + // 如果是内置枚举,那么引IsEnum注解包 + importPackages.add(IsEnum.class.getName()); + } + } + columnObj.setName(column.getColumnName()); + columnObj.setColumnName(column.getTableColumn().getDbColumnName()); + columnObj.setNameProperty( + column.getColumnName().substring(0, 1).toUpperCase() + column.getColumnName() + .substring(1)); + columnObj.setDescription(column.getName()); + columnObj.setHasAvailableTag( + column.getViewType() == GenViewType.SELECT && column.getDataType() == GenDataType.BOOLEAN + && "available".equals(column.getColumnName())); + if (!StringUtil.isBlank(column.getRegularExpression())) { + columnObj.setRegularExpression(column.getRegularExpression()); + importPackages.add(Pattern.class.getName()); + } + + columnObj.setIsNumberType(GenDataType.isNumberType(column.getDataType())); + columnObj.setIsDecimalType(GenDataType.isDecimalType(column.getDataType())); + if (column.getViewType() == GenViewType.DATA_DIC) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(column.getDataDicId()); + columnObj.setDataDicCode(dic.getCode()); + } else if (column.getViewType() == GenViewType.CUSTOM_SELECTOR) { + columnObj.setCustomSelectorId(column.getCustomSelectorId()); + } + columnObj.setLen(column.getLen()); + columnObj.setDecimals(column.getDecimals()); + if (columnObj.getIsNumberType()) { + if (columnObj.getIsDecimalType()) { + importPackages.add(IsNumberPrecision.class.getName()); + } + } else if (column.getDataType() == GenDataType.STRING) { + if (column.getViewType() == GenViewType.INPUT + || column.getViewType() == GenViewType.TEXTATREA) { + importPackages.add(Length.class.getName()); + } + } + columns.add(columnObj); + } + + createTemplate.setColumns(columns); + createTemplate.setImportPackages(importPackages); + List keyColumns = dataEntity.getColumns().stream() + .filter(DataEntityColumn::getIsKey) + .collect(Collectors.toList()); + List keys = keyColumns.stream().map(t -> { + CreateTemplate.Key key = new CreateTemplate.Key(); + // 主键不会是枚举 + key.setDataType(t.getDataType().getDesc()); + key.setName(t.getColumnName()); + key.setNameProperty( + t.getColumnName().substring(0, 1).toUpperCase() + t.getColumnName().substring(1)); + key.setColumnName(t.getTableColumn().getDbColumnName()); + key.setDescription(t.getName()); + + return key; + }).collect(Collectors.toList()); + + createTemplate.setKeys(keys); + + return createTemplate; + } + + private UpdateTemplate getUpdateTemplate() { + + List targetColumns = dataEntity.getColumns().stream() + .filter(t -> t.getUpdateConfig() != null) + .sorted(Comparator.comparing(t -> t.getUpdateConfig().getOrderNo())) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(targetColumns)) { + return null; + } + Set importPackages = new HashSet<>(); + UpdateTemplate updateTemplate = new UpdateTemplate(); + updateTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + updateTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + updateTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + updateTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + updateTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + updateTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + importPackages.add(TypeMismatch.class.getName()); + importPackages.add(ApiModelProperty.class.getName()); + importPackages.add(BaseVo.class.getName()); + + List columns = new ArrayList<>(); + for (DataEntityColumn column : targetColumns) { + UpdateTemplate.Column columnObj = new UpdateTemplate.Column(); + columnObj.setIsKey(column.getIsKey()); + columnObj.setRequired(column.getUpdateConfig().getRequired()); + if (column.getFixEnum()) { + // 如果是枚举类型 + columnObj.setDataType( + column.getEnumBack().substring(column.getEnumBack().lastIndexOf(".") + 1)); + columnObj.setFrontType(column.getEnumFront()); + columnObj.setViewType(column.getViewType().getCode()); + columnObj.setFrontDataType("number"); + importPackages.add(column.getEnumBack()); + importPackages.add(EnumUtil.class.getName()); + } else { + columnObj.setDataType(column.getDataType().getDesc()); + columnObj.setFrontDataType(column.getDataType().getFrontDesc()); + columnObj.setViewType(column.getViewType().getCode()); + } + if (column.getViewType() == GenViewType.DATE_RANGE) { + if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + columnObj.setViewType(GenViewType.DATETIME.getCode()); + } else { + columnObj.setViewType(GenViewType.DATE.getCode()); + } + } + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + columnObj.setFixEnum(column.getFixEnum()); + if (columnObj.getFixEnum()) { + columnObj.setEnumCodeType(column.getDataType().getDesc()); + } + if (columnObj.getRequired()) { + // 如果必填,那么需要引Validation注解包 + if (column.getDataType() == GenDataType.STRING) { + // 如果是String,则引@NotBlank注解 + columnObj.setValidateAnno(NotBlank.class.getSimpleName()); + importPackages.add(NotBlank.class.getName()); + } else { + // 否则引@NotNull注解 + columnObj.setValidateAnno(NotNull.class.getSimpleName()); + importPackages.add(NotNull.class.getName()); + } + + if (column.getViewType() == GenViewType.SELECT + || column.getViewType() == GenViewType.DATA_DIC) { + columnObj.setValidateMsg("请选择"); + } else { + columnObj.setValidateMsg("请输入"); + } + + if (columnObj.getFixEnum()) { + // 如果是内置枚举,那么引IsEnum注解包 + importPackages.add(IsEnum.class.getName()); + } + } + columnObj.setName(column.getColumnName()); + columnObj.setColumnName(column.getTableColumn().getDbColumnName()); + columnObj.setNameProperty( + column.getColumnName().substring(0, 1).toUpperCase() + column.getColumnName() + .substring(1)); + columnObj.setDescription(column.getName()); + columnObj.setHasAvailableTag( + column.getViewType() == GenViewType.SELECT && column.getDataType() == GenDataType.BOOLEAN + && "available".equals(column.getColumnName())); + if (!StringUtil.isBlank(column.getRegularExpression())) { + columnObj.setRegularExpression(column.getRegularExpression()); + importPackages.add(Pattern.class.getName()); + } + columnObj.setIsNumberType(GenDataType.isNumberType(column.getDataType())); + columnObj.setIsDecimalType(GenDataType.isDecimalType(column.getDataType())); + columnObj.setLen(column.getLen()); + columnObj.setDecimals(column.getDecimals()); + if (columnObj.getIsNumberType()) { + if (columnObj.getIsDecimalType()) { + importPackages.add(IsNumberPrecision.class.getName()); + } + } else if (column.getDataType() == GenDataType.STRING) { + if (column.getViewType() == GenViewType.INPUT + || column.getViewType() == GenViewType.TEXTATREA) { + importPackages.add(Length.class.getName()); + } + } + + if (column.getViewType() == GenViewType.DATA_DIC) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(column.getDataDicId()); + columnObj.setDataDicCode(dic.getCode()); + } else if (column.getViewType() == GenViewType.CUSTOM_SELECTOR) { + columnObj.setCustomSelectorId(column.getCustomSelectorId()); + } + + columns.add(columnObj); + } + + updateTemplate.setColumns(columns); + updateTemplate.setImportPackages(importPackages); + List keyColumns = dataEntity.getColumns().stream() + .filter(DataEntityColumn::getIsKey) + .collect(Collectors.toList()); + List keys = keyColumns.stream().map(t -> { + UpdateTemplate.Key key = new UpdateTemplate.Key(); + // 主键不会是枚举 + key.setDataType(t.getDataType().getDesc()); + key.setFrontDataType(t.getDataType().getFrontDesc()); + key.setName(t.getColumnName()); + key.setNameProperty( + t.getColumnName().substring(0, 1).toUpperCase() + t.getColumnName().substring(1)); + key.setColumnName(t.getTableColumn().getDbColumnName()); + key.setDescription(t.getName()); + if (t.getDataType() == GenDataType.STRING) { + // 如果是String,则引@NotBlank注解 + importPackages.add(NotBlank.class.getName()); + } else { + // 否则引@NotNull注解 + importPackages.add(NotNull.class.getName()); + } + return key; + }).collect(Collectors.toList()); + updateTemplate.setKeys(keys); + + return updateTemplate; + } + + private QueryTemplate getQueryTemplate() { + + List targetColumns = dataEntity.getColumns().stream() + .filter(t -> t.getQueryConfig() != null) + .sorted(Comparator.comparing(t -> t.getQueryConfig().getOrderNo())) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(targetColumns)) { + return null; + } + QueryTemplate queryTemplate = new QueryTemplate(); + queryTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + queryTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + queryTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + queryTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + queryTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + queryTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + + Set importPackages = new HashSet<>(); + importPackages.add(TypeMismatch.class.getName()); + importPackages.add(ApiModelProperty.class.getName()); + importPackages.add(StringPool.class.getName()); + importPackages.add(BaseBo.class.getName()); + List columns = new ArrayList<>(); + for (DataEntityColumn column : targetColumns) { + QueryTemplate.Column columnObj = new QueryTemplate.Column(); + if (column.getFixEnum()) { + // 如果是枚举类型 + columnObj.setDataType( + column.getEnumBack().substring(column.getEnumBack().lastIndexOf(".") + 1)); + columnObj.setFrontType(column.getEnumFront()); + columnObj.setFrontDataType("number"); + columnObj.setViewType(column.getViewType().getCode()); + importPackages.add(column.getEnumBack()); + importPackages.add(EnumUtil.class.getName()); + } else { + columnObj.setDataType(column.getDataType().getDesc()); + columnObj.setFrontDataType(column.getDataType().getFrontDesc()); + columnObj.setIsNumberType(GenDataType.isNumberType(column.getDataType())); + columnObj.setViewType(column.getViewType().getCode()); + columnObj.setHasAvailableTag( + column.getViewType() == GenViewType.SELECT + && column.getDataType() == GenDataType.BOOLEAN + && "available".equals(column.getColumnName())); + } + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + columnObj.setFixEnum(column.getFixEnum()); + if (columnObj.getFixEnum()) { + columnObj.setEnumCodeType(column.getDataType().getDesc()); + } + columnObj.setName(column.getColumnName()); + columnObj.setNameProperty( + column.getColumnName().substring(0, 1).toUpperCase() + column.getColumnName() + .substring(1)); + columnObj.setWidthType(column.getQueryConfig().getWidthType().getCode()); + columnObj.setWidth(column.getQueryConfig().getWidth()); + columnObj.setSortable(column.getQueryConfig().getSortable()); + columnObj.setDescription(column.getName()); + if (column.getViewType() == GenViewType.DATA_DIC) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(column.getDataDicId()); + columnObj.setDataDicCode(dic.getCode()); + importPackages.add(SysDataDicItemService.class.getName()); + importPackages.add(StringUtil.class.getName()); + importPackages.add(ApplicationUtil.class.getName()); + importPackages.add(StringPool.class.getName()); + } + + columns.add(columnObj); + } + + queryTemplate.setColumns(columns); + queryTemplate.setHasFixEnum(columns.stream().anyMatch(QueryTemplate.Column::getFixEnum)); + + List keyColumns = dataEntity.getColumns().stream() + .filter(DataEntityColumn::getIsKey) + .collect(Collectors.toList()); + List keys = keyColumns.stream().map(t -> { + QueryTemplate.Key key = new QueryTemplate.Key(); + // 主键不会是枚举 + key.setDataType(t.getDataType().getDesc()); + key.setFrontDataType(t.getDataType().getFrontDesc()); + key.setName(t.getColumnName()); + key.setNameProperty( + t.getColumnName().substring(0, 1).toUpperCase() + t.getColumnName().substring(1)); + key.setDescription(t.getName()); + + return key; + }).collect(Collectors.toList()); + + queryTemplate.setKeys(keys); + + queryTemplate.setImportPackages(importPackages); + + return queryTemplate; + } + + private DetailTemplate getDetailTemplate() { + + List targetColumns = dataEntity.getColumns().stream() + .filter(t -> t.getDetailConfig() != null) + .sorted(Comparator.comparing(t -> t.getDetailConfig().getOrderNo())) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(targetColumns)) { + return null; + } + DetailTemplate detailTemplate = new DetailTemplate(); + detailTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + detailTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + detailTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + detailTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + detailTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + detailTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + + Set importPackages = new HashSet<>(); + importPackages.add(TypeMismatch.class.getName()); + importPackages.add(ApiModelProperty.class.getName()); + importPackages.add(StringPool.class.getName()); + importPackages.add(BaseBo.class.getName()); + List columns = new ArrayList<>(); + for (DataEntityColumn column : targetColumns) { + DetailTemplate.Column columnObj = new DetailTemplate.Column(); + if (column.getFixEnum()) { + // 如果是枚举类型 + columnObj.setDataType( + column.getEnumBack().substring(column.getEnumBack().lastIndexOf(".") + 1)); + columnObj.setFrontType(column.getEnumFront()); + columnObj.setFrontDataType("number"); + importPackages.add(column.getEnumBack()); + importPackages.add(EnumUtil.class.getName()); + } else { + columnObj.setDataType(column.getDataType().getDesc()); + columnObj.setFrontDataType(column.getDataType().getFrontDesc()); + columnObj.setHasAvailableTag( + column.getViewType() == GenViewType.SELECT + && column.getDataType() == GenDataType.BOOLEAN + && "available".equals(column.getColumnName())); + if (columnObj.getHasAvailableTag()) { + detailTemplate.setHasAvailableTag(Boolean.TRUE); + } + } + // 以下类型需要单独引包 + if (column.getDataType() == GenDataType.LOCAL_DATE) { + importPackages.add(LocalDate.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_DATE_TIME) { + importPackages.add(LocalDateTime.class.getName()); + } else if (column.getDataType() == GenDataType.LOCAL_TIME) { + importPackages.add(LocalTime.class.getName()); + } else if (column.getDataType() == GenDataType.BIG_DECIMAL) { + importPackages.add(BigDecimal.class.getName()); + } + columnObj.setFixEnum(column.getFixEnum()); + if (columnObj.getFixEnum()) { + columnObj.setEnumCodeType(column.getDataType().getDesc()); + } + columnObj.setName(column.getColumnName()); + columnObj.setNameProperty( + column.getColumnName().substring(0, 1).toUpperCase() + column.getColumnName() + .substring(1)); + columnObj.setDescription(column.getName()); + columnObj.setSpan(column.getDetailConfig().getSpan()); + + if (column.getViewType() == GenViewType.DATA_DIC) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dic = sysDataDicService.findById(column.getDataDicId()); + columnObj.setDataDicCode(dic.getCode()); + importPackages.add(SysDataDicItemService.class.getName()); + importPackages.add(StringUtil.class.getName()); + importPackages.add(ApplicationUtil.class.getName()); + importPackages.add(StringPool.class.getName()); + } + + columns.add(columnObj); + } + + detailTemplate.setColumns(columns); + detailTemplate.setHasFixEnum(columns.stream().anyMatch(DetailTemplate.Column::getFixEnum)); + detailTemplate.setDetailSpan(dataEntity.getGenerateInfo().getDetailSpan()); + List keyColumns = dataEntity.getColumns().stream() + .filter(DataEntityColumn::getIsKey) + .collect(Collectors.toList()); + List keys = keyColumns.stream().map(t -> { + DetailTemplate.Key key = new DetailTemplate.Key(); + // 主键不会是枚举 + key.setDataType(t.getDataType().getDesc()); + key.setFrontDataType(t.getDataType().getFrontDesc()); + key.setName(t.getColumnName()); + key.setNameProperty( + t.getColumnName().substring(0, 1).toUpperCase() + t.getColumnName().substring(1)); + key.setDescription(t.getName()); + + return key; + }).collect(Collectors.toList()); + + detailTemplate.setKeys(keys); + + detailTemplate.setImportPackages(importPackages); + + return detailTemplate; + } + + private ControllerTemplate getControllerTemplate() { + + Set importPackages = new HashSet<>(); + ControllerTemplate controllerTemplate = new ControllerTemplate(); + controllerTemplate.setPackageName(dataEntity.getGenerateInfo().getPackageName()); + controllerTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + controllerTemplate.setClassNameProperty( + dataEntity.getGenerateInfo().getClassName().substring(0, 1).toLowerCase() + + dataEntity.getGenerateInfo() + .getClassName().substring(1)); + controllerTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + controllerTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + controllerTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + controllerTemplate.setAuthor(dataEntity.getGenerateInfo().getAuthor()); + controllerTemplate.setIsCache(dataEntity.getGenerateInfo().getIsCache()); + controllerTemplate.setHasDelete(dataEntity.getGenerateInfo().getHasDelete()); + if (controllerTemplate.getHasDelete()) { + importPackages.add(DeleteMapping.class.getName()); + } + importPackages.add(DefaultClientException.class.getName()); + importPackages.add(CollectionUtil.class.getName()); + importPackages.add(PageResult.class.getName()); + importPackages.add(PageResultUtil.class.getName()); + importPackages.add(InvokeResult.class.getName()); + importPackages.add(InvokeResultBuilder.class.getName()); + importPackages.add(Api.class.getName()); + importPackages.add(ApiOperation.class.getName()); + importPackages.add(ApiImplicitParam.class.getName()); + importPackages.add(ApiImplicitParams.class.getName()); + + List keyColumns = dataEntity.getColumns().stream() + .filter(DataEntityColumn::getIsKey) + .collect(Collectors.toList()); + List keys = keyColumns.stream().map(t -> { + ControllerTemplate.Key key = new ControllerTemplate.Key(); + // 主键不会是枚举 + key.setDataType(t.getDataType().getDesc()); + key.setName(t.getColumnName()); + key.setNameProperty(t.getColumnName().substring(0, 1).toUpperCase() + t.getColumnName() + .substring(1)); + + if (t.getDataType() == GenDataType.STRING) { + importPackages.add(NotBlank.class.getName()); + } else { + importPackages.add(NotNull.class.getName()); + } + + return key; + }).collect(Collectors.toList()); + + controllerTemplate.setKeys(keys); + controllerTemplate.setImportPackages(importPackages); + controllerTemplate.setCreate(this.getCreateTemplate()); + controllerTemplate.setUpdate(this.getUpdateTemplate()); + controllerTemplate.setQuery(this.getQueryTemplate()); + controllerTemplate.setQueryParams(this.getQueryParamsTemplate()); + controllerTemplate.setDetail(this.getDetailTemplate()); + if (controllerTemplate.getCreate() != null) { + importPackages.addAll(controllerTemplate.getCreate().getImportPackages()); + } + if (controllerTemplate.getUpdate() != null) { + importPackages.addAll(controllerTemplate.getUpdate().getImportPackages()); + } + if (controllerTemplate.getQuery() != null) { + importPackages.addAll(controllerTemplate.getQuery().getImportPackages()); + if (!controllerTemplate.getHasAvailableTag()) { + controllerTemplate.setHasAvailableTag(controllerTemplate.getQuery().getColumns().stream() + .anyMatch(QueryTemplate.Column::getHasAvailableTag)); + } + } + if (controllerTemplate.getQueryParams() != null) { + importPackages.addAll(controllerTemplate.getQueryParams().getImportPackages()); + if (!controllerTemplate.getHasAvailableTag()) { + controllerTemplate.setHasAvailableTag( + controllerTemplate.getQueryParams().getColumns().stream() + .anyMatch(QueryParamsTemplate.Column::getHasAvailableTag)); + } + } + if (controllerTemplate.getDetail() != null) { + importPackages.addAll(controllerTemplate.getDetail().getImportPackages()); + } + + return controllerTemplate; + } + + private SqlTemplate getSqlTemplate() { + + SqlTemplate sqlTemplate = new SqlTemplate(); + sqlTemplate.setModuleName(dataEntity.getGenerateInfo().getModuleName()); + sqlTemplate.setBizName(dataEntity.getGenerateInfo().getBizName()); + sqlTemplate.setClassName(dataEntity.getGenerateInfo().getClassName()); + sqlTemplate.setClassDescription(dataEntity.getGenerateInfo().getClassDescription()); + sqlTemplate.setParentMenuId(dataEntity.getGenerateInfo().getParentMenuId()); + sqlTemplate.setMenuId(dataEntity.getGenerateInfo().getId()); + sqlTemplate.setMenuCode(dataEntity.getGenerateInfo().getMenuCode()); + sqlTemplate.setMenuName(dataEntity.getGenerateInfo().getMenuName()); + sqlTemplate.setCreate(this.getCreateTemplate()); + sqlTemplate.setUpdate(this.getUpdateTemplate()); + + return sqlTemplate; + } + + /** + * 生成代码 + * + * @param templateName 模板名称 + * @param data 数据 + * @return + */ + private String generate(String templateName, Object data) { + + Template template = this.getTemplate(templateName); + Map root = JsonUtil.convert(data, Map.class); + StringWriter stringWriter = new StringWriter(); + BufferedWriter writer = new BufferedWriter(stringWriter); + + loadStaticClasses(root); + + try { + template.process(root, writer); + } catch (TemplateException | IOException e) { + log.error(e.getMessage(), e); + throw new DefaultSysException(e.getMessage()); + } + + return stringWriter.toString(); + } + + private GenerateDto buildGenerateResult(String path, String fileName, String content) { + + if (StringUtil.isBlank(content)) { + return null; + } + GenerateDto result = new GenerateDto(); + result.setPath(path); + result.setFileName(fileName); + result.setContent(content); + + return result; + } + + private void loadStaticClasses(Map root) { + + BeansWrapper wrapper = BeansWrapper.getDefaultInstance(); + + TemplateHashModel staticModels = wrapper.getStaticModels(); + + TemplateHashModel fileStatics = null; + try { + fileStatics = (TemplateHashModel) staticModels.get(IdUtil.class.getName()); + } catch (TemplateModelException e) { + log.error("加载静态类失败", e); + throw new DefaultSysException("加载静态类失败"); + } + + root.put(IdUtil.class.getSimpleName(), fileStatics); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ControllerTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ControllerTemplate.java new file mode 100644 index 0000000..88aa822 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ControllerTemplate.java @@ -0,0 +1,116 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 用于Controller.java、index.vue、api.js生成 + */ +@Data +public class ControllerTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 类名(首字母小写) + */ + private String classNameProperty; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 是否应用缓存 + */ + private Boolean isCache; + + /** + * 是否内置删除功能 + */ + private Boolean hasDelete; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 主键 + */ + private List keys; + + /** + * 需要import的包 + */ + private Set importPackages; + + /** + * 新增配置 + */ + private CreateTemplate create; + + /** + * 修改配置 + */ + private UpdateTemplate update; + + /** + * 查询配置 + */ + private QueryTemplate query; + + /** + * 查询参数配置 + */ + private QueryParamsTemplate queryParams; + + /** + * 详情配置 + */ + private DetailTemplate detail; + + @Data + public static class Key { + + /** + * 类型 + */ + private String dataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/CreateTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/CreateTemplate.java new file mode 100644 index 0000000..6409297 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/CreateTemplate.java @@ -0,0 +1,210 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 新增功能Template + */ +@Data +public class CreateTemplate { + + /** + * 是否指定ID 如果是自增ID就不需要指定ID + */ + private Boolean appointId; + + /** + * 指定ID的代码 当appointId == true时生效 + */ + private String idCode; + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 字段 + */ + private List columns; + + /** + * 需要import的包 + */ + private Set importPackages; + + /** + * 主键 + */ + private List keys; + + @Data + public static class Key { + + /** + * 字段类型 + */ + private String dataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段名 + */ + private String columnName; + + /** + * 字段备注 + */ + private String description; + } + + @Data + public static class Column { + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 验证注解 + */ + private String validateAnno; + + /** + * 验证信息 当required == true时生效 + */ + private String validateMsg; + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 枚举的Code的类型 当fixEnum == true时生效 + */ + private String enumCodeType; + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + private String frontType; + + /** + * 显示类型 + */ + private Integer viewType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段名 + */ + private String columnName; + + /** + * 正则表达式 + */ + private String regularExpression; + + /** + * 字段备注 + */ + private String description; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 是否数字类型 + */ + private Boolean isNumberType = Boolean.FALSE; + + /** + * 是否小数类型 + */ + private Boolean isDecimalType = Boolean.FALSE; + + /** + * 数据字典编号 + */ + private String dataDicCode; + + /** + * 自定义选择器ID + */ + private String customSelectorId; + + /** + * 长度 + */ + private Long len; + + /** + * 小数点位数 + */ + private Integer decimals; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/DetailTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/DetailTemplate.java new file mode 100644 index 0000000..dfd38ca --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/DetailTemplate.java @@ -0,0 +1,160 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 详情功能Template + */ +@Data +public class DetailTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 字段 + */ + private List columns; + + /** + * 主键 + */ + private List keys; + + /** + * 是否存在内置枚举 + */ + private Boolean hasFixEnum; + + /** + * 详情页Span总数量 + */ + private Integer detailSpan; + + /** + * 需要import的包 + */ + private Set importPackages; + + @Data + public static class Key { + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段备注 + */ + private String description; + } + + @Data + public static class Column { + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 枚举的Code的类型 当fixEnum == true时生效 + */ + private String enumCodeType; + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + private String frontType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段备注 + */ + private String description; + + /** + * 列宽 + */ + private Integer span; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 数据字典Code + */ + private String dataDicCode; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/EntityTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/EntityTemplate.java new file mode 100644 index 0000000..ea5fae3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/EntityTemplate.java @@ -0,0 +1,112 @@ +package com.lframework.xingyun.template.gen.generate.templates; + + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 实体类Template + */ +@Data +public class EntityTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 库表名 + */ + private String tableName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 列信息 + */ + private List columns; + + /** + * 需要import的包 + */ + private Set importPackages; + + @Data + public static class Column { + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 是否自增主键 + */ + private Boolean autoIncrKey; + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + private String frontType; + + /** + * 字段名称 + */ + private String name; + + /** + * 是否默认字段名转换方式(下划线转驼峰) + */ + private Boolean defaultConvertType; + + /** + * 数据库字段名称 + */ + private String columnName; + + /** + * 字段备注 + */ + private String description; + + /** + * 是否填充字段 isKey == false时生效 + */ + private Boolean fill; + + /** + * 填充策略 + */ + private String fillStrategy; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/MapperTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/MapperTemplate.java new file mode 100644 index 0000000..7ad9050 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/MapperTemplate.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 用于生成Mapper.java、Mapper.xml + */ +@Data +public class MapperTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 主键 + */ + private List keys; + + /** + * 排序字段 + */ + private List orderColumns; + + /** + * 实体类配置 + */ + private EntityTemplate entity; + + /** + * 需要import的包 + */ + private Set importPackages; + + /** + * 查询参数配置 + */ + private QueryParamsTemplate queryParams; + + @Data + public static class Key { + + /** + * 类型 + */ + private String dataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 数据表列名 + */ + private String columnName; + } + + @Data + public static class OrderColumn { + + /** + * 数据表列名 + */ + private String columnName; + + /** + * 排序类型 + */ + private String orderType; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryParamsTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryParamsTemplate.java new file mode 100644 index 0000000..51a5443 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryParamsTemplate.java @@ -0,0 +1,131 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 查询参数Template + */ +@Data +public class QueryParamsTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 字段 + */ + private List columns; + + /** + * 需要import的包 + */ + private Set importPackages; + + @Data + public static class Column { + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 正则表达式 + */ + private String regularExpression; + + /** + * 枚举的Code的类型 当fixEnum == true时生效 + */ + private String enumCodeType; + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + private String frontType; + + /** + * 显示类型 + */ + private Integer viewType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段名 + */ + private String columnName; + + /** + * 查询类型 + */ + private Integer queryType; + + /** + * 字段备注 + */ + private String description; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 数据字典Code + */ + private String dataDicCode; + + /** + * 自定义选择器ID + */ + private String customSelectorId; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryTemplate.java new file mode 100644 index 0000000..0ce6dc4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/QueryTemplate.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 查询功能Template + */ +@Data +public class QueryTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 字段 + */ + private List columns; + + /** + * 主键 + */ + private List keys; + + /** + * 是否存在内置枚举 + */ + private Boolean hasFixEnum; + + /** + * 需要import的包 + */ + private Set importPackages; + + @Data + public static class Key { + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段备注 + */ + private String description; + } + + @Data + public static class Column { + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 枚举的Code的类型 当fixEnum == true时生效 + */ + private String enumCodeType; + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + private String frontType; + + /** + * 是否数字类型 + */ + private Boolean isNumberType = Boolean.FALSE; + + /** + * 显示类型 + */ + private Integer viewType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 宽度类型 + */ + private Integer widthType; + + /** + * 宽度 + */ + private Integer width; + + /** + * 是否页面排序 + */ + private Boolean sortable; + + /** + * 字段备注 + */ + private String description; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 数据字典Code + */ + private String dataDicCode; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ServiceTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ServiceTemplate.java new file mode 100644 index 0000000..457f4e1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/ServiceTemplate.java @@ -0,0 +1,106 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 用于Service.java、ServiceImpl.java生成 + */ +@Data +public class ServiceTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 类名(首字母小写) + */ + private String classNameProperty; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 是否应用缓存 + */ + private Boolean isCache; + + /** + * 是否内置删除功能 + */ + private Boolean hasDelete; + + /** + * 需要import的包 + */ + private Set importPackages; + + /** + * 主键 + */ + private List keys; + + /** + * 查询参数配置 + */ + private QueryParamsTemplate queryParams; + + /** + * 新增配置 + */ + private CreateTemplate create; + + /** + * 修改配置 + */ + private UpdateTemplate update; + + @Data + public static class Key { + + /** + * 类型 + */ + private String dataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 数据表列名 + */ + private String columnName; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/SqlTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/SqlTemplate.java new file mode 100644 index 0000000..03d9530 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/SqlTemplate.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import lombok.Data; + +/** + * 用于生成Sql + */ +@Data +public class SqlTemplate { + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类名 + */ + private String className; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 父级菜单ID + */ + private String parentMenuId; + + /** + * 菜单ID + */ + private String menuId; + + /** + * 本级菜单编号 + */ + private String menuCode; + + /** + * 本级菜单名称 + */ + private String menuName; + + /** + * 新增配置 + */ + private CreateTemplate create; + + /** + * 修改配置 + */ + private UpdateTemplate update; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/UpdateTemplate.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/UpdateTemplate.java new file mode 100644 index 0000000..938b4c4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/generate/templates/UpdateTemplate.java @@ -0,0 +1,205 @@ +package com.lframework.xingyun.template.gen.generate.templates; + +import java.util.List; +import java.util.Set; +import lombok.Data; + +/** + * 修改功能Template + */ +@Data +public class UpdateTemplate { + + /** + * 包名 + */ + private String packageName; + + /** + * 类名 + */ + private String className; + + /** + * 模块名称 + */ + private String moduleName; + + /** + * 业务名称 + */ + private String bizName; + + /** + * 类描述 + */ + private String classDescription; + + /** + * 作者 + */ + private String author; + + /** + * 字段 + */ + private List columns; + + /** + * 需要import的包 + */ + private Set importPackages; + + /** + * 主键 + */ + private List keys; + + @Data + public static class Key { + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段名 + */ + private String columnName; + + /** + * 字段备注 + */ + private String description; + } + + @Data + public static class Column { + + /** + * 是否主键 + */ + private Boolean isKey; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 验证注解 + */ + private String validateAnno; + + /** + * 验证信息 当required == true时生效 + */ + private String validateMsg; + + /** + * 是否内置枚举 + */ + private Boolean fixEnum; + + /** + * 枚举的Code的类型 当fixEnum == true时生效 + */ + private String enumCodeType; + + /** + * 字段类型 + */ + private String dataType; + + /** + * 前端字段类型 + */ + private String frontDataType; + + /** + * 前端字段类型 只有字段是枚举时生效,此值为前端枚举类型 + */ + private String frontType; + + /** + * 显示类型 + */ + private Integer viewType; + + /** + * 字段名称 + */ + private String name; + + /** + * 字段名称(首字母大写) + */ + private String nameProperty; + + /** + * 字段名 + */ + private String columnName; + + /** + * 正则表达式 + */ + private String regularExpression; + + /** + * 字段备注 + */ + private String description; + + /** + * 是否包含状态Tag + */ + private Boolean hasAvailableTag = Boolean.FALSE; + + /** + * 是否数字类型 + */ + private Boolean isNumberType = Boolean.FALSE; + + /** + * 是否小数类型 + */ + private Boolean isDecimalType = Boolean.FALSE; + + /** + * 数据字典编号 + */ + private String dataDicCode; + + /** + * 自定义选择器ID + */ + private String customSelectorId; + + /** + * 长度 + */ + private Long len; + + /** + * 小数点位数 + */ + private Integer decimals; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCreateColumnConfigServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCreateColumnConfigServiceImpl.java new file mode 100644 index 0000000..431fee3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCreateColumnConfigServiceImpl.java @@ -0,0 +1,74 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenCreateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenCreateColumnConfig; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.mappers.GenCreateColumnConfigMapper; +import com.lframework.xingyun.template.gen.service.GenCreateColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.vo.gen.UpdateCreateColumnConfigVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCreateColumnConfigServiceImpl + extends BaseMpServiceImpl + implements GenCreateColumnConfigService { + + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Override + public List getByDataEntityId(String entityId) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (CollectionUtil.isEmpty(columns)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(String entityId, List vo) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (!CollectionUtil.isEmpty(columns)) { + getBaseMapper().deleteBatchIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + if (!CollectionUtil.isEmpty(vo)) { + int orderNo = 1; + for (UpdateCreateColumnConfigVo updateCreateColumnConfigVo : vo) { + GenCreateColumnConfig record = new GenCreateColumnConfig(); + record.setId(updateCreateColumnConfigVo.getId()); + record.setRequired(updateCreateColumnConfigVo.getRequired()); + record.setOrderNo(orderNo++); + + getBaseMapper().insert(record); + } + } + } + + @Override + public GenCreateColumnConfigDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + getBaseMapper().deleteById(id); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListCategoryServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListCategoryServiceImpl.java new file mode 100644 index 0000000..4b622c2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListCategoryServiceImpl.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.mappers.GenCustomListCategoryMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.vo.custom.list.category.CreateGenCustomListCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.list.category.GenCustomListCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.list.category.UpdateGenCustomListCategoryVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomListCategoryServiceImpl extends + BaseMpServiceImpl implements + GenCustomListCategoryService { + + @Autowired + private GenCustomListService genCustomListService; + + @Cacheable(value = GenCustomListCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomListCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenCustomListCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenCustomListCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenCustomListCategoryVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(GenCustomListCategory.class) + .eq(GenCustomListCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenCustomListCategory.class) + .eq(GenCustomListCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenCustomListCategory record = new GenCustomListCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenCustomListCategoryVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(GenCustomListCategory.class) + .eq(GenCustomListCategory::getCode, vo.getCode()) + .ne(GenCustomListCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenCustomListCategory.class) + .eq(GenCustomListCategory::getName, vo.getName()) + .ne(GenCustomListCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenCustomListCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("自定义列表分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenCustomList.class) + .eq(GenCustomList::getCategoryId, id); + if (genCustomListService.count(queryWrapper) > 0) { + throw new DefaultClientException("此分类下存在自定义列表,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = GenCustomListCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListDetailServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListDetailServiceImpl.java new file mode 100644 index 0000000..1392e43 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListDetailServiceImpl.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.xingyun.template.gen.mappers.GenCustomListDetailMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListDetailService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomListDetailServiceImpl extends + BaseMpServiceImpl implements + GenCustomListDetailService { + + @Override + public List getByCustomListId(String customListId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(GenCustomListDetail.class) + .eq(GenCustomListDetail::getCustomListId, customListId) + .orderByAsc(GenCustomListDetail::getOrderNo); + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByCustomListId(String customListId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(GenCustomListDetail.class) + .eq(GenCustomListDetail::getCustomListId, customListId); + this.remove(deleteWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListHandleColumnServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListHandleColumnServiceImpl.java new file mode 100644 index 0000000..dbaa7e1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListHandleColumnServiceImpl.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenCustomListHandleColumn; +import com.lframework.xingyun.template.gen.mappers.GenCustomListHandleColumnMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListHandleColumnService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomListHandleColumnServiceImpl extends + BaseMpServiceImpl implements + GenCustomListHandleColumnService { + + @Override + public List getByCustomListId(String customListId) { + return getBaseMapper().getByCustomListId(customListId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByCustomListId(String customListId) { + + Wrapper deleteWrapper = Wrappers + .lambdaQuery(GenCustomListHandleColumn.class) + .eq(GenCustomListHandleColumn::getCustomListId, customListId); + this.remove(deleteWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListQueryParamsServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListQueryParamsServiceImpl.java new file mode 100644 index 0000000..63a1ede --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListQueryParamsServiceImpl.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.xingyun.template.gen.mappers.GenCustomListQueryParamsMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListQueryParamsService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomListQueryParamsServiceImpl extends + BaseMpServiceImpl implements + GenCustomListQueryParamsService { + + @Override + public List getByCustomListId(String customListId) { + Wrapper queryWrapper = Wrappers.lambdaQuery( + GenCustomListQueryParams.class).eq(GenCustomListQueryParams::getCustomListId, customListId) + .orderByAsc(GenCustomListQueryParams::getOrderNo); + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByCustomListId(String customListId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery( + GenCustomListQueryParams.class) + .eq(GenCustomListQueryParams::getCustomListId, customListId); + this.remove(deleteWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListServiceImpl.java new file mode 100644 index 0000000..8a9ff4f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListServiceImpl.java @@ -0,0 +1,526 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.xingyun.template.gen.components.custom.list.CustomListConfig; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.xingyun.template.gen.entity.GenCustomListHandleColumn; +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.xingyun.template.gen.entity.GenCustomListToolbar; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnType; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnViewType; +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.enums.GenCustomListType; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.xingyun.template.gen.events.CustomListDeleteEvent; +import com.lframework.xingyun.template.gen.mappers.GenCustomListMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListDetailService; +import com.lframework.xingyun.template.gen.service.GenCustomListHandleColumnService; +import com.lframework.xingyun.template.gen.service.GenCustomListQueryParamsService; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.service.GenCustomListToolbarService; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.vo.custom.list.CreateGenCustomListVo; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListDetailVo; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListHandleColumnVo; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListQueryParamsVo; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListToolbarVo; +import com.lframework.xingyun.template.gen.vo.custom.list.QueryGenCustomListVo; +import com.lframework.xingyun.template.gen.vo.custom.list.UpdateGenCustomListVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.JsonUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomListServiceImpl extends + BaseMpServiceImpl implements GenCustomListService { + + @Autowired + private GenCustomListQueryParamsService genCustomListQueryParamsService; + + @Autowired + private GenCustomListDetailService genCustomListDetailService; + + @Autowired + private GenCustomListToolbarService genCustomListToolbarService; + + @Autowired + private GenCustomListHandleColumnService genCustomListHandleColumnService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryGenCustomListVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryGenCustomListVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomListSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenCustomList.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenCustomList findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenCustomListVo data) { + GenCustomList record = new GenCustomList(); + record.setId(IdUtil.getId()); + record.setName(data.getName()); + if (!StringUtil.isBlank(data.getCategoryId())) { + record.setCategoryId(data.getCategoryId()); + } + record.setListType(EnumUtil.getByCode(GenCustomListType.class, data.getListType())); + record.setQueryPrefixSql(StringUtil.isBlank(data.getQueryPrefixSql()) ? StringPool.EMPTY_STR + : data.getQueryPrefixSql()); + record.setQuerySuffixSql(StringUtil.isBlank(data.getQuerySuffixSql()) ? StringPool.EMPTY_STR + : data.getQuerySuffixSql()); + record.setSuffixSql( + StringUtil.isBlank(data.getSuffixSql()) ? StringPool.EMPTY_STR : data.getSuffixSql()); + + record.setLabelWidth(data.getLabelWidth()); + record.setHasPage(data.getHasPage()); + record.setTreeData(data.getTreeData()); + // 如果是树形列表,那么分页必须禁用 + // 如果分页没有禁用,那么一定不是树形列表 + if (record.getTreeData()) { + record.setHasPage(Boolean.FALSE); + } + + if (record.getHasPage()) { + record.setTreeData(Boolean.FALSE); + } + + record.setIdColumn(data.getIdColumn()); + record.setIdColumnRelaId(data.getIdColumnRelaId()); + + if (record.getTreeData()) { + + if (StringUtil.isBlank(data.getTreePidColumn())) { + throw new DefaultClientException("父级ID字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreePidColumnRelaId())) { + throw new DefaultClientException("父级ID字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreeNodeColumn())) { + throw new DefaultClientException("树形节点字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreeNodeColumnRelaId())) { + throw new DefaultClientException("树形节点字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreeChildrenKey())) { + throw new DefaultClientException("子节点Key值不能为空!"); + } + record.setTreePidColumn(data.getTreePidColumn()); + record.setTreePidColumnRelaId(data.getTreePidColumnRelaId()); + record.setTreeNodeColumn(data.getTreeNodeColumn()); + record.setTreeNodeColumnRelaId(data.getTreeNodeColumnRelaId()); + record.setTreeChildrenKey(data.getTreeChildrenKey()); + } + record.setAllowExport(data.getAllowExport()); + record.setDataObjId(data.getDataObjId()); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + if (!CollectionUtil.isEmpty(data.getQueryParams())) { + int orderNo = 1; + for (GenCustomListQueryParamsVo queryParam : data.getQueryParams()) { + GenCustomListQueryParams genCustomListQueryParams = new GenCustomListQueryParams(); + genCustomListQueryParams.setId(IdUtil.getId()); + genCustomListQueryParams.setCustomListId(record.getId()); + genCustomListQueryParams.setRelaId(queryParam.getRelaId()); + genCustomListQueryParams.setDataEntityId(queryParam.getId()); + genCustomListQueryParams.setQueryType( + EnumUtil.getByCode(GenQueryType.class, queryParam.getQueryType())); + genCustomListQueryParams.setFrontShow(queryParam.getFrontShow()); + genCustomListQueryParams.setFormWidth(queryParam.getFormWidth()); + genCustomListQueryParams.setDefaultValue(queryParam.getDefaultValue() == null ? null + : queryParam.getDefaultValue() instanceof String ? queryParam.getDefaultValue() + .toString() : JsonUtil.toJsonString(queryParam.getDefaultValue())); + genCustomListQueryParams.setOrderNo(orderNo); + genCustomListQueryParams.setType( + EnumUtil.getByCode(GenCustomListDetailType.class, queryParam.getType())); + + genCustomListQueryParamsService.save(genCustomListQueryParams); + + orderNo++; + } + } + + int orderNo = 1; + for (GenCustomListDetailVo detail : data.getDetails()) { + GenCustomListDetail genCustomListDetail = new GenCustomListDetail(); + genCustomListDetail.setId(IdUtil.getId()); + genCustomListDetail.setCustomListId(record.getId()); + genCustomListDetail.setDataEntityId(detail.getId()); + genCustomListDetail.setRelaId(detail.getRelaId()); + genCustomListDetail.setWidthType( + EnumUtil.getByCode(GenQueryWidthType.class, detail.getWidthType())); + genCustomListDetail.setWidth(detail.getWidth()); + genCustomListDetail.setSortable(detail.getSortable()); + genCustomListDetail.setOrderNo(orderNo); + genCustomListDetail.setType( + EnumUtil.getByCode(GenCustomListDetailType.class, detail.getType())); + if (genCustomListDetail.getType() == GenCustomListDetailType.CUSTOM) { + genCustomListDetail.setDataEntityId(null); + } + if (!StringUtil.isBlank(detail.getFormatter())) { + genCustomListDetail.setFormatter(detail.getFormatter()); + } + + genCustomListDetailService.save(genCustomListDetail); + + orderNo++; + } + + if (!CollectionUtil.isEmpty(data.getToolbars())) { + orderNo = 1; + for (GenCustomListToolbarVo tb : data.getToolbars()) { + GenCustomListToolbar toolbar = new GenCustomListToolbar(); + toolbar.setId(IdUtil.getId()); + toolbar.setCustomListId(record.getId()); + toolbar.setName(tb.getName()); + toolbar.setViewType(EnumUtil.getByCode(GenCustomListBtnViewType.class, tb.getViewType())); + toolbar.setBtnType(EnumUtil.getByCode(GenCustomListBtnType.class, tb.getBtnType())); + toolbar.setBtnConfig(tb.getBtnConfig()); + if (!StringUtil.isBlank(tb.getIcon())) { + toolbar.setIcon(tb.getIcon()); + } + toolbar.setOrderNo(orderNo); + orderNo++; + + genCustomListToolbarService.save(toolbar); + } + } + + if (!CollectionUtil.isEmpty(data.getHandleColumns())) { + orderNo = 1; + for (GenCustomListHandleColumnVo hd : data.getHandleColumns()) { + GenCustomListHandleColumn handleColumn = new GenCustomListHandleColumn(); + handleColumn.setId(IdUtil.getId()); + handleColumn.setCustomListId(record.getId()); + handleColumn.setName(hd.getName()); + handleColumn + .setViewType(EnumUtil.getByCode(GenCustomListBtnViewType.class, hd.getViewType())); + handleColumn.setBtnType(EnumUtil.getByCode(GenCustomListBtnType.class, hd.getBtnType())); + handleColumn.setBtnConfig(hd.getBtnConfig()); + if (!StringUtil.isBlank(hd.getIcon())) { + handleColumn.setIcon(hd.getIcon()); + } + handleColumn.setOrderNo(orderNo); + handleColumn.setWidth(hd.getWidth()); + orderNo++; + + genCustomListHandleColumnService.save(handleColumn); + } + } + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenCustomListVo data) { + GenCustomList record = this.getById(data.getId()); + if (record == null) { + throw new DefaultClientException("自定义列表不存在!"); + } + + record.setHasPage(data.getHasPage()); + record.setTreeData(data.getTreeData()); + + // 如果是树形列表,那么分页必须禁用 + // 如果分页没有禁用,那么一定不是树形列表 + if (record.getTreeData()) { + record.setHasPage(Boolean.FALSE); + } + + if (record.getHasPage()) { + record.setTreeData(Boolean.FALSE); + } + + if (record.getTreeData()) { + + if (StringUtil.isBlank(data.getTreePidColumn())) { + throw new DefaultClientException("父级ID字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreePidColumnRelaId())) { + throw new DefaultClientException("父级ID字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreeNodeColumn())) { + throw new DefaultClientException("树形节点字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreeNodeColumnRelaId())) { + throw new DefaultClientException("树形节点字段不能为空!"); + } + + if (StringUtil.isBlank(data.getTreeChildrenKey())) { + throw new DefaultClientException("子节点Key值不能为空!"); + } + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(GenCustomList.class) + .eq(GenCustomList::getId, data.getId()).set(GenCustomList::getName, data.getName()) + .set(GenCustomList::getCategoryId, + StringUtil.isBlank(data.getCategoryId()) ? null : data.getCategoryId()) + .set(GenCustomList::getListType, + EnumUtil.getByCode(GenCustomListType.class, data.getListType())) + .set(GenCustomList::getLabelWidth, data.getLabelWidth()) + .set(GenCustomList::getHasPage, record.getHasPage()) + .set(GenCustomList::getTreeData, record.getTreeData()) + .set(GenCustomList::getIdColumn, data.getIdColumn()) + .set(GenCustomList::getIdColumnRelaId, data.getIdColumnRelaId()) + .set(GenCustomList::getTreePidColumn, record.getTreeData() ? data.getTreePidColumn() : null) + .set(GenCustomList::getTreePidColumnRelaId, + record.getTreeData() ? data.getTreePidColumnRelaId() : null) + .set(GenCustomList::getTreeNodeColumn, + record.getTreeData() ? data.getTreeNodeColumn() : null) + .set(GenCustomList::getTreeNodeColumnRelaId, + record.getTreeData() ? data.getTreeNodeColumnRelaId() : null) + .set(GenCustomList::getTreeChildrenKey, + record.getTreeData() ? data.getTreeChildrenKey() : null) + .set(GenCustomList::getQueryPrefixSql, + StringUtil.isBlank(data.getQueryPrefixSql()) ? StringPool.EMPTY_STR + : data.getQueryPrefixSql()) + .set(GenCustomList::getQuerySuffixSql, + StringUtil.isBlank(data.getQuerySuffixSql()) ? StringPool.EMPTY_STR + : data.getQuerySuffixSql()) + .set(GenCustomList::getSuffixSql, + StringUtil.isBlank(data.getSuffixSql()) ? StringPool.EMPTY_STR : data.getSuffixSql()) + .set(GenCustomList::getDescription, + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR + : data.getDescription()).set(GenCustomList::getAvailable, data.getAvailable()) + .set(GenCustomList::getAllowExport, data.getAllowExport()); + + this.update(updateWrapper); + + genCustomListDetailService.deleteByCustomListId(data.getId()); + genCustomListQueryParamsService.deleteByCustomListId(data.getId()); + + if (!CollectionUtil.isEmpty(data.getQueryParams())) { + int orderNo = 1; + for (GenCustomListQueryParamsVo queryParam : data.getQueryParams()) { + GenCustomListQueryParams genCustomListQueryParams = new GenCustomListQueryParams(); + genCustomListQueryParams.setId(IdUtil.getId()); + genCustomListQueryParams.setCustomListId(record.getId()); + genCustomListQueryParams.setRelaId(queryParam.getRelaId()); + genCustomListQueryParams.setDataEntityId(queryParam.getId()); + genCustomListQueryParams.setQueryType( + EnumUtil.getByCode(GenQueryType.class, queryParam.getQueryType())); + genCustomListQueryParams.setFrontShow(queryParam.getFrontShow()); + genCustomListQueryParams.setFormWidth(queryParam.getFormWidth()); + genCustomListQueryParams.setDefaultValue(queryParam.getDefaultValue() == null ? null + : queryParam.getDefaultValue() instanceof String ? queryParam.getDefaultValue() + .toString() : JsonUtil.toJsonString(queryParam.getDefaultValue())); + genCustomListQueryParams.setOrderNo(orderNo); + genCustomListQueryParams.setType( + EnumUtil.getByCode(GenCustomListDetailType.class, queryParam.getType())); + + genCustomListQueryParamsService.save(genCustomListQueryParams); + + orderNo++; + } + } + + int orderNo = 1; + for (GenCustomListDetailVo detail : data.getDetails()) { + GenCustomListDetail genCustomListDetail = new GenCustomListDetail(); + genCustomListDetail.setId(IdUtil.getId()); + genCustomListDetail.setCustomListId(record.getId()); + genCustomListDetail.setDataEntityId(detail.getId()); + genCustomListDetail.setRelaId(detail.getRelaId()); + genCustomListDetail.setWidthType( + EnumUtil.getByCode(GenQueryWidthType.class, detail.getWidthType())); + genCustomListDetail.setWidth(detail.getWidth()); + genCustomListDetail.setSortable(detail.getSortable()); + genCustomListDetail.setOrderNo(orderNo); + genCustomListDetail.setType( + EnumUtil.getByCode(GenCustomListDetailType.class, detail.getType())); + if (genCustomListDetail.getType() == GenCustomListDetailType.CUSTOM) { + genCustomListDetail.setDataEntityId(null); + } + genCustomListDetail.setFormatter(detail.getFormatter()); + + genCustomListDetailService.save(genCustomListDetail); + + orderNo++; + } + + genCustomListToolbarService.deleteByCustomListId(record.getId()); + + if (!CollectionUtil.isEmpty(data.getToolbars())) { + orderNo = 1; + for (GenCustomListToolbarVo tb : data.getToolbars()) { + GenCustomListToolbar toolbar = new GenCustomListToolbar(); + toolbar.setId(IdUtil.getId()); + toolbar.setCustomListId(record.getId()); + toolbar.setName(tb.getName()); + toolbar.setViewType(EnumUtil.getByCode(GenCustomListBtnViewType.class, tb.getViewType())); + toolbar.setBtnType(EnumUtil.getByCode(GenCustomListBtnType.class, tb.getBtnType())); + toolbar.setBtnConfig(tb.getBtnConfig()); + if (!StringUtil.isBlank(tb.getIcon())) { + toolbar.setIcon(tb.getIcon()); + } + toolbar.setOrderNo(orderNo); + orderNo++; + + genCustomListToolbarService.save(toolbar); + } + } + + genCustomListHandleColumnService.deleteByCustomListId(record.getId()); + + if (!CollectionUtil.isEmpty(data.getHandleColumns())) { + orderNo = 1; + for (GenCustomListHandleColumnVo hd : data.getHandleColumns()) { + GenCustomListHandleColumn handleColumn = new GenCustomListHandleColumn(); + handleColumn.setId(IdUtil.getId()); + handleColumn.setCustomListId(record.getId()); + handleColumn.setName(hd.getName()); + handleColumn + .setViewType(EnumUtil.getByCode(GenCustomListBtnViewType.class, hd.getViewType())); + handleColumn.setBtnType(EnumUtil.getByCode(GenCustomListBtnType.class, hd.getBtnType())); + handleColumn.setBtnConfig(hd.getBtnConfig()); + if (!StringUtil.isBlank(hd.getIcon())) { + handleColumn.setIcon(hd.getIcon()); + } + handleColumn.setWidth(hd.getWidth()); + handleColumn.setOrderNo(orderNo); + orderNo++; + + genCustomListHandleColumnService.save(handleColumn); + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(String id) { + GenCustomList data = this.getById(id); + + this.removeById(id); + genCustomListDetailService.deleteByCustomListId(id); + genCustomListQueryParamsService.deleteByCustomListId(id); + + if (data != null) { + CustomListDeleteEvent event = new CustomListDeleteEvent(this); + event.setId(id); + event.setName(data.getName()); + ApplicationUtil.publishEvent(event); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (String id : ids) { + this.delete(id); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenCustomList.class) + .set(GenCustomList::getAvailable, Boolean.TRUE).in(GenCustomList::getId, ids); + getBaseMapper().update(wrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenCustomList.class) + .set(GenCustomList::getAvailable, Boolean.FALSE).in(GenCustomList::getId, ids); + getBaseMapper().update(wrapper); + } + + @Override + public List getRelaGenDataObjIds(String objId) { + return getBaseMapper().getRelaGenDataObjIds(objId); + } + + @Override + public List getRelaGenDataEntityIds(String entityId) { + return getBaseMapper().getRelaGenDataEntityIds(entityId); + } + + @CacheEvict(value = {GenCustomList.CACHE_NAME, CustomListConfig.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + ThreadUtil.execAsync(() -> { + GenCustomSelectorService genCustomSelectorService = ApplicationUtil + .getBean(GenCustomSelectorService.class); + List ids = genCustomSelectorService.getRelaGenCustomListIds(String.valueOf(key)); + if (CollectionUtil.isNotEmpty(ids)) { + genCustomSelectorService.cleanCacheByKeys(ids); + } + }); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListToolbarServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListToolbarServiceImpl.java new file mode 100644 index 0000000..ee9b94e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomListToolbarServiceImpl.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenCustomListToolbar; +import com.lframework.xingyun.template.gen.mappers.GenCustomListToolbarMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListToolbarService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomListToolbarServiceImpl extends + BaseMpServiceImpl implements + GenCustomListToolbarService { + + @Override + public List getByCustomListId(String customListId) { + return getBaseMapper().getByCustomListId(customListId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByCustomListId(String customListId) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(GenCustomListToolbar.class) + .eq(GenCustomListToolbar::getCustomListId, customListId); + this.remove(deleteWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageCategoryServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageCategoryServiceImpl.java new file mode 100644 index 0000000..d60fd03 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageCategoryServiceImpl.java @@ -0,0 +1,135 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.service.GenCustomPageCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomPageService; +import com.lframework.xingyun.template.gen.vo.custom.page.category.CreateGenCustomPageCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.page.category.UpdateGenCustomPageCategoryVo; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.xingyun.template.gen.mappers.GenCustomPageCategoryMapper; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomPageCategoryServiceImpl extends + BaseMpServiceImpl implements + GenCustomPageCategoryService { + + @Autowired + private GenCustomPageService genCustomPageService; + + @Cacheable(value = GenCustomPageCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Cacheable(value = GenCustomPageCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenCustomPageCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenCustomPageCategoryVo vo) { + + Wrapper checkWrapper = Wrappers + .lambdaQuery(GenCustomPageCategory.class) + .eq(GenCustomPageCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenCustomPageCategory.class) + .eq(GenCustomPageCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenCustomPageCategory record = new GenCustomPageCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + record.setParentId(StringUtil.isBlank(vo.getParentId()) ? null : vo.getParentId()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenCustomPageCategoryVo vo) { + Wrapper checkWrapper = Wrappers + .lambdaQuery(GenCustomPageCategory.class) + .eq(GenCustomPageCategory::getCode, vo.getCode()) + .ne(GenCustomPageCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenCustomPageCategory.class) + .eq(GenCustomPageCategory::getName, vo.getName()) + .ne(GenCustomPageCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenCustomPageCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("自定义列表分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + Set categoryIds = new HashSet<>(); + categoryIds.add(id); + while (true) { + Wrapper queryCategoryWrapper = Wrappers.lambdaQuery( + GenCustomPageCategory.class).in(GenCustomPageCategory::getParentId, categoryIds); + List categoryList = this.list(queryCategoryWrapper); + + int oldSize = categoryIds.size(); + categoryIds.addAll( + categoryList.stream().map(GenCustomPageCategory::getId).collect(Collectors.toList())); + if (oldSize == categoryIds.size()) { + break; + } + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenCustomPage.class) + .in(GenCustomPage::getCategoryId, categoryIds); + if (genCustomPageService.count(queryWrapper) > 0) { + throw new DefaultClientException("此分类或其子分类下存在自定义页面,无法删除!"); + } + + this.removeByIds(categoryIds); + } + + @CacheEvict(value = GenCustomPageCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageServiceImpl.java new file mode 100644 index 0000000..b735f9e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomPageServiceImpl.java @@ -0,0 +1,129 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.components.custom.page.CustomPageConfig; +import com.lframework.xingyun.template.gen.service.GenCustomPageService; +import com.lframework.xingyun.template.gen.vo.custom.page.CreateGenCustomPageVo; +import com.lframework.xingyun.template.gen.vo.custom.page.GenCustomPageSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.page.QueryGenCustomPageVo; +import com.lframework.xingyun.template.gen.vo.custom.page.UpdateGenCustomPageVo; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.mappers.GenCustomPageMapper; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomPageServiceImpl extends + BaseMpServiceImpl implements + GenCustomPageService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryGenCustomPageVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryGenCustomPageVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomPageSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenCustomPage.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenCustomPage findById(Integer id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Integer create(CreateGenCustomPageVo data) { + GenCustomPage record = new GenCustomPage(); + + record.setName(data.getName()); + if (!StringUtil.isBlank(data.getCategoryId())) { + record.setCategoryId(data.getCategoryId()); + } + record.setPageCode(data.getPageCode()); + record.setScriptCode(data.getScriptCode()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenCustomPageVo data) { + GenCustomPage record = this.getById(data.getId()); + if (record == null) { + throw new DefaultClientException("自定义表单不存在!"); + } + + record.setPageCode(data.getPageCode()); + record.setScriptCode(data.getScriptCode()); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + this.updateAllColumnById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(Integer id) { + this.removeById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (Integer id : ids) { + this.delete(id); + } + } + + @CacheEvict(value = {GenCustomPage.CACHE_NAME, + CustomPageConfig.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + super.cleanCacheByKey(key); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorCategoryServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorCategoryServiceImpl.java new file mode 100644 index 0000000..4e1ae60 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorCategoryServiceImpl.java @@ -0,0 +1,134 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.xingyun.template.gen.mappers.GenCustomSelectorCategoryMapper; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorCategoryService; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.CreateGenCustomSelectorCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.GenCustomSelectorCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.UpdateGenCustomSelectorCategoryVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomSelectorCategoryServiceImpl extends + BaseMpServiceImpl implements + GenCustomSelectorCategoryService { + + @Autowired + private GenCustomSelectorService genCustomSelectorService; + + @Cacheable(value = GenCustomSelectorCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomSelectorCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenCustomSelectorCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenCustomSelectorCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenCustomSelectorCategoryVo vo) { + + Wrapper checkWrapper = Wrappers + .lambdaQuery(GenCustomSelectorCategory.class) + .eq(GenCustomSelectorCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenCustomSelectorCategory.class) + .eq(GenCustomSelectorCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenCustomSelectorCategory record = new GenCustomSelectorCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenCustomSelectorCategoryVo vo) { + Wrapper checkWrapper = Wrappers + .lambdaQuery(GenCustomSelectorCategory.class) + .eq(GenCustomSelectorCategory::getCode, vo.getCode()) + .ne(GenCustomSelectorCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenCustomSelectorCategory.class) + .eq(GenCustomSelectorCategory::getName, vo.getName()) + .ne(GenCustomSelectorCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenCustomSelectorCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("自定义列表分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenCustomSelector.class) + .eq(GenCustomSelector::getCategoryId, id); + if (genCustomSelectorService.count(queryWrapper) > 0) { + throw new DefaultClientException("此分类下存在自定义选择器,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = GenCustomSelectorCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorServiceImpl.java new file mode 100644 index 0000000..d7f0c74 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenCustomSelectorServiceImpl.java @@ -0,0 +1,184 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.components.custom.selector.CustomSelectorConfig; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.mappers.GenCustomSelectorMapper; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import com.lframework.xingyun.template.gen.vo.custom.selector.CreateGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.GenCustomSelectorSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.QueryGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.UpdateGenCustomSelectorVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenCustomSelectorServiceImpl extends + BaseMpServiceImpl implements + GenCustomSelectorService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryGenCustomSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryGenCustomSelectorVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomSelectorSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenCustomSelector.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenCustomSelector findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenCustomSelectorVo data) { + GenCustomSelector record = new GenCustomSelector(); + + record.setId(IdUtil.getId()); + record.setName(data.getName()); + if (!StringUtil.isBlank(data.getCategoryId())) { + record.setCategoryId(data.getCategoryId()); + } + record.setCustomListId(data.getCustomListId()); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + record.setIdColumn(data.getIdColumn()); + record.setIdColumnRelaId(data.getIdColumnRelaId()); + record.setNameColumn(data.getNameColumn()); + record.setNameColumnRelaId(data.getNameColumnRelaId()); + record.setDialogTittle( + StringUtil.isBlank(data.getDialogTittle()) ? StringPool.EMPTY_STR : data.getDialogTittle()); + record.setDialogWidth(data.getDialogWidth()); + record.setPlaceholder( + StringUtil.isBlank(data.getPlaceholder()) ? StringPool.EMPTY_STR : data.getPlaceholder()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenCustomSelectorVo data) { + GenCustomSelector record = this.getById(data.getId()); + if (record == null) { + throw new DefaultClientException("自定义列表不存在!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(GenCustomSelector.class) + .eq(GenCustomSelector::getId, data.getId()).set(GenCustomSelector::getName, data.getName()) + .set(GenCustomSelector::getCategoryId, + StringUtil.isBlank(data.getCategoryId()) ? null : data.getCategoryId()) + .set(GenCustomSelector::getDialogTittle, + StringUtil.isBlank(data.getDialogTittle()) ? StringPool.EMPTY_STR + : data.getDialogTittle()) + .set(GenCustomSelector::getDialogWidth, data.getDialogWidth()) + .set(GenCustomSelector::getPlaceholder, + StringUtil.isBlank(data.getPlaceholder()) ? StringPool.EMPTY_STR + : data.getPlaceholder()) + .set(GenCustomSelector::getIdColumn, data.getIdColumn()) + .set(GenCustomSelector::getIdColumnRelaId, data.getIdColumnRelaId()) + .set(GenCustomSelector::getNameColumn, data.getNameColumn()) + .set(GenCustomSelector::getNameColumnRelaId, data.getNameColumnRelaId()) + .set(GenCustomSelector::getDescription, + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR + : data.getDescription()).set(GenCustomSelector::getAvailable, data.getAvailable()); + + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(String id) { + this.removeById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (String id : ids) { + this.delete(id); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenCustomSelector.class) + .set(GenCustomSelector::getAvailable, Boolean.TRUE).in(GenCustomSelector::getId, ids); + getBaseMapper().update(wrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenCustomSelector.class) + .set(GenCustomSelector::getAvailable, Boolean.FALSE).in(GenCustomSelector::getId, ids); + getBaseMapper().update(wrapper); + } + + @Override + public List getRelaGenCustomListIds(String customListId) { + return getBaseMapper().getRelaGenCustomListIds(customListId); + } + + @CacheEvict(value = {GenCustomSelector.CACHE_NAME, CustomSelectorConfig.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + super.cleanCacheByKey(key); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityCategoryServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityCategoryServiceImpl.java new file mode 100644 index 0000000..c5a5f39 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityCategoryServiceImpl.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.mappers.GenDataEntityCategoryMapper; +import com.lframework.xingyun.template.gen.service.GenDataEntityCategoryService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.vo.data.entity.category.CreateGenDataEntityCategoryVo; +import com.lframework.xingyun.template.gen.vo.data.entity.category.GenDataEntityCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.category.UpdateGenDataEntityCategoryVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataEntityCategoryServiceImpl extends + BaseMpServiceImpl implements + GenDataEntityCategoryService { + + @Autowired + private GenDataEntityService genDataEntityService; + + @Cacheable(value = GenDataEntityCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenDataEntityCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenDataEntityCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenDataEntityCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenDataEntityCategoryVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(GenDataEntityCategory.class) + .eq(GenDataEntityCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenDataEntityCategory.class) + .eq(GenDataEntityCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenDataEntityCategory record = new GenDataEntityCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenDataEntityCategoryVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(GenDataEntityCategory.class) + .eq(GenDataEntityCategory::getCode, vo.getCode()) + .ne(GenDataEntityCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenDataEntityCategory.class) + .eq(GenDataEntityCategory::getName, vo.getName()) + .ne(GenDataEntityCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenDataEntityCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据实体分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataEntity.class) + .eq(GenDataEntity::getCategoryId, id); + if (genDataEntityService.count(queryWrapper) > 0) { + throw new DefaultClientException("此分类下存在数据实体,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = GenDataEntityCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityDetailServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityDetailServiceImpl.java new file mode 100644 index 0000000..392af9a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityDetailServiceImpl.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.mappers.GenDataEntityDetailMapper; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntityDetailSelectorVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataEntityDetailServiceImpl extends + BaseMpServiceImpl implements + GenDataEntityDetailService { + + @Override + public List getByEntityId(String entityId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataEntityDetail.class) + .eq(GenDataEntityDetail::getEntityId, entityId) + .orderByAsc(GenDataEntityDetail::getColumnOrder); + + return getBaseMapper().selectList(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByEntityId(String entityId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataEntityDetail.class) + .eq(GenDataEntityDetail::getEntityId, entityId); + getBaseMapper().delete(queryWrapper); + } + + @Override + public List selector(GenDataEntityDetailSelectorVo vo) { + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataEntityDetail.class) + .eq(GenDataEntityDetail::getEntityId, vo.getEntityId()) + .orderByAsc(GenDataEntityDetail::getColumnOrder); + + return getBaseMapper().selectList(queryWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityServiceImpl.java new file mode 100644 index 0000000..2d1f8ce --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataEntityServiceImpl.java @@ -0,0 +1,546 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.converters.GenStringConverter; +import com.lframework.xingyun.template.gen.converters.GenViewTypeConverter; +import com.lframework.xingyun.template.gen.dto.data.entity.DataEntityGenerateDto; +import com.lframework.xingyun.template.gen.dto.gen.GenCreateColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenDetailColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.gen.dto.gen.GenQueryColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenQueryParamsColumnConfigDto; +import com.lframework.xingyun.template.gen.dto.gen.GenUpdateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.xingyun.template.gen.enums.GenConvertType; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenKeyType; +import com.lframework.xingyun.template.gen.enums.GenOrderType; +import com.lframework.xingyun.template.gen.enums.GenStatus; +import com.lframework.xingyun.template.gen.enums.GenTemplateType; +import com.lframework.xingyun.template.gen.enums.GenViewType; +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.mappers.GenDataEntityMapper; +import com.lframework.xingyun.template.gen.service.GenCreateColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDataEntityService; +import com.lframework.xingyun.template.gen.service.GenDetailColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenQueryColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenQueryParamsColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenUpdateColumnConfigService; +import com.lframework.xingyun.template.gen.service.GenerateInfoService; +import com.lframework.xingyun.template.gen.service.SimpleDBService; +import com.lframework.xingyun.template.gen.vo.data.entity.CreateDataEntityVo; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntityDetailVo; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntitySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.QueryDataEntityVo; +import com.lframework.xingyun.template.gen.vo.data.entity.UpdateDataEntityGenerateVo; +import com.lframework.xingyun.template.gen.vo.data.entity.UpdateDataEntityVo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateGenerateInfoVo; +import com.lframework.xingyun.template.gen.dto.simpledb.OriSimpleTableDto; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataEntityServiceImpl extends + BaseMpServiceImpl implements GenDataEntityService { + + @Autowired + private GenerateInfoService generateInfoService; + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Autowired + private SimpleDBService simpleDBService; + + @Autowired + private GenCreateColumnConfigService genCreateColumnConfigService; + + @Autowired + private GenUpdateColumnConfigService genUpdateColumnConfigService; + + @Autowired + private GenQueryColumnConfigService genQueryColumnConfigService; + + @Autowired + private GenQueryParamsColumnConfigService genQueryParamsColumnConfigService; + + @Autowired + private GenDetailColumnConfigService genDetailColumnConfigService; + + @Autowired + private GenViewTypeConverter genViewTypeConverter; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QueryDataEntityVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryDataEntityVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenDataEntitySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public GenDataEntity findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateDataEntityVo data) { + GenDataEntity record = new GenDataEntity(); + record.setId(IdUtil.getId()); + record.setName(data.getName()); + if (!StringUtil.isBlank(data.getCategoryId())) { + record.setCategoryId(data.getCategoryId()); + } + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + + + OriSimpleTableDto table = simpleDBService.getByTableName(data.getTableName()); + if (ObjectUtil.isNull(table)) { + throw new DefaultClientException("数据表【" + data.getTableName() + "】不存在!"); + } + + record.setTableSchema(table.getTableSchema()); + record.setTableName(table.getTableName()); + record.setEngine(table.getEngine()); + record.setTableCollation(table.getTableCollation()); + record.setTableComment(table.getTableComment()); + record.setConvertType(GenConvertType.UNDERLINE_TO_CAMEL); + + this.save(record); + + int orderNo = 1; + for (GenDataEntityDetailVo column : data.getColumns()) { + GenSimpleTableColumn columnDto = table.getColumns().stream() + .filter(t -> t.getDbColumnName().equals(column.getId())).findFirst().orElse(null); + if (columnDto == null) { + throw new DefaultClientException("字段【" + column.getId() + "】不存在!"); + } + + GenDataEntityDetail detail = this.buildDetail(column, columnDto); + detail.setId(IdUtil.getId()); + detail.setEntityId(record.getId()); + detail.setColumnOrder(orderNo); + + genDataEntityDetailService.save(detail); + + orderNo++; + } + + // 设置默认的基础设置 + UpdateGenerateInfoVo updateGenerateInfoVo = new UpdateGenerateInfoVo(); + updateGenerateInfoVo.setTemplateType(GenTemplateType.LIST.getCode()); + updateGenerateInfoVo.setPackageName("com.lframework"); + updateGenerateInfoVo.setModuleName(StringPool.EMPTY_STR); + updateGenerateInfoVo.setBizName( + GenStringConverter.convertToNormalLowerCase(GenConvertType.UNDERLINE_TO_CAMEL, + record.getTableName())); + // 强制转驼峰并且首字母大写 + String className = GenStringConverter.convertToCamelCase(GenConvertType.UNDERLINE_TO_CAMEL, + record.getTableName()); + updateGenerateInfoVo.setClassName( + className.substring(0, 1).toUpperCase() + className.substring(1)); + updateGenerateInfoVo.setClassDescription( + StringUtil.isEmpty(record.getTableComment()) ? StringPool.EMPTY_STR + : record.getTableComment()); + updateGenerateInfoVo.setKeyType(GenKeyType.SNOW_FLAKE.getCode()); + updateGenerateInfoVo.setMenuCode(StringPool.EMPTY_STR); + updateGenerateInfoVo.setMenuName(StringPool.EMPTY_STR); + updateGenerateInfoVo.setDetailSpan(4); + updateGenerateInfoVo.setIsCache(true); + updateGenerateInfoVo.setHasDelete(false); + + generateInfoService.updateGenerate(record.getId(), updateGenerateInfoVo); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateDataEntityVo vo) { + GenDataEntity record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据实体不存在!"); + } + Wrapper updateWrapper = Wrappers.lambdaUpdate(GenDataEntity.class) + .eq(GenDataEntity::getId, vo.getId()).set(GenDataEntity::getName, vo.getName()) + .set(GenDataEntity::getAvailable, vo.getAvailable()).set(GenDataEntity::getCategoryId, + StringUtil.isBlank(vo.getCategoryId()) ? null : vo.getCategoryId()) + .set(GenDataEntity::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + this.update(updateWrapper); + + List columnDtos = genDataEntityDetailService.getByEntityId(record.getId()); + + int orderNo = 1; + for (GenDataEntityDetailVo column : vo.getColumns()) { + GenDataEntityDetail detail = columnDtos.stream() + .filter(t -> t.getId().equals(column.getId())).findFirst().orElse(null); + detail.setName(column.getName()); + + detail.setDataType(EnumUtil.getByCode(GenDataType.class, column.getDataType())); + detail.setDescription(column.getDescription()); + detail.setViewType(EnumUtil.getByCode(GenViewType.class, column.getViewType())); + detail.setFixEnum(column.getFixEnum()); + detail.setEnumBack(column.getEnumBack()); + detail.setEnumFront(column.getEnumFront()); + detail.setRegularExpression(column.getRegularExpression()); + detail.setIsOrder(column.getIsOrder()); + detail.setOrderType(EnumUtil.getByCode(GenOrderType.class, column.getOrderType())); + detail.setLen(column.getLen()); + detail.setDecimals(column.getDecimals()); + detail.setDataDicId(StringPool.EMPTY_STR); + detail.setCustomSelectorId(StringPool.EMPTY_STR); + if (!StringUtil.isBlank(column.getDataDicId()) + && detail.getViewType() == GenViewType.DATA_DIC) { + detail.setDataDicId(column.getDataDicId()); + } + if (!StringUtil.isBlank(column.getCustomSelectorId()) + && detail.getViewType() == GenViewType.CUSTOM_SELECTOR) { + detail.setCustomSelectorId(column.getCustomSelectorId()); + } + + if (!genViewTypeConverter.canConvert(detail.getViewType(), detail.getDataType())) { + List viewTypes = genViewTypeConverter.convert(detail.getDataType()); + throw new DefaultClientException( + "字段【" + detail.getName() + "】数据类型和显示类型不匹配,当前数据类型为【" + detail.getDataType().getDesc() + + "】," + (!CollectionUtil.isEmpty(viewTypes) ? "显示类型只能为【" + CollectionUtil.join( + genViewTypeConverter.convert(detail.getDataType()).stream() + .map(GenViewType::getDesc) + .collect(Collectors.toList()), StringPool.STR_SPLIT_CN) + "】" : "暂不支持显示此数据类型")); + } + detail.setColumnOrder(orderNo); + + genDataEntityDetailService.updateById(detail); + + orderNo++; + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(@NonNull String id) { + + GenDataEntity record = getBaseMapper().selectById(id); + if (record == null) { + throw new DefaultClientException("数据实体不存在!"); + } + + List columns = genDataEntityDetailService.getByEntityId(id); + List columnIds = columns.stream().map(GenDataEntityDetail::getId) + .collect(Collectors.toList()); + + getBaseMapper().deleteById(id); + + genDataEntityDetailService.deleteByEntityId(id); + + DataEntityDeleteEvent event = new DataEntityDeleteEvent(this); + event.setId(id); + event.setName(record.getName()); + event.setColumnIds(columnIds); + + ApplicationUtil.publishEvent(event); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(@NonNull List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (String id : ids) { + this.delete(id); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenDataEntity.class) + .set(GenDataEntity::getAvailable, Boolean.TRUE).in(GenDataEntity::getId, ids); + getBaseMapper().update(wrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenDataEntity.class) + .set(GenDataEntity::getAvailable, Boolean.FALSE).in(GenDataEntity::getId, ids); + getBaseMapper().update(wrapper); + } + + @Override + public DataEntityGenerateDto getGenerateById(String id) { + DataEntityGenerateDto result = new DataEntityGenerateDto(); + + List columns = genDataEntityDetailService.getByEntityId(id); + result.setColumns(columns); + + GenGenerateInfoDto generateInfo = generateInfoService.getByEntityId(id); + result.setGenerateInfo(generateInfo); + + List createColumnConfigDtos = genCreateColumnConfigService.getByDataEntityId( + id); + result.setCreateConfigs(createColumnConfigDtos); + + List updateColumnConfigDtos = genUpdateColumnConfigService.getByDataEntityId( + id); + result.setUpdateConfigs(updateColumnConfigDtos); + + List queryColumnConfigDtos = genQueryColumnConfigService.getByDataEntityId( + id); + result.setQueryConfigs(queryColumnConfigDtos); + + List queryParamsColumnConfigDtos = genQueryParamsColumnConfigService.getByDataEntityId( + id); + result.setQueryParamsConfigs(queryParamsColumnConfigDtos); + + List detailColumnConfigDtos = genDetailColumnConfigService.getByDataEntityId( + id); + result.setDetailConfigs(detailColumnConfigDtos); + + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(UpdateDataEntityGenerateVo vo) { + + generateInfoService.updateGenerate(vo.getId(), vo.getGenerateInfo()); + + genCreateColumnConfigService.updateGenerate(vo.getId(), vo.getCreateConfigs()); + + genUpdateColumnConfigService.updateGenerate(vo.getId(), vo.getUpdateConfigs()); + + genQueryColumnConfigService.updateGenerate(vo.getId(), vo.getQueryConfigs()); + + genQueryParamsColumnConfigService.updateGenerate(vo.getId(), vo.getQueryParamsConfigs()); + + genDetailColumnConfigService.updateGenerate(vo.getId(), vo.getDetailConfigs()); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(GenDataEntity.class) + .set(GenDataEntity::getGenStatus, GenStatus.SET_GEN).eq(GenDataEntity::getId, vo.getId()); + getBaseMapper().update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void syncTable(String id) { + // 查询simpleTable + GenDataEntity table = this.getById(id); + if (table == null) { + throw new DefaultClientException("数据表不存在!"); + } + List columns = genDataEntityDetailService.getByEntityId(table.getId()); + + // 最新的数据库结构 + OriSimpleTableDto oriTable = simpleDBService.getByTableName(table.getTableName()); + List oriColumns = oriTable.getColumns(); + + // 1、列是否匹配 + // db中是否有新增列 + List finalColumns = columns; + List newDbColumns = oriColumns.stream().filter( + t -> finalColumns.stream().noneMatch(c -> c.getDbColumnName().equals(t.getDbColumnName()))) + .collect(Collectors.toList()); + // 类型发生变化的列 + List changeTypeColumns = oriColumns.stream().filter( + t -> finalColumns.stream().anyMatch( + c -> c.getDbColumnName().equals(t.getDbColumnName()) && c.getDbDataType() != t.getDataType())) + .collect(Collectors.toList()); + if (!CollectionUtil.isEmpty(changeTypeColumns)) { + newDbColumns.addAll(changeTypeColumns); + } + + // db中是否有删除列 + List deleteDbColumns = columns.stream().filter( + t -> oriColumns.stream().noneMatch(c -> c.getDbColumnName().equals(t.getDbColumnName())) + || changeTypeColumns.stream() + .anyMatch(c2 -> c2.getDbColumnName().equals(t.getDbColumnName()))) + .collect(Collectors.toList()); + + // 先删除、后新增 + if (!CollectionUtil.isEmpty(deleteDbColumns)) { + for (GenDataEntityDetail deleteDbColumn : deleteDbColumns) { + genDataEntityDetailService.removeById(deleteDbColumn.getId()); + // 发布删除事件 + DataEntityDetailDeleteEvent event = new DataEntityDetailDeleteEvent(this); + event.setId(deleteDbColumn.getId()); + event.setName(deleteDbColumn.getDbColumnName()); + ApplicationUtil.publishEvent(event); + } + } + + List details = genDataEntityDetailService.getByEntityId(table.getId()); + if (CollectionUtil.isEmpty(details)) { + details = new ArrayList<>(); + } + int orderNo = 1; + for (GenDataEntityDetail detail : details) { + detail.setColumnOrder(orderNo); + genDataEntityDetailService.updateById(detail); + orderNo++; + } + + table = this.getById(id); + columns = details; + + orderNo = 1; + for (GenDataEntityDetail column : columns) { + column.setOrdinalPosition(orderNo); + genDataEntityDetailService.updateById(column); + orderNo++; + } + + if (!CollectionUtil.isEmpty(newDbColumns)) { + for (GenSimpleTableColumn columnDto : newDbColumns) { + GenDataEntityDetail detail = this.buildDetail(columnDto); + detail.setId(IdUtil.getId()); + detail.setColumnOrder(orderNo); + detail.setEntityId(table.getId()); + genDataEntityDetailService.save(detail); + + orderNo++; + } + } + } + + private GenDataEntityDetail buildDetail(GenSimpleTableColumn columnDto) { + GenDataEntityDetail detail = new GenDataEntityDetail(); + + detail.setName(columnDto.getColumnComment()); + detail.setColumnName(GenStringConverter.convertToCamelCase(GenConvertType.UNDERLINE_TO_CAMEL, + columnDto.getDbColumnName())); + detail.setIsKey(columnDto.getIsKey()); + detail.setDataType(columnDto.getDataType()); + List viewTypes = genViewTypeConverter.convert(detail.getDataType()); + if (CollectionUtil.isEmpty(viewTypes)) { + throw new DefaultClientException("字段:" + columnDto.getDbColumnName() + "类型暂不支持!"); + } + detail.setViewType(viewTypes.get(0)); + detail.setFixEnum(Boolean.FALSE); + detail.setIsOrder(Boolean.FALSE); + + detail.setDbColumnName(columnDto.getDbColumnName()); + detail.setDbDataType(columnDto.getDataType()); + detail.setIsNullable(columnDto.getIsNullable()); + detail.setIsKey(columnDto.getIsKey()); + detail.setColumnDefault(columnDto.getColumnDefault()); + detail.setOrdinalPosition(columnDto.getOrdinalPosition()); + detail.setColumnComment(columnDto.getColumnComment()); + detail.setDbLen(columnDto.getLen()); + detail.setDbDecimals(columnDto.getDecimals()); + + return detail; + } + + private GenDataEntityDetail buildDetail(GenDataEntityDetailVo column, + GenSimpleTableColumn columnDto) { + GenDataEntityDetail detail = new GenDataEntityDetail(); + detail.setColumnName(GenStringConverter.convertToCamelCase(GenConvertType.UNDERLINE_TO_CAMEL, + columnDto.getDbColumnName())); + detail.setIsKey(columnDto.getIsKey()); + + detail.setName(column.getName()); + detail.setDataType(EnumUtil.getByCode(GenDataType.class, column.getDataType())); + detail.setDescription(column.getDescription()); + detail.setViewType(EnumUtil.getByCode(GenViewType.class, column.getViewType())); + detail.setFixEnum(column.getFixEnum()); + detail.setEnumBack(column.getEnumBack()); + detail.setEnumFront(column.getEnumFront()); + detail.setRegularExpression(column.getRegularExpression()); + detail.setIsOrder(column.getIsOrder()); + detail.setOrderType(EnumUtil.getByCode(GenOrderType.class, column.getOrderType())); + detail.setLen(column.getLen()); + detail.setDecimals(column.getDecimals()); + detail.setDataDicId(StringPool.EMPTY_STR); + detail.setCustomSelectorId(StringPool.EMPTY_STR); + if (!StringUtil.isBlank(column.getDataDicId()) + && detail.getViewType() == GenViewType.DATA_DIC) { + detail.setDataDicId(column.getDataDicId()); + } + if (!StringUtil.isBlank(column.getCustomSelectorId()) + && detail.getViewType() == GenViewType.CUSTOM_SELECTOR) { + detail.setCustomSelectorId(column.getCustomSelectorId()); + } + detail.setDbColumnName(columnDto.getDbColumnName()); + detail.setDbDataType(columnDto.getDataType()); + detail.setIsNullable(columnDto.getIsNullable()); + detail.setColumnDefault(columnDto.getColumnDefault()); + detail.setOrdinalPosition(columnDto.getOrdinalPosition()); + detail.setColumnComment(columnDto.getColumnComment()); + detail.setDbLen(columnDto.getLen()); + detail.setDbDecimals(columnDto.getDecimals()); + + if (!genViewTypeConverter.canConvert(detail.getViewType(), detail.getDataType())) { + List viewTypes = genViewTypeConverter.convert(detail.getDataType()); + throw new DefaultClientException( + "字段【" + detail.getName() + "】数据类型和显示类型不匹配,当前数据类型为【" + detail.getDataType().getDesc() + + "】," + (!CollectionUtil.isEmpty(viewTypes) ? "显示类型只能为【" + CollectionUtil.join( + genViewTypeConverter.convert(detail.getDataType()).stream().map(GenViewType::getDesc) + .collect(Collectors.toList()), StringPool.STR_SPLIT_CN) + "】" : "暂不支持显示此数据类型")); + } + + return detail; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjCategoryServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjCategoryServiceImpl.java new file mode 100644 index 0000000..a7f25b7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjCategoryServiceImpl.java @@ -0,0 +1,132 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.mappers.GenDataObjCategoryMapper; +import com.lframework.xingyun.template.gen.service.GenDataObjCategoryService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import com.lframework.xingyun.template.gen.vo.data.obj.category.CreateGenDataObjCategoryVo; +import com.lframework.xingyun.template.gen.vo.data.obj.category.GenDataObjCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.category.UpdateGenDataObjCategoryVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataObjCategoryServiceImpl extends + BaseMpServiceImpl implements + GenDataObjCategoryService { + + @Autowired + private GenDataObjService genDataObjService; + + @Cacheable(value = GenDataObjCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenDataObjCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenDataObjCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenDataObjCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenDataObjCategoryVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(GenDataObjCategory.class) + .eq(GenDataObjCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenDataObjCategory.class) + .eq(GenDataObjCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenDataObjCategory record = new GenDataObjCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenDataObjCategoryVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(GenDataObjCategory.class) + .eq(GenDataObjCategory::getCode, vo.getCode()) + .ne(GenDataObjCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(GenDataObjCategory.class) + .eq(GenDataObjCategory::getName, vo.getName()) + .ne(GenDataObjCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + GenDataObjCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据对象分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataObj.class) + .eq(GenDataObj::getCategoryId, id); + if (genDataObjService.count(queryWrapper) > 0) { + throw new DefaultClientException("此分类下存在数据对象,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = GenDataObjCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjDetailServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjDetailServiceImpl.java new file mode 100644 index 0000000..eebfa3c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjDetailServiceImpl.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.mappers.GenDataObjDetailMapper; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataObjDetailServiceImpl extends + BaseMpServiceImpl implements + GenDataObjDetailService { + + @Override + public List getByObjId(String objId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataObjDetail.class) + .eq(GenDataObjDetail::getDataObjId, objId).orderByAsc(GenDataObjDetail::getOrderNo); + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByObjId(String objId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(GenDataObjDetail.class) + .eq(GenDataObjDetail::getDataObjId, objId); + getBaseMapper().delete(deleteWrapper); + } + + @Override + public Boolean entityDetailIsRela(String entityDetailId) { + return getBaseMapper().entityDetailIsRela(entityDetailId); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjQueryDetailServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjQueryDetailServiceImpl.java new file mode 100644 index 0000000..eae2e8e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjQueryDetailServiceImpl.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.xingyun.template.gen.mappers.GenDataObjQueryDetailMapper; +import com.lframework.xingyun.template.gen.service.GenDataObjQueryDetailService; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataObjQueryDetailServiceImpl extends + BaseMpServiceImpl implements + GenDataObjQueryDetailService { + + @Override + public List getByObjId(String objId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataObjQueryDetail.class) + .eq(GenDataObjQueryDetail::getDataObjId, objId) + .orderByAsc(GenDataObjQueryDetail::getOrderNo); + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByObjId(String objId) { + Wrapper deleteWrapper = Wrappers.lambdaQuery(GenDataObjQueryDetail.class) + .eq(GenDataObjQueryDetail::getDataObjId, objId); + getBaseMapper().delete(deleteWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjServiceImpl.java new file mode 100644 index 0000000..9ebf8de --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDataObjServiceImpl.java @@ -0,0 +1,327 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryObj; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenRelaMode; +import com.lframework.xingyun.template.gen.enums.GenRelaType; +import com.lframework.xingyun.template.gen.events.DataObjDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataObjQueryDetailDeleteEvent; +import com.lframework.xingyun.template.gen.mappers.GenDataObjMapper; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjQueryDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import com.lframework.xingyun.template.gen.vo.data.obj.CreateGenDataObjVo; +import com.lframework.xingyun.template.gen.vo.data.obj.GenDataObjDetailVo; +import com.lframework.xingyun.template.gen.vo.data.obj.GenDataObjQueryDetailVo; +import com.lframework.xingyun.template.gen.vo.data.obj.GenDataObjSelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.QueryGenDataObjVo; +import com.lframework.xingyun.template.gen.vo.data.obj.UpdateGenDataObjVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDataObjServiceImpl extends + BaseMpServiceImpl implements GenDataObjService { + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Autowired + private GenDataObjQueryDetailService genDataObjQueryDetailService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryGenDataObjVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QueryGenDataObjVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + GenDataObjSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = GenDataObj.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public GenDataObj findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateGenDataObjVo data) { + + GenDataObj record = new GenDataObj(); + record.setId(IdUtil.getId()); + record.setName(data.getName()); + if (!StringUtil.isBlank(data.getCategoryId())) { + record.setCategoryId(data.getCategoryId()); + } + record.setMainTableId(data.getMainTableId()); + record.setMainTableAlias(data.getMainTableAlias()); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR : data.getDescription()); + + this.save(record); + + int orderNo = 1; + if (!CollectionUtil.isEmpty(data.getColumns())) { + for (GenDataObjDetailVo column : data.getColumns()) { + GenDataObjDetail detail = new GenDataObjDetail(); + detail.setId(IdUtil.getId()); + detail.setDataObjId(record.getId()); + detail.setMainTableDetailIds( + CollectionUtil.join(column.getMainTableDetailIds(), StringPool.STR_SPLIT)); + detail.setRelaType(EnumUtil.getByCode(GenRelaType.class, column.getRelaType())); + detail.setRelaMode(EnumUtil.getByCode(GenRelaMode.class, column.getRelaMode())); + detail.setSubTableId(column.getSubTableId()); + detail.setSubTableAlias(column.getSubTableAlias()); + detail.setSubTableDetailIds( + CollectionUtil.join(column.getSubTableDetailIds(), StringPool.STR_SPLIT)); + detail.setOrderNo(orderNo); + + genDataObjDetailService.save(detail); + + orderNo++; + } + } + + if (!CollectionUtil.isEmpty(data.getQueryColumns())) { + orderNo = 1; + for (GenDataObjQueryDetailVo queryColumn : data.getQueryColumns()) { + GenDataObjQueryDetail detail = new GenDataObjQueryDetail(); + detail.setId(IdUtil.getId()); + detail.setDataObjId(record.getId()); + detail.setCustomName(queryColumn.getCustomName()); + detail.setCustomSql(queryColumn.getCustomSql()); + detail.setCustomAlias(queryColumn.getCustomAlias()); + detail.setDataType(EnumUtil.getByCode(GenDataType.class, queryColumn.getDataType())); + detail.setOrderNo(orderNo); + + genDataObjQueryDetailService.save(detail); + + orderNo++; + } + } + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateGenDataObjVo data) { + + GenDataObj record = this.getById(data.getId()); + if (record == null) { + throw new DefaultClientException("数据对象不存在!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(GenDataObj.class) + .eq(GenDataObj::getId, record.getId()).set(GenDataObj::getName, data.getName()) + .set(GenDataObj::getMainTableAlias, data.getMainTableAlias()).set(GenDataObj::getCategoryId, + StringUtil.isBlank(data.getCategoryId()) ? null : data.getCategoryId()) + .set(GenDataObj::getDescription, + StringUtil.isBlank(data.getDescription()) ? StringPool.EMPTY_STR + : data.getDescription()).set(GenDataObj::getAvailable, data.getAvailable()); + this.update(updateWrapper); + + List queryDetails = genDataObjQueryDetailService.getByObjId( + record.getId()); + + Wrapper deleteDetailWrapper = Wrappers.lambdaQuery(GenDataObjDetail.class) + .eq(GenDataObjDetail::getDataObjId, record.getId()); + genDataObjDetailService.remove(deleteDetailWrapper); + + Wrapper deleteQueryDetailWrapper = Wrappers.lambdaQuery( + GenDataObjQueryDetail.class).eq(GenDataObjQueryDetail::getDataObjId, record.getId()); + genDataObjQueryDetailService.remove(deleteQueryDetailWrapper); + + int orderNo = 1; + if (!CollectionUtil.isEmpty(data.getColumns())) { + for (GenDataObjDetailVo column : data.getColumns()) { + GenDataObjDetail detail = new GenDataObjDetail(); + detail.setId(column.getId()); + detail.setDataObjId(record.getId()); + detail.setMainTableDetailIds( + CollectionUtil.join(column.getMainTableDetailIds(), StringPool.STR_SPLIT)); + detail.setRelaType(EnumUtil.getByCode(GenRelaType.class, column.getRelaType())); + detail.setRelaMode(EnumUtil.getByCode(GenRelaMode.class, column.getRelaMode())); + detail.setSubTableId(column.getSubTableId()); + detail.setSubTableAlias(column.getSubTableAlias()); + detail.setSubTableDetailIds( + CollectionUtil.join(column.getSubTableDetailIds(), StringPool.STR_SPLIT)); + detail.setOrderNo(orderNo); + + genDataObjDetailService.save(detail); + + orderNo++; + } + } + + List newQueryDetailIds = new ArrayList<>(); + if (!CollectionUtil.isEmpty(data.getQueryColumns())) { + orderNo = 1; + for (GenDataObjQueryDetailVo queryColumn : data.getQueryColumns()) { + GenDataObjQueryDetail detail = new GenDataObjQueryDetail(); + detail.setId(queryColumn.getId()); + detail.setDataObjId(record.getId()); + detail.setCustomName(queryColumn.getCustomName()); + detail.setCustomSql(queryColumn.getCustomSql()); + detail.setCustomAlias(queryColumn.getCustomAlias()); + detail.setDataType(EnumUtil.getByCode(GenDataType.class, queryColumn.getDataType())); + detail.setOrderNo(orderNo); + + genDataObjQueryDetailService.save(detail); + + orderNo++; + + newQueryDetailIds.add(detail.getId()); + } + } + + List deleteQueryDetailIds = queryDetails.stream().map(GenDataObjQueryDetail::getId) + .filter(t -> !newQueryDetailIds.contains(t)).collect( + Collectors.toList()); + + if (!CollectionUtil.isEmpty(deleteQueryDetailIds)) { + for (String deleteDetailId : deleteQueryDetailIds) { + DataObjQueryDetailDeleteEvent event = new DataObjQueryDetailDeleteEvent(this); + event.setId(deleteDetailId); + event.setName( + queryDetails.stream().filter(t -> t.getId().equals(deleteDetailId)).findFirst().get() + .getCustomName()); + + ApplicationUtil.publishEvent(event); + } + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(@NonNull String id) { + GenDataObj record = this.getById(id); + if (record == null) { + return; + } + + List details = genDataObjDetailService.getByObjId(id); + List queryDetails = genDataObjQueryDetailService.getByObjId(id); + + getBaseMapper().deleteById(id); + + genDataObjDetailService.deleteByObjId(id); + + genDataObjQueryDetailService.deleteByObjId(id); + + DataObjDeleteEvent event = new DataObjDeleteEvent(this); + event.setId(id); + event.setName(record.getName()); + event.setDetailIds(details.stream().map(GenDataObjDetail::getId).collect(Collectors.toList())); + event.setQueryDetailIds(queryDetails.stream().map(GenDataObjQueryDetail::getId).collect( + Collectors.toList())); + + ApplicationUtil.publishEvent(event); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchDelete(@NonNull List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (String id : ids) { + this.delete(id); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenDataObj.class) + .set(GenDataObj::getAvailable, Boolean.TRUE).in(GenDataObj::getId, ids); + getBaseMapper().update(wrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(List ids) { + if (CollectionUtil.isEmpty(ids)) { + return; + } + + Wrapper wrapper = Wrappers.lambdaUpdate(GenDataObj.class) + .set(GenDataObj::getAvailable, Boolean.FALSE).in(GenDataObj::getId, ids); + getBaseMapper().update(wrapper); + } + + @Override + public List getRelaGenDataEntityIds(String entityId) { + return getBaseMapper().getRelaGenDataEntityIds(entityId); + } + + @CacheEvict(value = {GenDataObj.CACHE_NAME, DataObjectQueryObj.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + ThreadUtil.execAsync(() -> { + GenCustomListService genCustomListService = ApplicationUtil.getBean(GenCustomListService.class); + List ids = genCustomListService.getRelaGenDataObjIds(String.valueOf(key)); + if (CollectionUtil.isNotEmpty(ids)) { + genCustomListService.cleanCacheByKeys(ids); + } + }); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDetailColumnConfigServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDetailColumnConfigServiceImpl.java new file mode 100644 index 0000000..49e92fe --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenDetailColumnConfigServiceImpl.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenDetailColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenDetailColumnConfig; +import com.lframework.xingyun.template.gen.mappers.GenDetailColumnConfigMapper; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenDetailColumnConfigService; +import com.lframework.xingyun.template.gen.vo.gen.UpdateDetailColumnConfigVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenDetailColumnConfigServiceImpl + extends BaseMpServiceImpl + implements GenDetailColumnConfigService { + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Override + public List getByDataEntityId(String entityId) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (CollectionUtil.isEmpty(columns)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(String entityId, List vo) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (!CollectionUtil.isEmpty(columns)) { + getBaseMapper().deleteBatchIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + if (!CollectionUtil.isEmpty(vo)) { + int orderNo = 1; + for (UpdateDetailColumnConfigVo updateDetailColumnConfigVo : vo) { + GenDetailColumnConfig record = new GenDetailColumnConfig(); + record.setId(updateDetailColumnConfigVo.getId()); + record.setSpan(updateDetailColumnConfigVo.getSpan()); + record.setOrderNo(orderNo++); + + getBaseMapper().insert(record); + } + } + } + + @Override + public GenDetailColumnConfigDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + getBaseMapper().deleteById(id); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryColumnConfigServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryColumnConfigServiceImpl.java new file mode 100644 index 0000000..3701ee7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryColumnConfigServiceImpl.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenQueryColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenQueryColumnConfig; +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.xingyun.template.gen.mappers.GenQueryColumnConfigMapper; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenQueryColumnConfigService; +import com.lframework.xingyun.template.gen.vo.gen.UpdateQueryColumnConfigVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.EnumUtil; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenQueryColumnConfigServiceImpl extends + BaseMpServiceImpl + implements GenQueryColumnConfigService { + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Override + public List getByDataEntityId(String entityId) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (CollectionUtil.isEmpty(columns)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(String entityId, List vo) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (!CollectionUtil.isEmpty(columns)) { + getBaseMapper().deleteBatchIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + if (!CollectionUtil.isEmpty(vo)) { + int orderNo = 1; + for (UpdateQueryColumnConfigVo updateQueryColumnConfigVo : vo) { + GenQueryColumnConfig record = new GenQueryColumnConfig(); + record.setId(updateQueryColumnConfigVo.getId()); + record.setWidthType( + EnumUtil.getByCode(GenQueryWidthType.class, updateQueryColumnConfigVo.getWidthType())); + record.setWidth(updateQueryColumnConfigVo.getWidth()); + record.setSortable(updateQueryColumnConfigVo.getSortable()); + record.setOrderNo(orderNo++); + + getBaseMapper().insert(record); + } + } + } + + @Override + public GenQueryColumnConfigDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + getBaseMapper().deleteById(id); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryParamsColumnConfigServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryParamsColumnConfigServiceImpl.java new file mode 100644 index 0000000..9bd4593 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenQueryParamsColumnConfigServiceImpl.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenQueryParamsColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenQueryParamsColumnConfig; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.xingyun.template.gen.mappers.GenQueryParamsColumnConfigMapper; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenQueryParamsColumnConfigService; +import com.lframework.xingyun.template.gen.vo.gen.UpdateQueryParamsColumnConfigVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.EnumUtil; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenQueryParamsColumnConfigServiceImpl + extends BaseMpServiceImpl + implements GenQueryParamsColumnConfigService { + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Override + public List getByDataEntityId(String entityId) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (CollectionUtil.isEmpty(columns)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(String entityId, List vo) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (!CollectionUtil.isEmpty(columns)) { + getBaseMapper().deleteBatchIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + if (!CollectionUtil.isEmpty(vo)) { + int orderNo = 1; + for (UpdateQueryParamsColumnConfigVo updateQueryParamsColumnConfigVo : vo) { + GenQueryParamsColumnConfig record = new GenQueryParamsColumnConfig(); + record.setId(updateQueryParamsColumnConfigVo.getId()); + record.setQueryType( + EnumUtil.getByCode(GenQueryType.class, updateQueryParamsColumnConfigVo.getQueryType())); + record.setOrderNo(orderNo++); + + getBaseMapper().insert(record); + } + } + } + + @Override + public GenQueryParamsColumnConfigDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + getBaseMapper().deleteById(id); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenUpdateColumnConfigServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenUpdateColumnConfigServiceImpl.java new file mode 100644 index 0000000..975d9a6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenUpdateColumnConfigServiceImpl.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenUpdateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.entity.GenUpdateColumnConfig; +import com.lframework.xingyun.template.gen.mappers.GenUpdateColumnConfigMapper; +import com.lframework.xingyun.template.gen.service.GenDataEntityDetailService; +import com.lframework.xingyun.template.gen.service.GenUpdateColumnConfigService; +import com.lframework.xingyun.template.gen.vo.gen.UpdateUpdateColumnConfigVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenUpdateColumnConfigServiceImpl + extends BaseMpServiceImpl + implements GenUpdateColumnConfigService { + + @Autowired + private GenDataEntityDetailService genDataEntityDetailService; + + @Override + public List getByDataEntityId(String entityId) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (CollectionUtil.isEmpty(columns)) { + return CollectionUtil.emptyList(); + } + + return getBaseMapper().getByIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(String entityId, List vo) { + + List columns = genDataEntityDetailService.getByEntityId(entityId); + if (!CollectionUtil.isEmpty(columns)) { + getBaseMapper().deleteBatchIds( + columns.stream().map(GenDataEntityDetail::getId).collect(Collectors.toList())); + } + + if (!CollectionUtil.isEmpty(vo)) { + int orderNo = 1; + for (UpdateUpdateColumnConfigVo updateUpdateColumnConfigVo : vo) { + GenUpdateColumnConfig record = new GenUpdateColumnConfig(); + record.setId(updateUpdateColumnConfigVo.getId()); + record.setRequired(updateUpdateColumnConfigVo.getRequired()); + record.setOrderNo(orderNo++); + + getBaseMapper().insert(record); + } + } + } + + @Override + public GenUpdateColumnConfigDto findById(String id) { + + return getBaseMapper().findById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + getBaseMapper().deleteById(id); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenerateInfoServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenerateInfoServiceImpl.java new file mode 100644 index 0000000..2a0c56c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/GenerateInfoServiceImpl.java @@ -0,0 +1,67 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.gen.entity.GenGenerateInfo; +import com.lframework.xingyun.template.gen.enums.GenKeyType; +import com.lframework.xingyun.template.gen.enums.GenTemplateType; +import com.lframework.xingyun.template.gen.mappers.GenGenerateInfoMapper; +import com.lframework.xingyun.template.gen.service.GenerateInfoService; +import com.lframework.xingyun.template.gen.vo.gen.UpdateGenerateInfoVo; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.EnumUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GenerateInfoServiceImpl extends + BaseMpServiceImpl + implements GenerateInfoService { + + @Override + public GenGenerateInfoDto getByEntityId(String entityId) { + + return getBaseMapper().getByDataObjId(entityId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateGenerate(String dataObjId, UpdateGenerateInfoVo vo) { + + GenGenerateInfo data = getBaseMapper().selectById(dataObjId); + if (data != null) { + getBaseMapper().deleteById(data.getId()); + } else { + data = new GenGenerateInfo(); + } + data.setId(dataObjId); + data.setTemplateType(EnumUtil.getByCode(GenTemplateType.class, vo.getTemplateType())); + data.setPackageName(vo.getPackageName()); + data.setModuleName(vo.getModuleName()); + data.setBizName(vo.getBizName()); + data.setClassName(vo.getClassName()); + data.setClassDescription(vo.getClassDescription()); + if (!StringUtil.isBlank(vo.getParentMenuId())) { + data.setParentMenuId(vo.getParentMenuId()); + } + data.setKeyType(EnumUtil.getByCode(GenKeyType.class, vo.getKeyType())); + + if (!StringUtil.isBlank(vo.getAuthor())) { + data.setAuthor(vo.getAuthor()); + } + data.setMenuCode(vo.getMenuCode()); + data.setMenuName(vo.getMenuName()); + data.setDetailSpan(vo.getDetailSpan()); + data.setIsCache(vo.getIsCache()); + data.setHasDelete(vo.getHasDelete()); + + getBaseMapper().insert(data); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteByEntityId(String entityId) { + + getBaseMapper().deleteById(entityId); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleDBServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleDBServiceImpl.java new file mode 100644 index 0000000..7f2b4ae --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleDBServiceImpl.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.xingyun.template.gen.mappers.DBMapper; +import com.lframework.xingyun.template.gen.mappers.SimpleDBMapper; +import com.lframework.xingyun.template.gen.service.SimpleDBService; +import com.lframework.xingyun.template.gen.service.SimpleTableColumnService; +import com.lframework.xingyun.template.gen.vo.simpledb.QuerySimpleTableColumnVo; +import com.lframework.xingyun.template.gen.vo.simpledb.SimpleTableSelectorVo; +import com.lframework.xingyun.template.gen.dto.simpledb.OriSimpleTableDto; +import com.lframework.xingyun.template.gen.dto.simpledb.SimpleDBDto; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SimpleDBServiceImpl implements SimpleDBService { + + @Autowired + private SimpleDBMapper simpleDBMapper; + + @Autowired + private DBMapper dbMapper; + + @Autowired + private SimpleTableColumnService simpleTableColumnService; + + @Override + public String getCurrentDBName() { + return dbMapper.getCurrentDBName(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SimpleTableSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = simpleDBMapper.selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public OriSimpleTableDto getByTableName(String tableName) { + OriSimpleTableDto table = simpleDBMapper.getByTableName(tableName); + if (ObjectUtil.isNull(table)) { + return table; + } + + QuerySimpleTableColumnVo queryVo = new QuerySimpleTableColumnVo(); + queryVo.setTableName(tableName); + + List columns = simpleTableColumnService.query(queryVo); + table.setColumns(columns); + + return table; + } + + @Override + public List listByIds(List tableNames) { + return simpleDBMapper.listByIds(tableNames); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleTableColumnServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleTableColumnServiceImpl.java new file mode 100644 index 0000000..af9876d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/impl/SimpleTableColumnServiceImpl.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.template.gen.impl; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.xingyun.template.gen.mappers.GenSimpleTableColumnMapper; +import com.lframework.xingyun.template.gen.service.SimpleDBService; +import com.lframework.xingyun.template.gen.service.SimpleTableColumnService; +import com.lframework.xingyun.template.gen.vo.simpledb.QuerySimpleTableColumnVo; +import com.lframework.xingyun.template.gen.dto.simpledb.OriSimpleTableColumnDto; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SimpleTableColumnServiceImpl extends + BaseMpServiceImpl + implements SimpleTableColumnService { + + @Autowired + private SimpleDBService simpleDBService; + + @Override + public List query(QuerySimpleTableColumnVo vo) { + if (StringUtil.isBlank(vo.getTableSchema())) { + vo.setTableSchema(simpleDBService.getCurrentDBName()); + } + List columns = getBaseMapper().query(vo); + if (!CollectionUtil.isEmpty(columns)) { + + return columns.stream().map(t -> { + GenSimpleTableColumn column = new GenSimpleTableColumn(); + column.setId(IdUtil.getId()); + column.setColumnName(t.getColumnName()); + column.setIsNullable(t.getIsNullable()); + column.setIsKey(t.getIsKey()); + column.setColumnDefault(t.getColumnDefault()); + column.setOrdinalPosition(t.getOrdinalPosition()); + column.setColumnComment(t.getColumnComment()); + column.setDataType(t.getDataType().getDataType()); + column.setLen(t.getLen()); + column.setDecimals(t.getDecimals()); + + return column; + }).collect(Collectors.toList()); + } + + return null; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/CreateColumnConfigListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/CreateColumnConfigListener.java new file mode 100644 index 0000000..7dfaab3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/CreateColumnConfigListener.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenCreateColumnConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class CreateColumnConfigListener { + + @Component + public static class DeleteEntityListener implements ApplicationListener { + + @Autowired + private GenCreateColumnConfigService genCreateColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + for (String columnId : event.getColumnIds()) { + genCreateColumnConfigService.deleteById(columnId); + } + } + } + + @Component + public static class DeleteEntityDetailListener implements + ApplicationListener { + + @Autowired + private GenCreateColumnConfigService genCreateColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + + genCreateColumnConfigService.deleteById(event.getId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/DetailColumnConfigListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/DetailColumnConfigListener.java new file mode 100644 index 0000000..56ac627 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/DetailColumnConfigListener.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenDetailColumnConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class DetailColumnConfigListener { + + @Component + public static class DeleteEntityListener implements ApplicationListener { + + @Autowired + private GenDetailColumnConfigService genDetailColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + for (String columnId : event.getColumnIds()) { + genDetailColumnConfigService.deleteById(columnId); + } + } + } + + @Component + public static class DeleteEntityDetailListener implements + ApplicationListener { + + @Autowired + private GenDetailColumnConfigService genDetailColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + + genDetailColumnConfigService.deleteById(event.getId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomListListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomListListener.java new file mode 100644 index 0000000..ff5be83 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomListListener.java @@ -0,0 +1,90 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataObjDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataObjQueryDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenCustomListDetailService; +import com.lframework.xingyun.template.gen.service.GenCustomListQueryParamsService; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class GenCustomListListener { + + @Component + public static class DataObjDeleteListener implements ApplicationListener { + + @Autowired + private GenCustomListService genCustomListService; + + @Override + public void onApplicationEvent(DataObjDeleteEvent event) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenCustomList.class) + .eq(GenCustomList::getDataObjId, event.getId()); + if (genCustomListService.count(queryWrapper) > 0) { + throw new DefaultClientException("数据对象【" + event.getName() + "】已关联自定义列表,无法删除!"); + } + } + } + + @Component + public static class DataEntityDetailDeleteListener implements + ApplicationListener { + + @Autowired + private GenCustomListDetailService genCustomListDetailService; + + @Autowired + private GenCustomListQueryParamsService genCustomListQueryParamsService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + GenCustomListDetail.class).eq(GenCustomListDetail::getDataEntityId, event.getId()); + if (genCustomListDetailService.count(queryDetailWrapper) > 0) { + throw new DefaultClientException("字段【" + event.getName() + "】已关联自定义列表,无法删除!"); + } + + Wrapper queryQueryDetailWrapper = Wrappers.lambdaQuery( + GenCustomListQueryParams.class).eq(GenCustomListQueryParams::getRelaId, event.getId()); + if (genCustomListQueryParamsService.count(queryQueryDetailWrapper) > 0) { + throw new DefaultClientException("字段【" + event.getName() + "】已关联自定义列表,无法删除!"); + } + } + } + + @Component + public static class DataObjQueryDetailDeleteListener implements + ApplicationListener { + + @Autowired + private GenCustomListDetailService genCustomListDetailService; + + @Autowired + private GenCustomListQueryParamsService genCustomListQueryParamsService; + + @Override + public void onApplicationEvent(DataObjQueryDetailDeleteEvent event) { + Wrapper queryDetailWrapper = Wrappers.lambdaQuery( + GenCustomListDetail.class).eq(GenCustomListDetail::getDataEntityId, event.getId()); + if (genCustomListDetailService.count(queryDetailWrapper) > 0) { + throw new DefaultClientException("字段【" + event.getName() + "】已关联自定义列表,无法删除!"); + } + + Wrapper queryQueryDetailWrapper = Wrappers.lambdaQuery( + GenCustomListQueryParams.class).eq(GenCustomListQueryParams::getRelaId, event.getId()); + if (genCustomListQueryParamsService.count(queryQueryDetailWrapper) > 0) { + throw new DefaultClientException("字段【" + event.getName() + "】已关联自定义列表,无法删除!"); + } + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomSelectorListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomSelectorListener.java new file mode 100644 index 0000000..bfcd1a1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenCustomSelectorListener.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.events.CustomListDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenCustomSelectorService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class GenCustomSelectorListener { + + @Component + public static class CustomListDeleteListener implements + ApplicationListener { + + @Autowired + private GenCustomSelectorService genCustomSelectorService; + + @Override + public void onApplicationEvent(CustomListDeleteEvent event) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenCustomSelector.class) + .eq(GenCustomSelector::getCustomListId, event.getId()); + if (genCustomSelectorService.count(queryWrapper) > 0) { + throw new DefaultClientException("自定义列表【" + event.getName() + "】已关联自定义选择器,无法删除!"); + } + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenDataObjListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenDataObjListener.java new file mode 100644 index 0000000..20f5913 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenDataObjListener.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenDataObjDetailService; +import com.lframework.xingyun.template.gen.service.GenDataObjService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class GenDataObjListener { + + @Component + public static class DataEntityDeleteListener implements + ApplicationListener { + + @Autowired + private GenDataObjService genDataObjService; + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(GenDataObj.class) + .eq(GenDataObj::getMainTableId, event.getId()); + if (genDataObjService.count(queryWrapper) > 0) { + throw new DefaultClientException("数据实体【" + event.getName() + "】已关联数据对象,无法删除!"); + } + + Wrapper queryDetailWrapper = Wrappers.lambdaQuery(GenDataObjDetail.class) + .eq(GenDataObjDetail::getSubTableId, event.getId()); + if (genDataObjDetailService.count(queryDetailWrapper) > 0) { + throw new DefaultClientException("数据实体【" + event.getName() + "】已关联数据对象,无法删除!"); + } + } + } + + @Component + public static class DataEntityDetailDeleteListener implements + ApplicationListener { + + @Autowired + private GenDataObjDetailService genDataObjDetailService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + if (genDataObjDetailService.entityDetailIsRela(event.getId())) { + throw new DefaultClientException("字段【" + event.getName() + "】已关联数据对象,无法删除!"); + } + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenTenantListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenTenantListener.java new file mode 100644 index 0000000..02961fb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenTenantListener.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import com.lframework.starter.web.utils.DataSourceUtil; +import com.lframework.starter.web.common.event.ReloadTenantEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; +import org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource; + +public class GenTenantListener { + + @Component + public static class ReloadTenantListener implements ApplicationListener, + Ordered { + + @Autowired + private MagicDynamicDataSource magicDynamicDataSource; + + @Autowired + private DynamicDataSourceProperties dynamicDataSourceProperties; + + @Override + public void onApplicationEvent(ReloadTenantEvent event) { + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource() + .get("master"); + magicDynamicDataSource.add(String.valueOf(event.getTenantId()), + DataSourceUtil.createDataSource(dataSourceProperty, event.getJdbcUrl(), + event.getJdbcUsername(), event.getJdbcPassword(), event.getDriver())); + } + + @Override + public int getOrder() { + return Integer.MAX_VALUE; + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenerateInfoListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenerateInfoListener.java new file mode 100644 index 0000000..25ab065 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/GenerateInfoListener.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenerateInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class GenerateInfoListener { + + @Component + public static class DeleteEntityListener implements ApplicationListener { + + @Autowired + private GenerateInfoService generateInfoService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + generateInfoService.deleteByEntityId(event.getId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryColumnConfigListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryColumnConfigListener.java new file mode 100644 index 0000000..e4814ab --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryColumnConfigListener.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenQueryColumnConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class QueryColumnConfigListener { + + @Component + public static class DeleteEntityListener implements ApplicationListener { + + @Autowired + private GenQueryColumnConfigService genQueryColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + for (String columnId : event.getColumnIds()) { + genQueryColumnConfigService.deleteById(columnId); + } + } + } + + @Component + public static class DeleteEntityDetailListener implements + ApplicationListener { + + @Autowired + private GenQueryColumnConfigService genQueryColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + + genQueryColumnConfigService.deleteById(event.getId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryParamsColumnConfigListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryParamsColumnConfigListener.java new file mode 100644 index 0000000..04c7e60 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/QueryParamsColumnConfigListener.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenQueryParamsColumnConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class QueryParamsColumnConfigListener { + + @Component + public static class DeleteEntityListener implements ApplicationListener { + + @Autowired + private GenQueryParamsColumnConfigService genQueryParamsColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + for (String columnId : event.getColumnIds()) { + genQueryParamsColumnConfigService.deleteById(columnId); + } + } + } + + @Component + public static class DeleteEntityDetailListener implements + ApplicationListener { + + @Autowired + private GenQueryParamsColumnConfigService genQueryParamsColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + + genQueryParamsColumnConfigService.deleteById(event.getId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/UpdateColumnConfigListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/UpdateColumnConfigListener.java new file mode 100644 index 0000000..ceb130d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/listeners/UpdateColumnConfigListener.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.listeners; + +import com.lframework.xingyun.template.gen.events.DataEntityDeleteEvent; +import com.lframework.xingyun.template.gen.events.DataEntityDetailDeleteEvent; +import com.lframework.xingyun.template.gen.service.GenUpdateColumnConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +public class UpdateColumnConfigListener { + + @Component + public static class DeleteEntityListener implements ApplicationListener { + + @Autowired + private GenUpdateColumnConfigService genUpdateColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDeleteEvent event) { + + for (String columnId : event.getColumnIds()) { + genUpdateColumnConfigService.deleteById(columnId); + } + } + } + + @Component + public static class DeleteEntityDetailListener implements + ApplicationListener { + + @Autowired + private GenUpdateColumnConfigService genUpdateColumnConfigService; + + @Override + public void onApplicationEvent(DataEntityDetailDeleteEvent event) { + + genUpdateColumnConfigService.deleteById(event.getId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/DBMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/DBMapper.java new file mode 100644 index 0000000..dd80222 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/DBMapper.java @@ -0,0 +1,13 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; + +public interface DBMapper extends BaseMapper { + + /** + * 查询当前数据库名称 + * + * @return + */ + String getCurrentDBName(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCreateColumnConfigMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCreateColumnConfigMapper.java new file mode 100644 index 0000000..e9ba07a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCreateColumnConfigMapper.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.gen.dto.gen.GenCreateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenCreateColumnConfig; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-10 + */ +public interface GenCreateColumnConfigMapper extends BaseMapper { + + /** + * 根据数据对象ID查询 + * + * @param ids + * @return + */ + List getByIds(@Param("ids") List ids); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCreateColumnConfigDto findById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListCategoryMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListCategoryMapper.java new file mode 100644 index 0000000..1a6afd6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListCategoryMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.vo.custom.list.category.GenCustomListCategorySelectorVo; +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 自定义列表分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface GenCustomListCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenCustomListCategorySelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListDetailMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListDetailMapper.java new file mode 100644 index 0000000..9b62031 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListDetailMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.starter.web.mapper.BaseMapper; + +public interface GenCustomListDetailMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListHandleColumnMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListHandleColumnMapper.java new file mode 100644 index 0000000..e3ed9f8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListHandleColumnMapper.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenCustomListHandleColumn; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface GenCustomListHandleColumnMapper extends BaseMapper { + + /** + * 根据自定义列表ID查询 + * + * @param customListId + * @return + */ + List getByCustomListId(@Param("customListId") String customListId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListMapper.java new file mode 100644 index 0000000..54ab1d8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListMapper.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.list.QueryGenCustomListVo; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 自定义列表 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenCustomListMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryGenCustomListVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenCustomListSelectorVo vo); + + /** + * 查询所有关联了数据对象的自定义列表ID + * + * @param objId + * @return + */ + List getRelaGenDataObjIds(@Param("objId") String objId); + + /** + * 查询所有关联了数据实体的自定义列表ID + * + * @param entityId + * @return + */ + List getRelaGenDataEntityIds(@Param("entityId") String entityId); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListQueryParamsMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListQueryParamsMapper.java new file mode 100644 index 0000000..b0e9a68 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListQueryParamsMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.starter.web.mapper.BaseMapper; + +public interface GenCustomListQueryParamsMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListToolbarMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListToolbarMapper.java new file mode 100644 index 0000000..baaed27 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomListToolbarMapper.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenCustomListToolbar; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface GenCustomListToolbarMapper extends BaseMapper { + + /** + * 根据自定义列表ID查询 + * + * @param customListId + * @return + */ + List getByCustomListId(@Param("customListId") String customListId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageCategoryMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageCategoryMapper.java new file mode 100644 index 0000000..68546bf --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageCategoryMapper.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; + +/** + *

+ * 自定义页面分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface GenCustomPageCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageMapper.java new file mode 100644 index 0000000..e980df9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomPageMapper.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.xingyun.template.gen.vo.custom.page.GenCustomPageSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.page.QueryGenCustomPageVo; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 自定义页面 Mapper 接口 + *

+ * + * @author zmj + * @since 2023-06-20 + */ +public interface GenCustomPageMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryGenCustomPageVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenCustomPageSelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorCategoryMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorCategoryMapper.java new file mode 100644 index 0000000..c97fb1f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorCategoryMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.vo.custom.selector.category.GenCustomSelectorCategorySelectorVo; +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 自定义选择器分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface GenCustomSelectorCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenCustomSelectorCategorySelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorMapper.java new file mode 100644 index 0000000..6a159ba --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenCustomSelectorMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.vo.custom.selector.GenCustomSelectorSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.QueryGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 自定义选择器 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenCustomSelectorMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryGenCustomSelectorVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenCustomSelectorSelectorVo vo); + + /** + * 查询所有关联了自定义列表的自定义选择器ID + * + * @return + */ + List getRelaGenCustomListIds(@Param("customListId") String customListId); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityCategoryMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityCategoryMapper.java new file mode 100644 index 0000000..144de34 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityCategoryMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.vo.data.entity.category.GenDataEntityCategorySelectorVo; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据实体分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface GenDataEntityCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenDataEntityCategorySelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityDetailMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityDetailMapper.java new file mode 100644 index 0000000..3a1afc2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.starter.web.mapper.BaseMapper; + +/** + *

+ * 数据实体明细 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenDataEntityDetailMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityMapper.java new file mode 100644 index 0000000..971d5b2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataEntityMapper.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntitySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.QueryDataEntityVo; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据实体 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenDataEntityMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryDataEntityVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenDataEntitySelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjCategoryMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjCategoryMapper.java new file mode 100644 index 0000000..78f67e6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjCategoryMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.vo.data.obj.category.GenDataObjCategorySelectorVo; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据对象分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface GenDataObjCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenDataObjCategorySelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjDetailMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjDetailMapper.java new file mode 100644 index 0000000..5b4b808 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjDetailMapper.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.starter.web.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据对象明细 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenDataObjDetailMapper extends BaseMapper { + + /** + * 实体明细ID是否已关联数据对象 + * + * @param entityDetailId + * @return + */ + Boolean entityDetailIsRela(@Param("entityDetailId") String entityDetailId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjMapper.java new file mode 100644 index 0000000..e54c3f0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjMapper.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.vo.data.obj.GenDataObjSelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.QueryGenDataObjVo; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据对象 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenDataObjMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryGenDataObjVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") GenDataObjSelectorVo vo); + + /** + * 查询所有关联了数据实体的数据对象ID + * @param entityId + * @return + */ + List getRelaGenDataEntityIds(@Param("entityId") String entityId); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjQueryDetailMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjQueryDetailMapper.java new file mode 100644 index 0000000..5ad5892 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDataObjQueryDetailMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.starter.web.mapper.BaseMapper; + +/** + *

+ * 数据对象自定义查询明细 Mapper 接口 + *

+ * + * @author zmj + * @since 2022-09-17 + */ +public interface GenDataObjQueryDetailMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDetailColumnConfigMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDetailColumnConfigMapper.java new file mode 100644 index 0000000..fc1fd24 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenDetailColumnConfigMapper.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.dto.gen.GenDetailColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDetailColumnConfig; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-10 + */ +public interface GenDetailColumnConfigMapper extends BaseMapper { + + /** + * 根据数据对象ID查询 + * + * @param ids + * @return + */ + List getByIds(@Param("ids") List ids); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenDetailColumnConfigDto findById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenGenerateInfoMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenGenerateInfoMapper.java new file mode 100644 index 0000000..4e091b2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenGenerateInfoMapper.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.gen.entity.GenGenerateInfo; +import com.lframework.starter.web.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-08 + */ +public interface GenGenerateInfoMapper extends BaseMapper { + + /** + * 根据数据对象ID查询 + * + * @param dataObjId + * @return + */ + GenGenerateInfoDto getByDataObjId(String dataObjId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenMapper.java new file mode 100644 index 0000000..bed9fd1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenMapper.java @@ -0,0 +1,11 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.components.data.obj.DataObjectQueryObj; +import java.util.List; +import java.util.Map; +import org.apache.ibatis.annotations.Param; + +public interface GenMapper { + + List> findList(@Param("obj") DataObjectQueryObj obj); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryColumnConfigMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryColumnConfigMapper.java new file mode 100644 index 0000000..5480363 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryColumnConfigMapper.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.dto.gen.GenQueryColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenQueryColumnConfig; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-10 + */ +public interface GenQueryColumnConfigMapper extends BaseMapper { + + /** + * 根据数据对象ID查询 + * + * @param ids + * @return + */ + List getByIds(@Param("ids") List ids); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenQueryColumnConfigDto findById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryParamsColumnConfigMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryParamsColumnConfigMapper.java new file mode 100644 index 0000000..2d9f30e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenQueryParamsColumnConfigMapper.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.dto.gen.GenQueryParamsColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenQueryParamsColumnConfig; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-10 + */ +public interface GenQueryParamsColumnConfigMapper extends BaseMapper { + + /** + * 根据数据对象ID查询 + * + * @param ids + * @return + */ + List getByIds(@Param("ids") List ids); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenQueryParamsColumnConfigDto findById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableColumnMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableColumnMapper.java new file mode 100644 index 0000000..5aad67b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableColumnMapper.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.vo.simpledb.QuerySimpleTableColumnVo; +import com.lframework.xingyun.template.gen.dto.simpledb.OriSimpleTableColumnDto; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-05-28 + */ +public interface GenSimpleTableColumnMapper extends BaseMapper { + + /** + * 根据创建Vo查询 + * + * @param vo + * @return + */ + List query(QuerySimpleTableColumnVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableMapper.java new file mode 100644 index 0000000..e118002 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenSimpleTableMapper.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.dto.simpledb.SimpleTableDto; +import com.lframework.xingyun.template.gen.entity.GenSimpleTable; +import com.lframework.starter.web.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-05-28 + */ +public interface GenSimpleTableMapper extends BaseMapper { + + /** + * 根据数据实体ID查询 + * + * @param id + * @return + */ + SimpleTableDto getByEntityId(@Param("id") String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenUpdateColumnConfigMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenUpdateColumnConfigMapper.java new file mode 100644 index 0000000..8f65be5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/GenUpdateColumnConfigMapper.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.dto.gen.GenUpdateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenUpdateColumnConfig; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-12-10 + */ +public interface GenUpdateColumnConfigMapper extends BaseMapper { + + /** + * 根据数据对象ID查询 + * + * @param ids + * @return + */ + List getByIds(@Param("ids") List ids); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenUpdateColumnConfigDto findById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/SimpleDBMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/SimpleDBMapper.java new file mode 100644 index 0000000..f86f4be --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/mappers/SimpleDBMapper.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.mappers; + +import com.lframework.xingyun.template.gen.vo.simpledb.SimpleTableSelectorVo; +import com.lframework.xingyun.template.gen.dto.simpledb.OriSimpleTableDto; +import com.lframework.xingyun.template.gen.dto.simpledb.SimpleDBDto; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface SimpleDBMapper extends BaseMapper { + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(SimpleTableSelectorVo vo); + + /** + * 根据TableName查询 + * + * @param tableName + * @return + */ + OriSimpleTableDto getByTableName(@Param("tableName") String tableName); + + /** + * 批量查询 + * + * @param tableNames + * @return + */ + List listByIds(@Param("tableNames") List tableNames); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCreateColumnConfigService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCreateColumnConfigService.java new file mode 100644 index 0000000..941f53b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCreateColumnConfigService.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.gen.GenCreateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenCreateColumnConfig; +import com.lframework.xingyun.template.gen.vo.gen.UpdateCreateColumnConfigVo; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCreateColumnConfigService extends BaseMpService { + + /** + * 根据数据实体ID查询 + * + * @param entityId + * @return + */ + List getByDataEntityId(String entityId); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(String entityId, List vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCreateColumnConfigDto findById(String id); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListCategoryService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListCategoryService.java new file mode 100644 index 0000000..da5203b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListCategoryService.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomListCategory; +import com.lframework.xingyun.template.gen.vo.custom.list.category.CreateGenCustomListCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.list.category.GenCustomListCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.list.category.UpdateGenCustomListCategoryVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +/** + * 自定义列表分类 Service + * + * @author zmj + */ +public interface GenCustomListCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomListCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCustomListCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateGenCustomListCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateGenCustomListCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListDetailService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListDetailService.java new file mode 100644 index 0000000..ccb267a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListDetailService.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomListDetail; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomListDetailService extends BaseMpService { + + /** + * 根据自定义列表ID查询 + * @param customListId + * @return + */ + List getByCustomListId(String customListId); + + /** + * 根据自定义列表ID删除 + * @param customListId + */ + void deleteByCustomListId(String customListId); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListHandleColumnService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListHandleColumnService.java new file mode 100644 index 0000000..da89da2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListHandleColumnService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomListHandleColumn; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomListHandleColumnService extends + BaseMpService { + + /** + * 根据自定义列表ID查询 + * + * @param customListId + * @return + */ + List getByCustomListId(String customListId); + + /** + * 根据自定义列表ID删除 + * + * @param customListId + */ + void deleteByCustomListId(String customListId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListQueryParamsService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListQueryParamsService.java new file mode 100644 index 0000000..c6fe6b6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListQueryParamsService.java @@ -0,0 +1,22 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomListQueryParams; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomListQueryParamsService extends BaseMpService { + + /** + * 根据自定义列表ID查询 + * @param customListId + * @return + */ + List getByCustomListId(String customListId); + + /** + * 根据自定义列表ID删除 + * @param customListId + */ + void deleteByCustomListId(String customListId); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListService.java new file mode 100644 index 0000000..1a9ccab --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListService.java @@ -0,0 +1,103 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.vo.custom.list.CreateGenCustomListVo; +import com.lframework.xingyun.template.gen.vo.custom.list.GenCustomListSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.list.QueryGenCustomListVo; +import com.lframework.xingyun.template.gen.vo.custom.list.UpdateGenCustomListVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomListService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryGenCustomListVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryGenCustomListVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomListSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCustomList findById(String id); + + /** + * 新增 + * + * @param data + * @return + */ + String create(CreateGenCustomListVo data); + + /** + * 修改 + * + * @param data + */ + void update(UpdateGenCustomListVo data); + + /** + * 根据ID删除 + * @param id + */ + void delete(String id); + + /** + * 批量删除 + * @param ids + */ + void batchDelete(List ids); + + /** + * 批量启用 + * + * @param ids + */ + void batchEnable(List ids); + + /** + * 批量停用 + * + * @param ids + */ + void batchUnable(List ids); + + /** + * 查询所有关联了数据对象的自定义列表ID + * @return + */ + List getRelaGenDataObjIds(String objId); + + /** + * 查询所有关联了数据实体的自定义列表ID + * @return + */ + List getRelaGenDataEntityIds(String entityId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListToolbarService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListToolbarService.java new file mode 100644 index 0000000..4bf4f0e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomListToolbarService.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomListToolbar; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomListToolbarService extends BaseMpService { + + /** + * 根据自定义列表ID查询 + * + * @param customListId + * @return + */ + List getByCustomListId(String customListId); + + /** + * 根据自定义列表ID删除 + * + * @param customListId + */ + void deleteByCustomListId(String customListId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageCategoryService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageCategoryService.java new file mode 100644 index 0000000..08423cf --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageCategoryService.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.vo.custom.page.category.CreateGenCustomPageCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.page.category.UpdateGenCustomPageCategoryVo; +import com.lframework.xingyun.template.gen.entity.GenCustomPageCategory; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +/** + * 自定义页面分类 Service + * + * @author zmj + */ +public interface GenCustomPageCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCustomPageCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateGenCustomPageCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateGenCustomPageCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageService.java new file mode 100644 index 0000000..7a6ac1f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomPageService.java @@ -0,0 +1,80 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.vo.custom.page.CreateGenCustomPageVo; +import com.lframework.xingyun.template.gen.vo.custom.page.GenCustomPageSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.page.QueryGenCustomPageVo; +import com.lframework.xingyun.template.gen.vo.custom.page.UpdateGenCustomPageVo; +import com.lframework.xingyun.template.gen.entity.GenCustomPage; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomPageService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryGenCustomPageVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryGenCustomPageVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomPageSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCustomPage findById(Integer id); + + /** + * 新增 + * + * @param data + * @return + */ + Integer create(CreateGenCustomPageVo data); + + /** + * 修改 + * + * @param data + */ + void update(UpdateGenCustomPageVo data); + + /** + * 根据ID删除 + * + * @param id + */ + void delete(Integer id); + + /** + * 批量删除 + * + * @param ids + */ + void batchDelete(List ids); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorCategoryService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorCategoryService.java new file mode 100644 index 0000000..c87bd43 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorCategoryService.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomSelectorCategory; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.CreateGenCustomSelectorCategoryVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.GenCustomSelectorCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.category.UpdateGenCustomSelectorCategoryVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +/** + * 自定义选择器分类 Service + * + * @author zmj + */ +public interface GenCustomSelectorCategoryService extends + BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomSelectorCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCustomSelectorCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateGenCustomSelectorCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateGenCustomSelectorCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorService.java new file mode 100644 index 0000000..88f5185 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenCustomSelectorService.java @@ -0,0 +1,101 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenCustomSelector; +import com.lframework.xingyun.template.gen.vo.custom.selector.CreateGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.GenCustomSelectorSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.QueryGenCustomSelectorVo; +import com.lframework.xingyun.template.gen.vo.custom.selector.UpdateGenCustomSelectorVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenCustomSelectorService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QueryGenCustomSelectorVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryGenCustomSelectorVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenCustomSelectorSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenCustomSelector findById(String id); + + /** + * 新增 + * + * @param data + * @return + */ + String create(CreateGenCustomSelectorVo data); + + /** + * 修改 + * + * @param data + */ + void update(UpdateGenCustomSelectorVo data); + + /** + * 根据ID删除 + * + * @param id + */ + void delete(String id); + + /** + * 批量删除 + * + * @param ids + */ + void batchDelete(List ids); + + /** + * 批量启用 + * + * @param ids + */ + void batchEnable(List ids); + + /** + * 批量停用 + * + * @param ids + */ + void batchUnable(List ids); + + /** + * 查询所有关联了自定义列表的自定义选择器ID + * + * @return + */ + List getRelaGenCustomListIds(String customListId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityCategoryService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityCategoryService.java new file mode 100644 index 0000000..d94bbae --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityCategoryService.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityCategory; +import com.lframework.xingyun.template.gen.vo.data.entity.category.CreateGenDataEntityCategoryVo; +import com.lframework.xingyun.template.gen.vo.data.entity.category.GenDataEntityCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.category.UpdateGenDataEntityCategoryVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +/** + * 数据实体分类 Service + * + * @author zmj + */ +public interface GenDataEntityCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenDataEntityCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenDataEntityCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateGenDataEntityCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateGenDataEntityCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityDetailService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityDetailService.java new file mode 100644 index 0000000..be288b9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityDetailService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenDataEntityDetail; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntityDetailSelectorVo; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenDataEntityDetailService extends BaseMpService { + + /** + * 根据实体ID查询 + * + * @param entityId + * @return + */ + List getByEntityId(String entityId); + + /** + * 根据实体ID删除 + * + * @param entityId + */ + void deleteByEntityId(String entityId); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(GenDataEntityDetailSelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityService.java new file mode 100644 index 0000000..6ed37be --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataEntityService.java @@ -0,0 +1,118 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.data.entity.DataEntityGenerateDto; +import com.lframework.xingyun.template.gen.entity.GenDataEntity; +import com.lframework.xingyun.template.gen.vo.data.entity.CreateDataEntityVo; +import com.lframework.xingyun.template.gen.vo.data.entity.GenDataEntitySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.entity.QueryDataEntityVo; +import com.lframework.xingyun.template.gen.vo.data.entity.UpdateDataEntityGenerateVo; +import com.lframework.xingyun.template.gen.vo.data.entity.UpdateDataEntityVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenDataEntityService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryDataEntityVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryDataEntityVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenDataEntitySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenDataEntity findById(String id); + + /** + * 创建 + * + * @param data + * @return + */ + String create(CreateDataEntityVo data); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateDataEntityVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void delete(String id); + + /** + * 根据ID批量删除 + * + * @param ids + */ + void batchDelete(List ids); + + /** + * 批量启用 + * + * @param ids + */ + void batchEnable(List ids); + + /** + * 批量停用 + * + * @param ids + */ + void batchUnable(List ids); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + DataEntityGenerateDto getGenerateById(String id); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(UpdateDataEntityGenerateVo vo); + + /** + * 同步数据表 + * + * @param id + */ + void syncTable(String id); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjCategoryService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjCategoryService.java new file mode 100644 index 0000000..a7eda58 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjCategoryService.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenDataObjCategory; +import com.lframework.xingyun.template.gen.vo.data.obj.category.CreateGenDataObjCategoryVo; +import com.lframework.xingyun.template.gen.vo.data.obj.category.GenDataObjCategorySelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.category.UpdateGenDataObjCategoryVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +/** + * 数据对象分类 Service + * + * @author zmj + */ +public interface GenDataObjCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + GenDataObjCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenDataObjCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateGenDataObjCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateGenDataObjCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjDetailService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjDetailService.java new file mode 100644 index 0000000..ef87c7e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjDetailService.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenDataObjDetail; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenDataObjDetailService extends BaseMpService { + + /** + * 根据数据对象ID查询 + * + * @param objId + * @return + */ + List getByObjId(String objId); + + /** + * 根据数据对象ID删除 + * + * @param objId + */ + void deleteByObjId(String objId); + + /** + * 实体明细ID是否已关联数据对象 + * + * @param entityDetailId + * @return + */ + Boolean entityDetailIsRela(String entityDetailId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjQueryDetailService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjQueryDetailService.java new file mode 100644 index 0000000..f11fcdd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjQueryDetailService.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenDataObjQueryDetail; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenDataObjQueryDetailService extends BaseMpService { + + /** + * 根据数据对象ID查询 + * + * @param objId + * @return + */ + List getByObjId(String objId); + + /** + * 根据数据对象ID删除 + * + * @param objId + */ + void deleteByObjId(String objId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjService.java new file mode 100644 index 0000000..6c4d455 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDataObjService.java @@ -0,0 +1,98 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.entity.GenDataObj; +import com.lframework.xingyun.template.gen.vo.data.obj.CreateGenDataObjVo; +import com.lframework.xingyun.template.gen.vo.data.obj.GenDataObjSelectorVo; +import com.lframework.xingyun.template.gen.vo.data.obj.QueryGenDataObjVo; +import com.lframework.xingyun.template.gen.vo.data.obj.UpdateGenDataObjVo; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenDataObjService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryGenDataObjVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QueryGenDataObjVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, GenDataObjSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenDataObj findById(String id); + + /** + * 新增 + * + * @param data + * @return + */ + String create(CreateGenDataObjVo data); + + /** + * 修改 + * + * @param data + */ + void update(UpdateGenDataObjVo data); + + /** + * 根据ID删除 + * + * @param id + */ + void delete(String id); + + /** + * 根据ID批量删除 + * + * @param ids + */ + void batchDelete(List ids); + + /** + * 批量启用 + * + * @param ids + */ + void batchEnable(List ids); + + /** + * 批量停用 + * + * @param ids + */ + void batchUnable(List ids); + + /** + * 查询所有关联了数据实体的数据对象ID + * @return + */ + List getRelaGenDataEntityIds(String entityId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDetailColumnConfigService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDetailColumnConfigService.java new file mode 100644 index 0000000..b6d634d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenDetailColumnConfigService.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.gen.GenDetailColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenDetailColumnConfig; +import com.lframework.xingyun.template.gen.vo.gen.UpdateDetailColumnConfigVo; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenDetailColumnConfigService extends BaseMpService { + + /** + * 根据数据实体ID查询 + * + * @param entityId + * @return + */ + List getByDataEntityId(String entityId); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(String entityId, List vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenDetailColumnConfigDto findById(String id); + + /** + * 根据ID查询 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryColumnConfigService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryColumnConfigService.java new file mode 100644 index 0000000..0d17eca --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryColumnConfigService.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.gen.GenQueryColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenQueryColumnConfig; +import com.lframework.xingyun.template.gen.vo.gen.UpdateQueryColumnConfigVo; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenQueryColumnConfigService extends BaseMpService { + + /** + * 根据数据对象ID查询 + * + * @param entityId + * @return + */ + List getByDataEntityId(String entityId); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(String entityId, List vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenQueryColumnConfigDto findById(String id); + + /** + * 根据ID查询 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryParamsColumnConfigService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryParamsColumnConfigService.java new file mode 100644 index 0000000..3cd6a18 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenQueryParamsColumnConfigService.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.gen.GenQueryParamsColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenQueryParamsColumnConfig; +import com.lframework.xingyun.template.gen.vo.gen.UpdateQueryParamsColumnConfigVo; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenQueryParamsColumnConfigService extends + BaseMpService { + + /** + * 根据数据实体ID查询 + * + * @param entityId + * @return + */ + List getByDataEntityId(String entityId); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(String entityId, List vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenQueryParamsColumnConfigDto findById(String id); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenUpdateColumnConfigService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenUpdateColumnConfigService.java new file mode 100644 index 0000000..76aa98d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenUpdateColumnConfigService.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.gen.GenUpdateColumnConfigDto; +import com.lframework.xingyun.template.gen.entity.GenUpdateColumnConfig; +import com.lframework.xingyun.template.gen.vo.gen.UpdateUpdateColumnConfigVo; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface GenUpdateColumnConfigService extends BaseMpService { + + /** + * 根据数据实体ID查询 + * + * @param entityId + * @return + */ + List getByDataEntityId(String entityId); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(String entityId, List vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + GenUpdateColumnConfigDto findById(String id); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenerateInfoService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenerateInfoService.java new file mode 100644 index 0000000..5b73540 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/GenerateInfoService.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.dto.gen.GenGenerateInfoDto; +import com.lframework.xingyun.template.gen.entity.GenGenerateInfo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateGenerateInfoVo; +import com.lframework.starter.web.service.BaseMpService; + +public interface GenerateInfoService extends BaseMpService { + + /** + * 根据数据实体ID查询 + * + * @param entityId + * @return + */ + GenGenerateInfoDto getByEntityId(String entityId); + + /** + * 修改生成器配置信息 + * + * @param vo + */ + void updateGenerate(String dataObjId, UpdateGenerateInfoVo vo); + + /** + * 根据数据实体ID删除 + * + * @param entityId + */ + void deleteByEntityId(String entityId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleDBService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleDBService.java new file mode 100644 index 0000000..66bbb84 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleDBService.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.vo.simpledb.SimpleTableSelectorVo; +import com.lframework.xingyun.template.gen.dto.simpledb.OriSimpleTableDto; +import com.lframework.xingyun.template.gen.dto.simpledb.SimpleDBDto; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseService; +import java.util.List; + +public interface SimpleDBService extends BaseService { + + /** + * 查询当前数据库名称 + * + * @return + */ + String getCurrentDBName(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SimpleTableSelectorVo vo); + + /** + * 根据表名查询 + * + * @return + */ + OriSimpleTableDto getByTableName(String tableName); + + /** + * 批量查询 + * + * @param tableNames + * @return + */ + List listByIds(List tableNames); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleTableColumnService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleTableColumnService.java new file mode 100644 index 0000000..9e3c670 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/service/SimpleTableColumnService.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.template.gen.service; + +import com.lframework.xingyun.template.gen.vo.simpledb.QuerySimpleTableColumnVo; +import com.lframework.xingyun.template.gen.entity.GenSimpleTableColumn; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface SimpleTableColumnService extends BaseMpService { + + /** + * 查询列信息 + * + * @param vo + * @return + */ + List query(QuerySimpleTableColumnVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/utils/WebUtils.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/utils/WebUtils.java new file mode 100644 index 0000000..668c401 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/utils/WebUtils.java @@ -0,0 +1,117 @@ +package com.lframework.xingyun.template.gen.utils; + +import cn.hutool.core.collection.ArrayIter; +import cn.hutool.core.collection.IterUtil; +import cn.hutool.core.map.CaseInsensitiveMap; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.ArrayUtil; +import org.springframework.util.Assert; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.Objects; + + +public class WebUtils { + + private static final String UNKNOWN ="unknown"; + + public static HttpServletRequest getHttpRequest() { + ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + Assert.notNull(attributes, "RequestContextHolder.getRequestAttributes can't be NULL"); + return attributes.getRequest(); + } + + public static HttpServletRequest getRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getRequest(); + } + + public static HttpServletResponse getResponse() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getResponse(); + } + + public static void redirect(String url) throws Exception { + redirect(getResponse(), url); + } + + public static void redirect(HttpServletResponse response, String url) throws Exception { + response.sendRedirect(url); + } + + public static void addCookie(String name, String value) { + getResponse().addCookie(new Cookie(name, value)); + } + + public static void addCookie(String name, String value, int expiry) { + Cookie cookie = new Cookie(name, value); + cookie.setMaxAge(expiry); + cookie.setPath("/"); + getResponse().addCookie(cookie); + } + + public static String getCookie(String name) { + Map cookieMap = readCookieMap(getRequest()); + return cookieMap.containsKey(name) ? ((Cookie)cookieMap.get(name)).getValue() : null; + } + + public static Map readCookieMap(HttpServletRequest httpServletRequest) { + Cookie[] cookies = httpServletRequest.getCookies(); + return ArrayUtil.isEmpty(cookies) ? MapUtil.empty() : IterUtil.toMap(new ArrayIter(httpServletRequest.getCookies()), new CaseInsensitiveMap(), Cookie::getName); + } + + + + public static String getRemoteIpAddress() { + return getRemoteIpAddress(getRequest()); + } + + /** + * 获取请求路径 + * + */ + public static String getRequestPath() { + return Objects.requireNonNull(getRequest()).getRequestURI(); + } + + public static String getRemoteIpAddress(HttpServletRequest request) { + String ip = null; + // X-Forwarded-For:Squid 服务代理 + String ipAddresses = request.getHeader("X-Forwarded-For"); + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // Proxy-Client-IP:apache 服务代理 + ipAddresses = request.getHeader("Proxy-Client-IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ipAddresses = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // WL-Proxy-Client-IP:weblogic 服务代理 + ipAddresses = request.getHeader("WL-Proxy-Client-IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // HTTP_CLIENT_IP:有些代理服务器 + ipAddresses = request.getHeader("HTTP_CLIENT_IP"); + } + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + // X-Real-IP:nginx服务代理 + ipAddresses = request.getHeader("X-Real-IP"); + } + // 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP + if (CharSequenceUtil.isNotBlank(ipAddresses)) { + ip = ipAddresses.split(",")[0]; + } + // 还是不能获取到,最后再通过request.getRemoteAddr();获取 + if (CharSequenceUtil.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ip = request.getRemoteAddr(); + } + return ip; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/CreateGenCustomListVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/CreateGenCustomListVo.java new file mode 100644 index 0000000..3ff6f17 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/CreateGenCustomListVo.java @@ -0,0 +1,174 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.xingyun.template.gen.enums.GenCustomListType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateGenCustomListVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 列表类型 + */ + @ApiModelProperty(value = "列表类型", required = true) + @NotNull(message = "列表类型不能为空!") + @IsEnum(message = "列表类型不能为空!", enumClass = GenCustomListType.class) + private Integer listType; + + /** + * 数据对象ID + */ + @ApiModelProperty(value = "数据对象ID", required = true) + @NotBlank(message = "数据对象ID不能为空!") + private String dataObjId; + + /** + * 表单Label宽度 + */ + @ApiModelProperty(value = "表单Label宽度", required = true) + @NotNull(message = "表单Label宽度不能为空!") + @Min(value = 1, message = "表单Label宽度不允许小于0!") + private Integer labelWidth; + + /** + * 是否分页 + */ + @ApiModelProperty(value = "是否分页", required = true) + @NotNull(message = "是否分页不能为空!") + private Boolean hasPage; + + /** + * 是否树形列表 + */ + @ApiModelProperty(value = "是否树形列表", required = true) + @NotNull(message = "是否树形列表不能为空!") + private Boolean treeData; + + /** + * ID字段 + */ + @ApiModelProperty(value = "ID字段", required = true) + @NotBlank(message = "ID字段不能为空!") + private String idColumn; + + /** + * ID字段关联ID + */ + @ApiModelProperty(value = "ID字段关联ID", required = true) + @NotBlank(message = "ID字段不能为空!") + private String idColumnRelaId; + + /** + * 父级ID字段 + */ + @ApiModelProperty("父级ID字段") + private String treePidColumn; + + /** + * 父级ID字段关联ID + */ + @ApiModelProperty("父级ID字段关联ID") + private String treePidColumnRelaId; + + /** + * 树形节点字段 + */ + @ApiModelProperty("树形节点字段") + private String treeNodeColumn; + + /** + * 树形节点字段关联ID + */ + @ApiModelProperty("树形节点字段关联ID") + private String treeNodeColumnRelaId; + + /** + * 子节点Key值 + */ + @ApiModelProperty("子节点Key值") + private String treeChildrenKey; + + /** + * 是否允许导出 + */ + @ApiModelProperty("是否允许导出") + @NotNull(message = "是否允许导出不能为空!") + private Boolean allowExport; + + /** + * 查询条件 + */ + @ApiModelProperty("查询条件") + @Valid + private List queryParams; + + /** + * 列表配置 + */ + @ApiModelProperty(value = "列表配置", required = true) + @NotEmpty(message = "列表配置不能为空!") + @Valid + private List details; + + /** + * 查询前置SQL + */ + @ApiModelProperty("查询前置SQL") + private String queryPrefixSql; + + /** + * 查询后置SQL + */ + @ApiModelProperty("查询后置SQL") + private String querySuffixSql; + + /** + * 后置SQL + */ + @ApiModelProperty("后置SQL") + private String suffixSql; + + /** + * 工具栏 + */ + @Valid + @ApiModelProperty("工具栏") + private List toolbars; + + /** + * 操作列 + */ + @Valid + @ApiModelProperty("操作列") + private List handleColumns; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListDetailVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListDetailVo.java new file mode 100644 index 0000000..36acf5f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListDetailVo.java @@ -0,0 +1,67 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenCustomListDetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 关联ID + */ + @ApiModelProperty(value = "关联ID") + private String relaId; + + /** + * 宽度类型 + */ + @ApiModelProperty(value = "宽度类型", required = true) + @NotNull(message = "宽度类型不能为空!") + @IsEnum(message = "宽度类型不能为空!", enumClass = GenQueryWidthType.class) + private Integer widthType; + + /** + * 是否页面排序 + */ + @ApiModelProperty(value = "是否页面排序", required = true) + @NotNull(message = "请选择是否页面排序!") + private Boolean sortable; + + /** + * 宽度 + */ + @ApiModelProperty(value = "宽度", required = true) + @NotNull(message = "宽度不能为空!") + @Min(value = 1, message = "宽度必须大于0!") + private Integer width; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型", required = true) + @NotNull(message = "类型不能为空!") + @IsEnum(message = "类型不能为空!", enumClass = GenCustomListDetailType.class) + private Integer type; + + /** + * 格式化脚本 + */ + @ApiModelProperty("格式化脚本") + private String formatter; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListHandleColumnVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListHandleColumnVo.java new file mode 100644 index 0000000..c8e644d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListHandleColumnVo.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnType; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnViewType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenCustomListHandleColumnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + @NotNull(message = "显示名称不能为空!") + private String name; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + @NotNull(message = "显示类型不能为空!") + @IsEnum(enumClass = GenCustomListBtnViewType.class, message = "显示类型格式错误!") + private String viewType; + + /** + * 按钮类型 + */ + @ApiModelProperty("按钮类型") + @NotNull(message = "按钮类型不能为空!") + @IsEnum(enumClass = GenCustomListBtnType.class, message = "显示类型格式错误!") + private Integer btnType; + + /** + * 按钮配置 + */ + @ApiModelProperty("按钮配置") + private String btnConfig; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 请求参数 + */ + @ApiModelProperty("请求参数") + private String requestParam; + + /** + * 宽度 + */ + @ApiModelProperty(value = "宽度", required = true) + @NotNull(message = "宽度不能为空!") + @Min(value = 0, message = "宽度必须大于0!") + private Integer width; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListQueryParamsVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListQueryParamsVo.java new file mode 100644 index 0000000..34628a4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListQueryParamsVo.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.xingyun.template.gen.enums.GenCustomListDetailType; +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenCustomListQueryParamsVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 关联ID + */ + @ApiModelProperty(value = "关联ID", required = true) + @NotBlank(message = "关联ID不能为空!") + private String relaId; + + /** + * 前端显示 + */ + @ApiModelProperty(value = "前端显示", required = true) + @NotNull(message = "前端显示不能为空!") + private Boolean frontShow; + + /** + * 查询类型 + */ + @ApiModelProperty(value = "查询类型", required = true) + @NotNull(message = "查询类型不能为空!") + @IsEnum(message = "查询类型不能为空!", enumClass = GenQueryType.class) + private Integer queryType; + + /** + * 表单宽度 + */ + @ApiModelProperty(value = "表单宽度", required = true) + @NotNull(message = "表单宽度不能为空!") + @Min(value = 1, message = "表单宽度不允许小于0!") + @Max(value = 24, message = "表单宽度不允许大于24!") + private Integer formWidth; + + /** + * 默认值 + */ + @ApiModelProperty("默认值") + private Object defaultValue; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型", required = true) + @NotNull(message = "类型不能为空!") + @IsEnum(message = "类型不能为空!", enumClass = GenCustomListDetailType.class) + private Integer type; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListSelectorVo.java new file mode 100644 index 0000000..02d491c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListSelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomListSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListToolbarVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListToolbarVo.java new file mode 100644 index 0000000..8beb586 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/GenCustomListToolbarVo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnType; +import com.lframework.xingyun.template.gen.enums.GenCustomListBtnViewType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenCustomListToolbarVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 显示名称 + */ + @ApiModelProperty("显示名称") + @NotNull(message = "显示名称不能为空!") + private String name; + + /** + * 显示类型 + */ + @ApiModelProperty("显示类型") + @NotNull(message = "显示类型不能为空!") + @IsEnum(enumClass = GenCustomListBtnViewType.class, message = "显示类型格式错误!") + private String viewType; + + /** + * 按钮类型 + */ + @ApiModelProperty("按钮类型") + @NotNull(message = "按钮类型不能为空!") + @IsEnum(enumClass = GenCustomListBtnType.class, message = "显示类型格式错误!") + private Integer btnType; + + /** + * 按钮配置 + */ + @ApiModelProperty("按钮配置") + private String btnConfig; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 请求参数 + */ + @ApiModelProperty("请求参数") + private String requestParam; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/QueryGenCustomListVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/QueryGenCustomListVo.java new file mode 100644 index 0000000..5eaeb8e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/QueryGenCustomListVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 查询自定义列表Vo + */ +@Data +public class QueryGenCustomListVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/UpdateGenCustomListVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/UpdateGenCustomListVo.java new file mode 100644 index 0000000..ecec21f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/UpdateGenCustomListVo.java @@ -0,0 +1,187 @@ +package com.lframework.xingyun.template.gen.vo.custom.list; + +import com.lframework.xingyun.template.gen.enums.GenCustomListType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenCustomListVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 列表类型 + */ + @ApiModelProperty(value = "列表类型", required = true) + @NotNull(message = "列表类型不能为空!") + @IsEnum(message = "列表类型不能为空!", enumClass = GenCustomListType.class) + private Integer listType; + + /** + * 表单Label宽度 + */ + @ApiModelProperty(value = "表单Label宽度", required = true) + @NotNull(message = "表单Label宽度不能为空!") + @Min(value = 1, message = "表单Label宽度不允许小于0!") + private Integer labelWidth; + + /** + * 是否分页 + */ + @ApiModelProperty(value = "是否分页", required = true) + @NotNull(message = "是否分页不能为空!") + private Boolean hasPage; + + /** + * 是否树形列表 + */ + @ApiModelProperty(value = "是否树形列表", required = true) + @NotNull(message = "是否树形列表不能为空!") + private Boolean treeData; + + /** + * ID字段 + */ + @ApiModelProperty(value = "ID字段", required = true) + @NotBlank(message = "ID字段不能为空!") + private String idColumn; + + /** + * ID字段关联ID + */ + @ApiModelProperty(value = "ID字段关联ID", required = true) + @NotBlank(message = "ID字段不能为空!") + private String idColumnRelaId; + + /** + * 父级ID字段 + */ + @ApiModelProperty("父级ID字段") + private String treePidColumn; + + /** + * 父级ID字段关联ID + */ + @ApiModelProperty("父级ID字段关联ID") + private String treePidColumnRelaId; + + /** + * 树形节点字段 + */ + @ApiModelProperty("树形节点字段") + private String treeNodeColumn; + + /** + * 树形节点字段关联ID + */ + @ApiModelProperty("树形节点字段关联ID") + private String treeNodeColumnRelaId; + + /** + * 子节点Key值 + */ + @ApiModelProperty("子节点Key值") + private String treeChildrenKey; + + /** + * 默认值 + */ + @ApiModelProperty("默认值") + private String defaultValue; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否允许导出 + */ + @ApiModelProperty("是否允许导出") + @NotNull(message = "是否允许导出不能为空!") + private Boolean allowExport; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 查询条件 + */ + @ApiModelProperty("查询条件") + @Valid + private List queryParams; + + /** + * 列表配置 + */ + @ApiModelProperty(value = "列表配置", required = true) + @NotEmpty(message = "列表配置不能为空!") + @Valid + private List details; + + /** + * 查询前置SQL + */ + @ApiModelProperty("查询前置SQL") + private String queryPrefixSql; + + /** + * 查询后置SQL + */ + @ApiModelProperty("查询后置SQL") + private String querySuffixSql; + + /** + * 后置SQL + */ + @ApiModelProperty("后置SQL") + private String suffixSql; + + /** + * 工具栏 + */ + @Valid + @ApiModelProperty("工具栏") + private List toolbars; + + /** + * 操作列 + */ + @Valid + @ApiModelProperty("操作列") + private List handleColumns; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/CreateGenCustomListCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/CreateGenCustomListCategoryVo.java new file mode 100644 index 0000000..a452137 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/CreateGenCustomListCategoryVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.custom.list.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenCustomListCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/GenCustomListCategorySelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/GenCustomListCategorySelectorVo.java new file mode 100644 index 0000000..e6d369f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/GenCustomListCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.vo.custom.list.category; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomListCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/UpdateGenCustomListCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/UpdateGenCustomListCategoryVo.java new file mode 100644 index 0000000..064c41f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/list/category/UpdateGenCustomListCategoryVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.vo.custom.list.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenCustomListCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/CreateGenCustomPageVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/CreateGenCustomPageVo.java new file mode 100644 index 0000000..60fb258 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/CreateGenCustomPageVo.java @@ -0,0 +1,46 @@ +package com.lframework.xingyun.template.gen.vo.custom.page; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenCustomPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 页面代码 + */ + @ApiModelProperty(value = "页面代码", required = true) + @NotBlank(message = "页面代码不能为空!") + private String pageCode; + + /** + * 脚本代码 + */ + @ApiModelProperty(value = "脚本代码", required = true) + @NotBlank(message = "脚本代码不能为空!") + private String scriptCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/GenCustomPageSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/GenCustomPageSelectorVo.java new file mode 100644 index 0000000..b52a5ef --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/GenCustomPageSelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.custom.page; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomPageSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private Integer id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/QueryGenCustomPageVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/QueryGenCustomPageVo.java new file mode 100644 index 0000000..9f17ffb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/QueryGenCustomPageVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.vo.custom.page; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 查询自定义页面Vo + */ +@Data +public class QueryGenCustomPageVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private Integer id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/UpdateGenCustomPageVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/UpdateGenCustomPageVo.java new file mode 100644 index 0000000..ed8b012 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/UpdateGenCustomPageVo.java @@ -0,0 +1,47 @@ +package com.lframework.xingyun.template.gen.vo.custom.page; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenCustomPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private Integer id; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 页面代码 + */ + @ApiModelProperty(value = "页面代码", required = true) + @NotBlank(message = "页面代码不能为空!") + private String pageCode; + + /** + * 脚本代码 + */ + @ApiModelProperty(value = "脚本代码", required = true) + @NotBlank(message = "脚本代码不能为空!") + private String scriptCode; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/CreateGenCustomPageCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/CreateGenCustomPageCategoryVo.java new file mode 100644 index 0000000..4aa93d4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/CreateGenCustomPageCategoryVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.gen.vo.custom.page.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenCustomPageCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty(value = "父级ID") + private String parentId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/UpdateGenCustomPageCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/UpdateGenCustomPageCategoryVo.java new file mode 100644 index 0000000..5eb6dfe --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/page/category/UpdateGenCustomPageCategoryVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.vo.custom.page.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenCustomPageCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/CreateGenCustomSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/CreateGenCustomSelectorVo.java new file mode 100644 index 0000000..d481edf --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/CreateGenCustomSelectorVo.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenCustomSelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 自定义列表ID + */ + @ApiModelProperty(value = "自定义列表ID", required = true) + @NotBlank(message = "自定义列表ID不能为空!") + private String customListId; + + /** + * 对话框标题 + */ + @ApiModelProperty(value = "对话框标题") + private String dialogTittle; + + /** + * 对话框宽度 + */ + @ApiModelProperty(value = "对话框宽度", required = true) + @NotBlank(message = "对话框宽度不能为空!") + private String dialogWidth; + + /** + * 占位符 + */ + @ApiModelProperty("占位符") + private String placeholder; + + /** + * ID字段 + */ + @ApiModelProperty(value = "ID字段", required = true) + @NotBlank(message = "ID字段不能为空!") + private String idColumn; + + /** + * ID字段关联ID + */ + @ApiModelProperty(value = "ID字段关联ID", required = true) + @NotBlank(message = "ID字段不能为空!") + private String idColumnRelaId; + + /** + * 名称字段 + */ + @ApiModelProperty(value = "名称字段", required = true) + @NotBlank(message = "名称字段不能为空!") + private String nameColumn; + + /** + * 名称字段关联ID + */ + @ApiModelProperty(value = "名称字段关联ID", required = true) + @NotBlank(message = "名称字段不能为空!") + private String nameColumnRelaId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/GenCustomSelectorSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/GenCustomSelectorSelectorVo.java new file mode 100644 index 0000000..70abb47 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/GenCustomSelectorSelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomSelectorSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/QueryGenCustomSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/QueryGenCustomSelectorVo.java new file mode 100644 index 0000000..dd50f0e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/QueryGenCustomSelectorVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 查询自定义选择器Vo + */ +@Data +public class QueryGenCustomSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/UpdateGenCustomSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/UpdateGenCustomSelectorVo.java new file mode 100644 index 0000000..e302820 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/UpdateGenCustomSelectorVo.java @@ -0,0 +1,90 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenCustomSelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 对话框标题 + */ + @ApiModelProperty(value = "对话框标题") + private String dialogTittle; + + /** + * 对话框宽度 + */ + @ApiModelProperty(value = "对话框宽度", required = true) + @NotBlank(message = "对话框宽度不能为空!") + private String dialogWidth; + + /** + * 占位符 + */ + @ApiModelProperty("占位符") + private String placeholder; + + /** + * ID字段 + */ + @ApiModelProperty("ID字段") + private String idColumn; + + /** + * ID字段关联ID + */ + @ApiModelProperty("ID字段关联ID") + private String idColumnRelaId; + + /** + * 名称字段 + */ + @ApiModelProperty("名称字段") + private String nameColumn; + + /** + * 名称字段关联ID + */ + @ApiModelProperty("名称字段关联ID") + private String nameColumnRelaId; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/CreateGenCustomSelectorCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/CreateGenCustomSelectorCategoryVo.java new file mode 100644 index 0000000..f84cb40 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/CreateGenCustomSelectorCategoryVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenCustomSelectorCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/GenCustomSelectorCategorySelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/GenCustomSelectorCategorySelectorVo.java new file mode 100644 index 0000000..b7ce894 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/GenCustomSelectorCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector.category; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenCustomSelectorCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/UpdateGenCustomSelectorCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/UpdateGenCustomSelectorCategoryVo.java new file mode 100644 index 0000000..5e413b0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/custom/selector/category/UpdateGenCustomSelectorCategoryVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.vo.custom.selector.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenCustomSelectorCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/CreateDataEntityVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/CreateDataEntityVo.java new file mode 100644 index 0000000..2d03016 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/CreateDataEntityVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class CreateDataEntityVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 数据表 + */ + @ApiModelProperty(value = "数据表", required = true) + @NotBlank(message = "数据表不能为空!") + private String tableName; + + /** + * 字段信息 + */ + @ApiModelProperty(value = "字段信息", required = true) + @Valid + @NotEmpty(message = "字段信息不能为空!") + private List columns; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailSelectorVo.java new file mode 100644 index 0000000..37162e9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailSelectorVo.java @@ -0,0 +1,20 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class GenDataEntityDetailSelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 数据实体ID + */ + @ApiModelProperty("数据实体ID") + @NotBlank(message = "数据实体ID不能为空!") + private String entityId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailVo.java new file mode 100644 index 0000000..66bbf20 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntityDetailVo.java @@ -0,0 +1,119 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.xingyun.template.gen.enums.GenOrderType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenDataEntityDetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 字段显示名称 + */ + @ApiModelProperty(value = "字段显示名称", required = true) + @NotBlank(message = "显示名称不能为空!") + private String name; + + /** + * 数据类型 + */ + @ApiModelProperty(value = "数据类型", required = true) + @NotNull(message = "数据类型不能为空!") + @IsEnum(message = "数据类型格式不正确!", enumClass = GenDataType.class) + private Integer dataType; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 显示类型 + */ + @ApiModelProperty(value = "显示类型", required = true) + @NotNull(message = "显示类型不能为空!") + @IsEnum(message = "显示类型格式不正确!", enumClass = GenDataType.class) + private Integer viewType; + + /** + * 是否内置枚举 + */ + @ApiModelProperty(value = "是否内置枚举", required = true) + @NotNull(message = "是否内置枚举不能为空!") + private Boolean fixEnum; + + /** + * 后端枚举名 + */ + @ApiModelProperty("后端枚举名") + private String enumBack; + + /** + * 前端枚举名 + */ + @ApiModelProperty("前端枚举名") + private String enumFront; + + /** + * 正则表达式 + */ + @ApiModelProperty("正则表达式") + private String regularExpression; + + /** + * 是否排序字段 + */ + @ApiModelProperty(value = "是否排序字段", required = true) + @NotNull(message = "是否排序字段不能为空!") + private Boolean isOrder; + + /** + * 排序类型 + */ + @ApiModelProperty("排序类型") + @IsEnum(message = "排序类型格式不正确!", enumClass = GenOrderType.class) + private String orderType; + + /** + * 数据字典ID + */ + @ApiModelProperty("数据字典ID") + private String dataDicId; + + /** + * 自定义选择器ID + */ + @ApiModelProperty("自定义选择器ID") + private String customSelectorId; + + /** + * 长度 + */ + @ApiModelProperty("长度") + @Min(value = 1, message = "长度必须大于0!") + private Long len; + + /** + * 小数位数 + */ + @ApiModelProperty("小数位数") + @Min(value = 1, message = "小数位数必须大于0!") + private Integer decimals; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntitySelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntitySelectorVo.java new file mode 100644 index 0000000..eeac666 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/GenDataEntitySelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntitySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/QueryDataEntityVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/QueryDataEntityVo.java new file mode 100644 index 0000000..e3fd825 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/QueryDataEntityVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 查询数据实体列表Vo + */ +@Data +public class QueryDataEntityVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityGenerateVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityGenerateVo.java new file mode 100644 index 0000000..b7aeb45 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityGenerateVo.java @@ -0,0 +1,72 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.xingyun.template.gen.vo.gen.UpdateCreateColumnConfigVo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateDetailColumnConfigVo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateGenerateInfoVo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateQueryColumnConfigVo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateQueryParamsColumnConfigVo; +import com.lframework.xingyun.template.gen.vo.gen.UpdateUpdateColumnConfigVo; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateDataEntityGenerateVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 基础设置 + */ + @ApiModelProperty(value = "基础设置", required = true) + @Valid + @NotNull(message = "基本设置不能为空!") + private UpdateGenerateInfoVo generateInfo; + + /** + * 新增配置 + */ + @ApiModelProperty("新增配置") + @Valid + private List createConfigs; + + /** + * 修改配置 + */ + @ApiModelProperty("修改配置") + @Valid + private List updateConfigs; + + /** + * 查询配置 + */ + @ApiModelProperty("查询配置") + @Valid + private List queryConfigs; + + /** + * 查询参数配置 + */ + @ApiModelProperty("查询参数配置") + @Valid + private List queryParamsConfigs; + + /** + * 详情配置 + */ + @ApiModelProperty("详情配置") + @Valid + private List detailConfigs; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityVo.java new file mode 100644 index 0000000..6c51b45 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/UpdateDataEntityVo.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.template.gen.vo.data.entity; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateDataEntityVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 字段信息 + */ + @ApiModelProperty(value = "字段信息", required = true) + @Valid + @NotEmpty(message = "字段信息不能为空!") + private List columns; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/CreateGenDataEntityCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/CreateGenDataEntityCategoryVo.java new file mode 100644 index 0000000..3faf7d9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/CreateGenDataEntityCategoryVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.data.entity.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenDataEntityCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/GenDataEntityCategorySelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/GenDataEntityCategorySelectorVo.java new file mode 100644 index 0000000..10d78f5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/GenDataEntityCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.vo.data.entity.category; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataEntityCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/UpdateGenDataEntityCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/UpdateGenDataEntityCategoryVo.java new file mode 100644 index 0000000..0d76626 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/entity/category/UpdateGenDataEntityCategoryVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.vo.data.entity.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenDataEntityCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/CreateGenDataObjVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/CreateGenDataObjVo.java new file mode 100644 index 0000000..b0e73b6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/CreateGenDataObjVo.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.template.gen.vo.data.obj; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenDataObjVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 主表 + */ + @ApiModelProperty(value = "主表", required = true) + @NotBlank(message = "主表不能为空!") + private String mainTableId; + + /** + * 主表别名 + */ + @ApiModelProperty(value = "主表别名", required = true) + @NotBlank(message = "主表别名不能为空!") + private String mainTableAlias; + + /** + * 关联信息 + */ + @ApiModelProperty(value = "关联信息") + @Valid + private List columns; + + /** + * 自定义查询 + */ + @ApiModelProperty(value = "自定义查询") + @Valid + private List queryColumns; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjDetailVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjDetailVo.java new file mode 100644 index 0000000..52a7b2b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjDetailVo.java @@ -0,0 +1,70 @@ +package com.lframework.xingyun.template.gen.vo.data.obj; + +import com.lframework.xingyun.template.gen.enums.GenRelaMode; +import com.lframework.xingyun.template.gen.enums.GenRelaType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenDataObjDetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 主表字段 + */ + @ApiModelProperty(value = "主表字段", required = true) + @NotEmpty(message = "主表字段不能为空!") + private List mainTableDetailIds; + + /** + * 关联类型 + */ + @ApiModelProperty(value = "关联类型", required = true) + @NotNull(message = "关联类型不能为空!") + @IsEnum(message = "关联类型不能为空!", enumClass = GenRelaType.class) + private Integer relaType; + + /** + * 关联方式 + */ + @ApiModelProperty(value = "关联方式", required = true) + @NotNull(message = "关联方式不能为空!") + @IsEnum(message = "关联方式不能为空!", enumClass = GenRelaMode.class) + private Integer relaMode; + + /** + * 子表ID + */ + @ApiModelProperty(value = "子表ID", required = true) + @NotBlank(message = "子表ID不能为空!") + private String subTableId; + + /** + * 子表别名 + */ + @ApiModelProperty(value = "子表别名", required = true) + @NotBlank(message = "子表别名不能为空!") + private String subTableAlias; + + /** + * 子表字段 + */ + @ApiModelProperty(value = "子表字段", required = true) + @NotEmpty(message = "子表字段不能为空!") + private List subTableDetailIds; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjQueryDetailVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjQueryDetailVo.java new file mode 100644 index 0000000..02821bf --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjQueryDetailVo.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.template.gen.vo.data.obj; + +import com.lframework.xingyun.template.gen.enums.GenDataType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class GenDataObjQueryDetailVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 显示名称 + */ + @ApiModelProperty(value = "显示名称", required = true) + @NotBlank(message = "显示名称不能为空!") + private String customName; + + /** + * 自定义SQL + */ + @ApiModelProperty(value = "自定义SQL", required = true) + @NotBlank(message = "自定义SQL不能为空!") + private String customSql; + + /** + * 别名 + */ + @ApiModelProperty(value = "别名", required = true) + @NotBlank(message = "别名不能为空!") + private String customAlias; + + /** + * 数据类型 + */ + @ApiModelProperty(value = "数据类型", required = true) + @NotNull(message = "数据类型不能为空!") + @IsEnum(message = "数据类型格式不正确!", enumClass = GenDataType.class) + private Integer dataType; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjSelectorVo.java new file mode 100644 index 0000000..373174f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/GenDataObjSelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.data.obj; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataObjSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/QueryGenDataObjVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/QueryGenDataObjVo.java new file mode 100644 index 0000000..18b53d3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/QueryGenDataObjVo.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.gen.vo.data.obj; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 查询数据对象列表Vo + */ +@Data +public class QueryGenDataObjVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/UpdateGenDataObjVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/UpdateGenDataObjVo.java new file mode 100644 index 0000000..0dce245 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/UpdateGenDataObjVo.java @@ -0,0 +1,70 @@ +package com.lframework.xingyun.template.gen.vo.data.obj; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenDataObjVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 主表别名 + */ + @ApiModelProperty(value = "主表别名", required = true) + @NotBlank(message = "主表别名不能为空!") + private String mainTableAlias; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 关联信息 + */ + @ApiModelProperty(value = "关联信息") + @Valid + private List columns; + + /** + * 自定义查询 + */ + @ApiModelProperty(value = "自定义查询") + @Valid + private List queryColumns; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/CreateGenDataObjCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/CreateGenDataObjCategoryVo.java new file mode 100644 index 0000000..0f2ed75 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/CreateGenDataObjCategoryVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.gen.vo.data.obj.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateGenDataObjCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/GenDataObjCategorySelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/GenDataObjCategorySelectorVo.java new file mode 100644 index 0000000..1554d2c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/GenDataObjCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.gen.vo.data.obj.category; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GenDataObjCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/UpdateGenDataObjCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/UpdateGenDataObjCategoryVo.java new file mode 100644 index 0000000..4ea5fb5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/data/obj/category/UpdateGenDataObjCategoryVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.gen.vo.data.obj.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenDataObjCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateCreateColumnConfigVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateCreateColumnConfigVo.java new file mode 100644 index 0000000..0af54b5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateCreateColumnConfigVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.vo.gen; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateCreateColumnConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 是否必填 + */ + @ApiModelProperty(value = "是否必填", required = true) + @NotNull(message = "是否必填不能为空!") + private Boolean required; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateDetailColumnConfigVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateDetailColumnConfigVo.java new file mode 100644 index 0000000..c6885d4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateDetailColumnConfigVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.vo.gen; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateDetailColumnConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 列宽 + */ + @ApiModelProperty(value = "列宽", required = true) + @NotNull(message = "列宽不能为空!") + private Integer span; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateGenerateInfoVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateGenerateInfoVo.java new file mode 100644 index 0000000..095301c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateGenerateInfoVo.java @@ -0,0 +1,117 @@ +package com.lframework.xingyun.template.gen.vo.gen; + +import com.lframework.xingyun.template.gen.enums.GenKeyType; +import com.lframework.xingyun.template.gen.enums.GenTemplateType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateGenerateInfoVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 生成模板类型 + */ + @ApiModelProperty(value = "生成模板类型", required = true) + @NotNull(message = "生成模板类型不能为空!") + @IsEnum(message = "生成模板类型格式不正确!", enumClass = GenTemplateType.class) + private Integer templateType; + + /** + * 包名 + */ + @ApiModelProperty(value = "包名", required = true) + @NotBlank(message = "包名不能为空!") + private String packageName; + + /** + * 模块名称 + */ + @ApiModelProperty(value = "模块名称", required = true) + @NotBlank(message = "模块名称不能为空!") + private String moduleName; + + /** + * 业务名称 + */ + @ApiModelProperty(value = "业务名称", required = true) + @NotBlank(message = "业务名称不能为空!") + private String bizName; + + /** + * 类名 + */ + @ApiModelProperty(value = "类名", required = true) + @NotBlank(message = "类名不能为空!") + private String className; + + /** + * 类描述 + */ + @ApiModelProperty(value = "类描述", required = true) + @NotBlank(message = "类描述不能为空!") + private String classDescription; + + /** + * 父级菜单ID + */ + @ApiModelProperty("父级菜单ID") + private String parentMenuId; + + /** + * 主键类型 + */ + @ApiModelProperty(value = "主键类型", required = true) + @NotNull(message = "主键类型不能为空!") + @IsEnum(message = "主键类型格式不正确!", enumClass = GenKeyType.class) + private Integer keyType; + + /** + * 作者 + */ + @ApiModelProperty("作者") + private String author; + + /** + * 本级菜单编号 + */ + @ApiModelProperty(value = "本级菜单编号", required = true) + @NotNull(message = "本级菜单编号不能为空!") + private String menuCode; + + /** + * 本级菜单名称 + */ + @ApiModelProperty(value = "本级菜单名称", required = true) + @NotNull(message = "本级菜单名称不能为空!") + private String menuName; + + /** + * 详情页Span总数量 + */ + @ApiModelProperty(value = "详情页Span总数量", required = true) + @NotNull(message = "详情页Span总数量不能为空!") + @Min(value = 1, message = "详情页Span总数量必须大于0!") + private Integer detailSpan; + + /** + * 是否应用缓存 + */ + @ApiModelProperty(value = "是否应用缓存", required = true) + @NotNull(message = "是否应用缓存不能为空!") + private Boolean isCache; + + /** + * 是否内置删除功能 + */ + @ApiModelProperty(value = "是否内置删除功能", required = true) + @NotNull(message = "是否内置删除功能不能为空!") + private Boolean hasDelete; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryColumnConfigVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryColumnConfigVo.java new file mode 100644 index 0000000..44cf497 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryColumnConfigVo.java @@ -0,0 +1,46 @@ +package com.lframework.xingyun.template.gen.vo.gen; + +import com.lframework.xingyun.template.gen.enums.GenQueryWidthType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateQueryColumnConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 宽度类型 + */ + @ApiModelProperty(value = "宽度类型", required = true) + @NotNull(message = "宽度类型不能为空!") + @IsEnum(message = "宽度类型不能为空!", enumClass = GenQueryWidthType.class) + private Integer widthType; + + /** + * 是否页面排序 + */ + @ApiModelProperty(value = "是否页面排序", required = true) + @NotNull(message = "请选择是否页面排序!") + private Boolean sortable; + + /** + * 宽度 + */ + @ApiModelProperty(value = "宽度", required = true) + @NotNull(message = "宽度不能为空!") + @Min(value = 1, message = "宽度必须大于0!") + private Integer width; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryParamsColumnConfigVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryParamsColumnConfigVo.java new file mode 100644 index 0000000..23cf77e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateQueryParamsColumnConfigVo.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.template.gen.vo.gen; + +import com.lframework.xingyun.template.gen.enums.GenQueryType; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateQueryParamsColumnConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 查询类型 + */ + @ApiModelProperty(value = "查询类型", required = true) + @NotNull(message = "查询类型不能为空!") + @IsEnum(message = "查询类型不能为空!", enumClass = GenQueryType.class) + private Integer queryType; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateUpdateColumnConfigVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateUpdateColumnConfigVo.java new file mode 100644 index 0000000..939f286 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/gen/UpdateUpdateColumnConfigVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.gen.vo.gen; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateUpdateColumnConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private String id; + + /** + * 是否必填 + */ + @ApiModelProperty(value = "是否必填", required = true) + @NotNull(message = "是否必填不能为空!") + private Boolean required; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/QuerySimpleTableColumnVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/QuerySimpleTableColumnVo.java new file mode 100644 index 0000000..8920089 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/QuerySimpleTableColumnVo.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.template.gen.vo.simpledb; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QuerySimpleTableColumnVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 数据表所属的数据库名 + */ + @ApiModelProperty(value = "数据表所属的数据库名", required = true) + private String tableSchema; + + /** + * 数据库表名 + */ + @ApiModelProperty(value = "数据库表名", required = true) + @NotBlank(message = "请输入数据库表名!") + private String tableName; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/SimpleTableSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/SimpleTableSelectorVo.java new file mode 100644 index 0000000..7912e49 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/gen/vo/simpledb/SimpleTableSelectorVo.java @@ -0,0 +1,17 @@ +package com.lframework.xingyun.template.gen.vo.simpledb; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SimpleTableSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/CollectMenuBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/CollectMenuBo.java new file mode 100644 index 0000000..ef39e66 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/CollectMenuBo.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.inner.bo.auth; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class CollectMenuBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 路由路径 + */ + @ApiModelProperty("路由路径") + private String path; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/ForgetPswUserInfoBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/ForgetPswUserInfoBo.java new file mode 100644 index 0000000..cb7a533 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/ForgetPswUserInfoBo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.inner.bo.auth; + +import com.lframework.starter.web.bo.SuperBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ForgetPswUserInfoBo implements SuperBo { + + /** + * 用户名 + */ + @ApiModelProperty("用户名") + private String username; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱,脱敏") + private String email; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话,脱敏") + private String telephone; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/LoginBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/LoginBo.java new file mode 100644 index 0000000..bd4e763 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/LoginBo.java @@ -0,0 +1,62 @@ +package com.lframework.xingyun.template.inner.bo.auth; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.inner.dto.LoginDto; +import com.lframework.xingyun.template.inner.dto.LoginDto.UserInfoDto; +import io.swagger.annotations.ApiModelProperty; +import java.util.Set; +import lombok.Data; + +@Data +public class LoginBo extends BaseBo { + + /** + * Token + */ + @ApiModelProperty("Token") + private String token; + + /** + * 用户信息 + */ + @ApiModelProperty("用户信息") + private UserInfoBo user; + + /** + * 角色 + */ + @ApiModelProperty("角色") + private Set roles; + + public LoginBo() { + } + + public LoginBo(LoginDto dto) { + super(dto); + } + + @Override + protected void afterInit(LoginDto dto) { + + this.user = new UserInfoBo(dto.getUser()); + } + + @Data + public static class UserInfoBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + public UserInfoBo() { + } + + public UserInfoBo(UserInfoDto dto) { + super(dto); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/MenuBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/MenuBo.java new file mode 100644 index 0000000..be18b20 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/MenuBo.java @@ -0,0 +1,114 @@ +package com.lframework.xingyun.template.inner.bo.auth; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; + +@Data +public class MenuBo extends BaseBo { + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 组件 + */ + @ApiModelProperty("组件") + private String component; + + /** + * 子节点 + */ + @ApiModelProperty("子节点") + private List children; + + /** + * 路由路径 + */ + @ApiModelProperty("路由路径") + private String path; + + /** + * 元数据 + */ + @ApiModelProperty("元数据") + private MetaBo meta; + + public MenuBo() { + } + + @Data + public static class MetaBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 是否隐藏 + */ + @ApiModelProperty("是否隐藏") + private Boolean hideMenu; + + /** + * 是否不缓存 + */ + @ApiModelProperty("是否不缓存") + private Boolean ignoreKeepAlive; + + /** + * 是否固定 + */ + @ApiModelProperty("是否固定") + private Boolean affix = Boolean.FALSE; + + /** + * 是否外部链接 + */ + @ApiModelProperty("是否外部链接") + private Boolean isLink = Boolean.FALSE; + + /** + * 是否收藏 + */ + @ApiModelProperty("是否收藏") + private Boolean isCollect = Boolean.FALSE; + + /** + * 内嵌链接地址 + */ + @ApiModelProperty("内嵌链接地址") + private String frameSrc; + + /** + * 自定义列表ID + */ + @ApiModelProperty("自定义列表ID") + private String customListId; + + /** + * 自定义页面ID + */ + @ApiModelProperty("自定义页面ID") + private String customPageId; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/TelephoneLoginBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/TelephoneLoginBo.java new file mode 100644 index 0000000..f755f18 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/auth/TelephoneLoginBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.bo.auth; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.inner.dto.LoginDto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 手机号登录Bo + * + * @author zmj + * @since 2022/4/25 + */ +@Data +public class TelephoneLoginBo extends BaseBo { + + /** + * 登录信息 + */ + @ApiModelProperty("登录信息") + private LoginBo loginInfo; + + /** + * 是否绑定用户 + */ + @ApiModelProperty("是否绑定用户") + private Boolean isBind = Boolean.TRUE; + + public TelephoneLoginBo() { + + } + + public TelephoneLoginBo(LoginDto dto) { + + this.afterInit(dto); + } + + @Override + protected void afterInit(LoginDto dto) { + + this.loginInfo = new LoginBo(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/oplog/OpLogInUserCenterBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/oplog/OpLogInUserCenterBo.java new file mode 100644 index 0000000..4e8de4d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/oplog/OpLogInUserCenterBo.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.template.inner.bo.oplog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.core.entity.OpLogs; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class OpLogInUserCenterBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 日志名称 + */ + @ApiModelProperty("日志名称") + private String name; + + /** + * 类别 + */ + @ApiModelProperty("类别") + private Integer logType; + + /** + * IP + */ + @ApiModelProperty("IP") + private String ip; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public OpLogInUserCenterBo() { + + } + + public OpLogInUserCenterBo(OpLogs dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/GetQrtzBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/GetQrtzBo.java new file mode 100644 index 0000000..61b415b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/GetQrtzBo.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.template.inner.bo.qrtz; + +import com.lframework.xingyun.template.inner.dto.qrtz.QrtzDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; + +@Data +public class GetQrtzBo extends BaseBo { + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分组 + */ + @ApiModelProperty("分组") + private String group; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 执行类名 + */ + @ApiModelProperty("执行类名") + private String targetClassName; + + /** + * 执行方法名 + */ + @ApiModelProperty("执行方法名") + private String targetMethodName; + + /** + * 执行参数类型 + */ + @ApiModelProperty("执行参数类型") + private List targetParamTypes; + + /** + * 执行参数 + */ + @ApiModelProperty("执行参数") + private List targetParams; + + /** + * 脚本 + */ + @ApiModelProperty("脚本") + private String script; + + /** + * 任务类型 + */ + @ApiModelProperty("任务类型") + private Integer jobType; + + /** + * Cron表达式 + */ + @ApiModelProperty("Cron表达式") + private String cron; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private String state; + + public GetQrtzBo(QrtzDto dto) { + super(dto); + } + + @Override + public BaseBo convert(QrtzDto dto) { + return super.convert(dto, GetQrtzBo::getState); + } + + @Override + protected void afterInit(QrtzDto dto) { + this.jobType = dto.getJobType().getCode(); + if (dto.getState() != null) { + this.state = dto.getState().getCode(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/QueryQrtzBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/QueryQrtzBo.java new file mode 100644 index 0000000..fafda0f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/qrtz/QueryQrtzBo.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.inner.bo.qrtz; + +import com.lframework.xingyun.template.inner.dto.qrtz.QrtzDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryQrtzBo extends BaseBo { + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分组 + */ + @ApiModelProperty("分组") + private String group; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 任务类型 + */ + @ApiModelProperty("任务类型") + private Integer jobType; + + /** + * Cron表达式 + */ + @ApiModelProperty("Cron表达式") + private String cron; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private String state; + + public QueryQrtzBo(QrtzDto dto) { + super(dto); + } + + @Override + public BaseBo convert(QrtzDto dto) { + return super.convert(dto, QueryQrtzBo::getState); + } + + @Override + protected void afterInit(QrtzDto dto) { + this.jobType = dto.getJobType().getCode(); + if (dto.getState() != null) { + this.state = dto.getState().getCode(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/GetSysDeptBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/GetSysDeptBo.java new file mode 100644 index 0000000..ffdb127 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/GetSysDeptBo.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.template.inner.bo.system.dept; + +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysDeptBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 简称 + */ + @ApiModelProperty("简称") + private String shortName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysDeptBo() { + + } + + public GetSysDeptBo(SysDept dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptSelectorBo.java new file mode 100644 index 0000000..4506a1d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.bo.system.dept; + +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDeptSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SysDeptSelectorBo() { + + } + + public SysDeptSelectorBo(SysDept dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptTreeBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptTreeBo.java new file mode 100644 index 0000000..a7d6c1a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dept/SysDeptTreeBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.bo.system.dept; + +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDeptTreeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SysDeptTreeBo() { + + } + + public SysDeptTreeBo(SysDept dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/GetSysDataDicBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/GetSysDataDicBo.java new file mode 100644 index 0000000..04c4ff6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/GetSysDataDicBo.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.template.inner.bo.system.dic; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.xingyun.template.inner.service.system.SysDataDicCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysDataDicBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + + public GetSysDataDicBo() { + + } + + public GetSysDataDicBo(SysDataDic dto) { + + super(dto); + } + + @Override + protected void afterInit(SysDataDic dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + SysDataDicCategoryService sysDataDicCategoryService = ApplicationUtil.getBean( + SysDataDicCategoryService.class); + SysDataDicCategory category = sysDataDicCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/QuerySysDataDicBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/QuerySysDataDicBo.java new file mode 100644 index 0000000..c1c7816 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/QuerySysDataDicBo.java @@ -0,0 +1,64 @@ +package com.lframework.xingyun.template.inner.bo.system.dic; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.xingyun.template.inner.service.system.SysDataDicCategoryService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QuerySysDataDicBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; + + /** + * 分类名称 + */ + @ApiModelProperty("分类名称") + private String categoryName; + + + public QuerySysDataDicBo() { + + } + + public QuerySysDataDicBo(SysDataDic dto) { + + super(dto); + } + + @Override + protected void afterInit(SysDataDic dto) { + if (!StringUtil.isBlank(dto.getCategoryId())) { + SysDataDicCategoryService sysDataDicCategoryService = ApplicationUtil.getBean( + SysDataDicCategoryService.class); + SysDataDicCategory category = sysDataDicCategoryService.findById(dto.getCategoryId()); + this.categoryName = category.getName(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/SysDataDicSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/SysDataDicSelectorBo.java new file mode 100644 index 0000000..699785f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/SysDataDicSelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.inner.bo.system.dic; + +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDataDicSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public SysDataDicSelectorBo() { + } + + public SysDataDicSelectorBo(SysDataDic dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java new file mode 100644 index 0000000..092745c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/GetSysDataDicCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.inner.bo.system.dic.category; + +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysDataDicCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public GetSysDataDicCategoryBo() { + + } + + public GetSysDataDicCategoryBo(SysDataDicCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java new file mode 100644 index 0000000..3af3e9f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/QuerySysDataDicCategoryBo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.inner.bo.system.dic.category; + +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QuerySysDataDicCategoryBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + + public QuerySysDataDicCategoryBo() { + + } + + public QuerySysDataDicCategoryBo(SysDataDicCategory dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java new file mode 100644 index 0000000..0a25a2b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/category/SysDataDicCategorySelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.inner.bo.system.dic.category; + +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDataDicCategorySelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public SysDataDicCategorySelectorBo() { + } + + public SysDataDicCategorySelectorBo(SysDataDicCategory dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/GetSysDataDicItemBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/GetSysDataDicItemBo.java new file mode 100644 index 0000000..c9913d2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/GetSysDataDicItemBo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.inner.bo.system.dic.item; + +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysDataDicItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 字典ID + */ + @ApiModelProperty("字典ID") + private String dicId; + + /** + * 排序 + */ + @ApiModelProperty("排序") + private Integer orderNo; + + + public GetSysDataDicItemBo() { + + } + + public GetSysDataDicItemBo(SysDataDicItem dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/QuerySysDataDicItemBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/QuerySysDataDicItemBo.java new file mode 100644 index 0000000..ada02c7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/QuerySysDataDicItemBo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.inner.bo.system.dic.item; + +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QuerySysDataDicItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 字典ID + */ + @ApiModelProperty("字典ID") + private String dicId; + + /** + * 排序 + */ + @ApiModelProperty("排序") + private Integer orderNo; + + + public QuerySysDataDicItemBo() { + + } + + public QuerySysDataDicItemBo(SysDataDicItem dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/SysDataDicItemBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/SysDataDicItemBo.java new file mode 100644 index 0000000..e31d485 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/dic/item/SysDataDicItemBo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.template.inner.bo.system.dic.item; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDataDicItemBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + public SysDataDicItemBo() { + + } + + public SysDataDicItemBo(SysDataDicItem dto) { + + super(dto); + } + + @Override + protected void afterInit(SysDataDicItem dto) { + SysDataDicService sysDataDicService = ApplicationUtil.getBean(SysDataDicService.class); + SysDataDic dataDic = sysDataDicService.findById(dto.getDicId()); + this.id = dataDic.getCode() + StringPool.DATA_DIC_SPLIT + this.code; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/GetSysMenuBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/GetSysMenuBo.java new file mode 100644 index 0000000..eb00f7a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/GetSysMenuBo.java @@ -0,0 +1,192 @@ +package com.lframework.xingyun.template.inner.bo.system.menu; + +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.template.gen.entity.GenCustomList; +import com.lframework.xingyun.template.gen.service.GenCustomListService; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.xingyun.template.inner.enums.system.SysMenuComponentType; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysMenuBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称(前端使用) + */ + @ApiModelProperty("名称(前端使用)") + private String name; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 组件类型 + */ + @ApiModelProperty("组件类型(前端使用)") + private Integer componentType; + + /** + * 组件(前端使用) + */ + @ApiModelProperty("组件(前端使用)") + private String component; + + /** + * 自定义列表ID + */ + @ApiModelProperty("自定义列表ID") + private String customListId; + + /** + * 自定义列表名称 + */ + @ApiModelProperty("自定义列表名称") + private String customListName; + + /** + * 自定义表单ID + */ + @ApiModelProperty("自定义表单ID") + private String customFormId; + + /** + * 自定义表单名称 + */ + @ApiModelProperty("自定义表单名称") + private String customFormName; + + /** + * 自定义请求参数 + */ + @ApiModelProperty("自定义请求参数") + private String requestParam; + + /** + * 自定义页面ID + */ + @ApiModelProperty("自定义页面ID") + private String customPageId; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 父级名称 + */ + @ApiModelProperty("父级名称") + private String parentName; + + /** + * 路由路径(前端使用) + */ + @ApiModelProperty("路由路径(前端使用)") + private String path; + + /** + * 是否缓存(前端使用) + */ + @ApiModelProperty("是否缓存(前端使用)") + private Boolean noCache; + + /** + * 类型 0-目录 1-菜单 2-功能 + */ + @ApiModelProperty("类型 0-目录 1-菜单 2-功能") + private Integer display; + + /** + * 是否隐藏(前端使用) + */ + @ApiModelProperty("是否隐藏(前端使用)") + private Boolean hidden; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 是否特殊菜单 + */ + @ApiModelProperty("是否特殊菜单") + private Boolean isSpecial; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysMenuBo() { + + } + + public GetSysMenuBo(SysMenu dto) { + + super(dto); + } + + @Override + public BaseBo convert(SysMenu dto) { + + return super.convert(dto, GetSysMenuBo::getDisplay); + } + + @Override + protected void afterInit(SysMenu dto) { + + this.display = dto.getDisplay().getCode(); + if (!StringUtil.isBlank(dto.getParentId())) { + SysMenuService sysMenuService = ApplicationUtil.getBean(SysMenuService.class); + this.parentName = sysMenuService.findById(dto.getParentId()).getTitle(); + } + + this.componentType = dto.getComponentType() == null ? null : dto.getComponentType().getCode(); + if (dto.getComponentType() == SysMenuComponentType.CUSTOM_LIST) { + this.customListId = dto.getComponent(); + GenCustomListService genCustomListService = ApplicationUtil + .getBean(GenCustomListService.class); + GenCustomList customList = genCustomListService.findById(dto.getComponent()); + this.customListName = customList.getName(); + } else if (dto.getComponentType() == SysMenuComponentType.CUSTOM_PAGE) { + this.customPageId = dto.getComponent(); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/QuerySysMenuBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/QuerySysMenuBo.java new file mode 100644 index 0000000..d78370b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/QuerySysMenuBo.java @@ -0,0 +1,93 @@ +package com.lframework.xingyun.template.inner.bo.system.menu; + +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QuerySysMenuBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 类型 + */ + @ApiModelProperty("类型") + private Integer display; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 是否特殊菜单 + */ + @ApiModelProperty("是否特殊菜单") + private Boolean isSpecial; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public QuerySysMenuBo() { + + } + + public QuerySysMenuBo(SysMenu dto) { + + super(dto); + } + + @Override + public BaseBo convert(SysMenu dto) { + + return super.convert(dto, QuerySysMenuBo::getDisplay); + } + + @Override + protected void afterInit(SysMenu dto) { + + this.display = dto.getDisplay().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/SysMenuSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/SysMenuSelectorBo.java new file mode 100644 index 0000000..430fad7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/menu/SysMenuSelectorBo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.template.inner.bo.system.menu; + +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysMenuSelectorBo extends BaseBo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + public SysMenuSelectorBo() { + + } + + public SysMenuSelectorBo(SysMenu dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/module/QuerySysModuleBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/module/QuerySysModuleBo.java new file mode 100644 index 0000000..e9ec361 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/module/QuerySysModuleBo.java @@ -0,0 +1,45 @@ +package com.lframework.xingyun.template.inner.bo.system.module; + +import com.lframework.xingyun.template.inner.entity.SysModule; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySysModuleBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private Integer id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 是否启用 + */ + @ApiModelProperty("是否启用") + private Boolean enabled; + + /** + * 过期时间 + */ + @ApiModelProperty("过期时间") + private LocalDateTime expireTime; + + public QuerySysModuleBo(SysModule dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/GetSysNoticeBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/GetSysNoticeBo.java new file mode 100644 index 0000000..b451b0a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/GetSysNoticeBo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.template.inner.bo.system.notice; + +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 系统通知 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysNoticeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 内容 + */ + @ApiModelProperty("内容") + private String content; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 是否发布 + */ + @ApiModelProperty("是否发布") + private Boolean published; + + public GetSysNoticeBo() { + + } + + public GetSysNoticeBo(SysNotice dto) { + + super(dto); + } + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QueryMySysNoticeBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QueryMySysNoticeBo.java new file mode 100644 index 0000000..13ad41a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QueryMySysNoticeBo.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.template.inner.bo.system.notice; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 我的系统通知 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QueryMySysNoticeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 是否已读 + */ + @ApiModelProperty("是否已读") + private Boolean readed; + + /** + * 发布时间 + */ + @ApiModelProperty("发布时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime publishTime; + + public QueryMySysNoticeBo() { + + } + + public QueryMySysNoticeBo(QuerySysNoticeByUserDto dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QuerySysNoticeBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QuerySysNoticeBo.java new file mode 100644 index 0000000..b94376b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/notice/QuerySysNoticeBo.java @@ -0,0 +1,89 @@ +package com.lframework.xingyun.template.inner.bo.system.notice; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统通知 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysNoticeBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 是否发布 + */ + @ApiModelProperty("是否发布") + private Boolean published; + + /** + * 发布时间 + */ + @ApiModelProperty("发布时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime publishTime; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 已读人数 + */ + @ApiModelProperty("已读人数") + private Integer readedNum; + + /** + * 未读人数 + */ + @ApiModelProperty("未读人数") + private Integer unReadNum; + + public QuerySysNoticeBo() { + + } + + public QuerySysNoticeBo(SysNotice dto) { + + super(dto); + } + + @Override + protected void afterInit(SysNotice dto) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/GetSysOpenDomainBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/GetSysOpenDomainBo.java new file mode 100644 index 0000000..21db57c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/GetSysOpenDomainBo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.template.inner.bo.system.open; + +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.starter.web.annotations.convert.EncryptConvert; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysOpenDomainBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * API密钥 + */ + @ApiModelProperty("API密钥") + @EncryptConvert + private String apiSecret; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private Integer tenantId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysOpenDomainBo() { + + } + + public GetSysOpenDomainBo(SysOpenDomain dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/QuerySysOpenDomainBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/QuerySysOpenDomainBo.java new file mode 100644 index 0000000..1ad6fda --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/QuerySysOpenDomainBo.java @@ -0,0 +1,57 @@ +package com.lframework.xingyun.template.inner.bo.system.open; + +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.starter.web.annotations.convert.EncryptConvert; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QuerySysOpenDomainBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * API密钥 + */ + @ApiModelProperty("API密钥") + @EncryptConvert + private String apiSecret; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public QuerySysOpenDomainBo() { + + } + + public QuerySysOpenDomainBo(SysOpenDomain dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/SysOpenDomainSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/SysOpenDomainSelectorBo.java new file mode 100644 index 0000000..5c94117 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/open/SysOpenDomainSelectorBo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.inner.bo.system.open; + +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysOpenDomainSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SysOpenDomainSelectorBo() { + } + + public SysOpenDomainSelectorBo(SysOpenDomain dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/GetOpLogBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/GetOpLogBo.java new file mode 100644 index 0000000..1ec2541 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/GetOpLogBo.java @@ -0,0 +1,65 @@ +package com.lframework.xingyun.template.inner.bo.system.oplog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.core.entity.OpLogs; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class GetOpLogBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 日志名称 + */ + @ApiModelProperty("日志名称") + private String name; + + /** + * 类别 + */ + @ApiModelProperty("类别") + private Integer logType; + + /** + * IP地址 + */ + @ApiModelProperty("IP地址") + private String ip; + + /** + * 补充信息 + */ + @ApiModelProperty("补充信息") + private String extra; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public GetOpLogBo() { + + } + + public GetOpLogBo(OpLogs dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/QueryOpLogBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/QueryOpLogBo.java new file mode 100644 index 0000000..2790b15 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/oplog/QueryOpLogBo.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.template.inner.bo.system.oplog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.core.entity.OpLogs; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QueryOpLogBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 日志名称 + */ + @ApiModelProperty("日志名称") + private String name; + + /** + * 类别 + */ + @ApiModelProperty("类别") + private Integer logType; + + /** + * IP地址 + */ + @ApiModelProperty("IP地址") + private String ip; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QueryOpLogBo() { + + } + + public QueryOpLogBo(OpLogs dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/GetSysParameterBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/GetSysParameterBo.java new file mode 100644 index 0000000..9c18fc7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/GetSysParameterBo.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.template.inner.bo.system.parameter; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.lframework.xingyun.template.inner.entity.SysParameter; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 系统参数 GetBo + *

+ * + * @author zmj + */ +@Data +public class GetSysParameterBo extends BaseBo { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + @ApiModelProperty("ID") + private Long id; + + /** + * 键 + */ + @ApiModelProperty("键") + private String pmKey; + + /** + * 值 + */ + @ApiModelProperty("值") + private String pmValue; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysParameterBo() { + + } + + public GetSysParameterBo(SysParameter dto) { + + super(dto); + } + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/QuerySysParameterBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/QuerySysParameterBo.java new file mode 100644 index 0000000..6fa695f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/parameter/QuerySysParameterBo.java @@ -0,0 +1,73 @@ +package com.lframework.xingyun.template.inner.bo.system.parameter; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.inner.entity.SysParameter; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统参数 QueryBo + *

+ * + * @author zmj + */ +@Data +public class QuerySysParameterBo extends BaseBo { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + @ApiModelProperty("ID") + private Long id; + + /** + * 键 + */ + @ApiModelProperty("键") + private String pmKey; + + /** + * 值 + */ + @ApiModelProperty("值") + private String pmValue; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + public QuerySysParameterBo() { + + } + + public QuerySysParameterBo(SysParameter dto) { + + super(dto); + } + + @Override + protected void afterInit(SysParameter dto) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java new file mode 100644 index 0000000..834d0a8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/QuerySysDataPermissionModelDetailBo.java @@ -0,0 +1,94 @@ +package com.lframework.xingyun.template.inner.bo.system.permission; + +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; + +@Data +public class QuerySysDataPermissionModelDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 明细ID + */ + @ApiModelProperty("明细ID") + private Integer detailId; + + /** + * 节点类型 + */ + @ApiModelProperty("节点类型") + private Integer nodeType; + + /** + * 计算类型 + */ + @ApiModelProperty("计算类型") + private Integer calcType; + + /** + * 值 + */ + @ApiModelProperty("值") + private String value; + + /** + * 值 + */ + @ApiModelProperty("值") + private List values; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 模型ID + */ + @ApiModelProperty("模型ID") + private Integer modelId; + + /** + * 条件 + */ + @ApiModelProperty("条件") + private Integer[] conditionTypes; + + /** + * 输入类型 + */ + @ApiModelProperty("输入类型") + @EnumConvert + private Integer inputType; + + /** + * 条件类型 + */ + @ApiModelProperty("条件类型") + private Integer conditionType; + + /** + * 前段枚举名 + */ + @ApiModelProperty("前端枚举名") + private String enumName; + + /** + * 子节点 + */ + @ApiModelProperty("子节点") + private List children; + + public QuerySysDataPermissionModelDetailBo() { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/SysDataPermissionModelDetailBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/SysDataPermissionModelDetailBo.java new file mode 100644 index 0000000..5fbe83b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/permission/SysDataPermissionModelDetailBo.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.template.inner.bo.system.permission; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.core.entity.SysDataPermissionModelDetail; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDataPermissionModelDetailBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private Integer id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 模型ID + */ + @ApiModelProperty("模型ID") + private Integer modelId; + + /** + * 条件 + */ + @ApiModelProperty("条件") + private String[] conditionTypes; + + /** + * 输入类型 + */ + @ApiModelProperty("输入类型") + @EnumConvert + private Integer inputType; + + /** + * 前段枚举名 + */ + @ApiModelProperty("前端枚举名") + private String enumName; + + public SysDataPermissionModelDetailBo() { + } + + public SysDataPermissionModelDetailBo(SysDataPermissionModelDetail dto) { + super(dto); + } + + @Override + protected void afterInit(SysDataPermissionModelDetail dto) { + this.conditionTypes = dto.getConditionType().split(StringPool.STR_SPLIT); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/GetSysPositionBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/GetSysPositionBo.java new file mode 100644 index 0000000..14c1f2a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/GetSysPositionBo.java @@ -0,0 +1,54 @@ +package com.lframework.xingyun.template.inner.bo.system.position; + +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysPositionBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysPositionBo() { + + } + + public GetSysPositionBo(SysPosition dto) { + + super(dto); + } + + @Override + protected void afterInit(SysPosition dto) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/QuerySysPositionBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/QuerySysPositionBo.java new file mode 100644 index 0000000..5d660bc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/QuerySysPositionBo.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.template.inner.bo.system.position; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySysPositionBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySysPositionBo() { + + } + + public QuerySysPositionBo(SysPosition dto) { + + super(dto); + } + + @Override + protected void afterInit(SysPosition dto) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/SysPositionSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/SysPositionSelectorBo.java new file mode 100644 index 0000000..4e6cffb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/position/SysPositionSelectorBo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.template.inner.bo.system.position; + +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysPositionSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SysPositionSelectorBo() { + + } + + public SysPositionSelectorBo(SysPosition dto) { + + super(dto); + } + + @Override + protected void afterInit(SysPosition dto) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/GetSysRoleBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/GetSysRoleBo.java new file mode 100644 index 0000000..bfe97b9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/GetSysRoleBo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.template.inner.bo.system.role; + +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetSysRoleBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysRoleBo() { + + } + + public GetSysRoleBo(SysRole dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QueryRoleMenuBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QueryRoleMenuBo.java new file mode 100644 index 0000000..fc02d23 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QueryRoleMenuBo.java @@ -0,0 +1,85 @@ +package com.lframework.xingyun.template.inner.bo.system.role; + +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryRoleMenuBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 类型 + */ + @ApiModelProperty("类型") + private Integer display; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 是否选择 + */ + @ApiModelProperty("是否选择") + private Boolean selected = Boolean.FALSE; + + public QueryRoleMenuBo() { + + } + + public QueryRoleMenuBo(SysMenu dto) { + + super(dto); + } + + @Override + public
BaseBo convert(SysMenu dto) { + + return super.convert(dto, QueryRoleMenuBo::getDisplay); + } + + @Override + protected void afterInit(SysMenu dto) { + + this.display = dto.getDisplay().getCode(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QuerySysRoleBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QuerySysRoleBo.java new file mode 100644 index 0000000..ca78fcc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/QuerySysRoleBo.java @@ -0,0 +1,88 @@ +package com.lframework.xingyun.template.inner.bo.system.role; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySysRoleBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySysRoleBo() { + + } + + public QuerySysRoleBo(SysRole dto) { + + super(dto); + } + + @Override + protected void afterInit(SysRole dto) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/SysRoleSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/SysRoleSelectorBo.java new file mode 100644 index 0000000..039f6c1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/role/SysRoleSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.bo.system.role; + +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysRoleSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SysRoleSelectorBo() { + + } + + public SysRoleSelectorBo(SysRole dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/GetTenantBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/GetTenantBo.java new file mode 100644 index 0000000..c5ab240 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/GetTenantBo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.template.inner.bo.system.tenant; + +import com.lframework.starter.web.annotations.constants.EncryType; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.starter.web.annotations.convert.EncryptConvert; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GetTenantBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * JdbcUrl + */ + @ApiModelProperty("JdbcUrl") + @EncryptConvert + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @ApiModelProperty("Jdbc用户名") + @EncryptConvert + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @ApiModelProperty("Jdbc密码") + @EncryptConvert(type = EncryType.PASSWORD) + private String jdbcPassword; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public GetTenantBo(Tenant dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/QueryTenantBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/QueryTenantBo.java new file mode 100644 index 0000000..198c83b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/QueryTenantBo.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.template.inner.bo.system.tenant; + +import com.lframework.starter.web.annotations.constants.EncryType; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.starter.web.annotations.convert.EncryptConvert; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryTenantBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * JdbcUrl + */ + @ApiModelProperty("JdbcUrl") + @EncryptConvert + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @ApiModelProperty("Jdbc用户名") + @EncryptConvert + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @ApiModelProperty("Jdbc密码") + @EncryptConvert(type = EncryType.PASSWORD) + private String jdbcPassword; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public QueryTenantBo(Tenant dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/TenantSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/TenantSelectorBo.java new file mode 100644 index 0000000..ed082f9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/tenant/TenantSelectorBo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.inner.bo.system.tenant; + +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class TenantSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public TenantSelectorBo() { + + } + + public TenantSelectorBo(Tenant dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/GetSysUserBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/GetSysUserBo.java new file mode 100644 index 0000000..7a5ea95 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/GetSysUserBo.java @@ -0,0 +1,228 @@ +package com.lframework.xingyun.template.inner.bo.system.user; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.inner.entity.SysUserDept; +import com.lframework.xingyun.template.inner.entity.SysUserPosition; +import com.lframework.xingyun.template.inner.entity.SysUserRole; +import com.lframework.xingyun.template.inner.service.system.SysDeptService; +import com.lframework.xingyun.template.inner.service.system.SysPositionService; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.service.system.SysUserDeptService; +import com.lframework.xingyun.template.inner.service.system.SysUserPositionService; +import com.lframework.xingyun.template.inner.service.system.SysUserRoleService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.dto.VoidDto; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import lombok.Data; + +@Data +public class GetSysUserBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 用户名 + */ + @ApiModelProperty("用户名") + private String username; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱") + private String email; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 性别 + */ + @ApiModelProperty("性别") + private Integer gender; + + /** + * 岗位 + */ + @ApiModelProperty("岗位") + private List positions; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String positionName; + + /** + * 部门 + */ + @ApiModelProperty("部门") + private List depts; + + /** + * 部门名称 + */ + @ApiModelProperty("部门名称") + private String deptName; + + + /** + * 角色 + */ + @ApiModelProperty("角色") + private List roles; + + /** + * 角色名称 + */ + @ApiModelProperty("角色名称") + private String roleName; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 是否锁定 + */ + @ApiModelProperty("是否锁定") + private Boolean lockStatus; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + public GetSysUserBo() { + + } + + public GetSysUserBo(SysUser dto) { + + super(dto); + } + + @Override + protected void afterInit(SysUser dto) { + + SysUserPositionService sysUserPositionService = ApplicationUtil.getBean( + SysUserPositionService.class); + List userPositions = sysUserPositionService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userPositions)) { + SysPositionService sysPositionService = ApplicationUtil.getBean(SysPositionService.class); + this.positions = userPositions.stream().map(SysUserPosition::getPositionId) + .collect(Collectors.toList()); + + this.positionName = StringUtil.join(StringPool.STR_SPLIT_CN, + userPositions.stream().map(t -> sysPositionService.findById(t.getPositionId())) + .filter(Objects::nonNull).map(SysPosition::getName) + .collect(Collectors.toList())); + } + + SysUserDeptService sysUserDeptService = ApplicationUtil.getBean(SysUserDeptService.class); + List userDepts = sysUserDeptService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userDepts)) { + SysDeptService sysDeptService = ApplicationUtil.getBean(SysDeptService.class); + this.depts = userDepts.stream().map(SysUserDept::getDeptId) + .collect(Collectors.toList()); + + this.deptName = StringUtil.join(StringPool.STR_SPLIT_CN, + userDepts.stream().map(t -> sysDeptService.findById(t.getDeptId())) + .filter(Objects::nonNull).map(SysDept::getName) + .collect(Collectors.toList())); + } + + SysUserRoleService sysUserRoleService = ApplicationUtil.getBean(SysUserRoleService.class); + List userRoles = sysUserRoleService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userRoles)) { + SysRoleService sysRoleService = ApplicationUtil.getBean(SysRoleService.class); + this.roles = userRoles.stream().map(SysUserRole::getRoleId) + .collect(Collectors.toList()); + + this.roleName = StringUtil.join(StringPool.STR_SPLIT_CN, + userRoles.stream().map(t -> sysRoleService.findById(t.getRoleId())) + .filter(Objects::nonNull).map(SysRole::getName) + .collect(Collectors.toList())); + } + } + + @Data + public static class PositionBo extends BaseBo { + + /** + * 岗位ID + */ + @ApiModelProperty("岗位ID") + private String id; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String name; + } + + @Data + public static class DeptBo extends BaseBo { + + /** + * 部门ID + */ + @ApiModelProperty("部门ID") + private String id; + + /** + * 部门名称 + */ + @ApiModelProperty("部门名称") + private String name; + } + + @Data + public static class RoleBo extends BaseBo { + + /** + * 角色ID + */ + @ApiModelProperty("角色ID") + private String id; + + /** + * 角色名称 + */ + @ApiModelProperty("角色名称") + private String name; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QuerySysUserBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QuerySysUserBo.java new file mode 100644 index 0000000..b23cf6e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QuerySysUserBo.java @@ -0,0 +1,187 @@ +package com.lframework.xingyun.template.inner.bo.system.user; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.inner.entity.SysUserDept; +import com.lframework.xingyun.template.inner.entity.SysUserPosition; +import com.lframework.xingyun.template.inner.entity.SysUserRole; +import com.lframework.xingyun.template.inner.service.system.SysDeptService; +import com.lframework.xingyun.template.inner.service.system.SysPositionService; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.service.system.SysUserDeptService; +import com.lframework.xingyun.template.inner.service.system.SysUserPositionService; +import com.lframework.xingyun.template.inner.service.system.SysUserRoleService; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +@Data +public class QuerySysUserBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + private String positionName; + + /** + * 部门名称 + */ + @ApiModelProperty("部门名称") + private String deptName; + + /** + * 角色名称 + */ + @ApiModelProperty("角色名称") + private String roleName; + + /** + * 用户名 + */ + @ApiModelProperty("用户名") + private String username; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱") + private String email; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 性别 + */ + @ApiModelProperty("性别") + private Integer gender; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 是否锁定 + */ + @ApiModelProperty("是否锁定") + private Boolean lockStatus; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 创建人 + */ + @ApiModelProperty("创建人") + private String createBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime createTime; + + /** + * 修改人 + */ + @ApiModelProperty("修改人") + private String updateBy; + + /** + * 修改时间 + */ + @ApiModelProperty("修改时间") + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + private LocalDateTime updateTime; + + public QuerySysUserBo() { + + } + + public QuerySysUserBo(SysUser dto) { + + super(dto); + } + + @Override + protected void afterInit(SysUser dto) { + + SysUserPositionService sysUserPositionService = ApplicationUtil.getBean( + SysUserPositionService.class); + List userPositions = sysUserPositionService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userPositions)) { + SysPositionService sysPositionService = ApplicationUtil.getBean(SysPositionService.class); + List positionNames = new ArrayList<>(userPositions.size()); + for (SysUserPosition userPosition : userPositions) { + SysPosition position = sysPositionService.findById(userPosition.getPositionId()); + positionNames.add(position.getName()); + } + + this.positionName = StringUtil.join(StringPool.STR_SPLIT_CN, positionNames); + } + + SysUserDeptService sysUserDeptService = ApplicationUtil.getBean(SysUserDeptService.class); + List userDepts = sysUserDeptService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userDepts)) { + SysDeptService sysDeptService = ApplicationUtil.getBean(SysDeptService.class); + List deptNames = new ArrayList<>(userDepts.size()); + for (SysUserDept userDept : userDepts) { + SysDept dept = sysDeptService.findById(userDept.getDeptId()); + deptNames.add(dept.getName()); + } + + this.deptName = StringUtil.join(StringPool.STR_SPLIT_CN, deptNames); + } + + SysUserRoleService sysUserRoleService = ApplicationUtil.getBean(SysUserRoleService.class); + List userRoles = sysUserRoleService.getByUserId(dto.getId()); + if (!CollectionUtil.isEmpty(userRoles)) { + SysRoleService sysRoleService = ApplicationUtil.getBean(SysRoleService.class); + List roleNames = new ArrayList<>(userRoles.size()); + for (SysUserRole userRole : userRoles) { + SysRole role = sysRoleService.findById(userRole.getRoleId()); + roleNames.add(role.getName()); + } + + this.roleName = StringUtil.join(StringPool.STR_SPLIT_CN, roleNames); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QueryUserRoleBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QueryUserRoleBo.java new file mode 100644 index 0000000..49095d0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/QueryUserRoleBo.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.inner.bo.system.user; + +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QueryUserRoleBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 是否选中 + */ + @ApiModelProperty("是否选中") + private Boolean selected = Boolean.FALSE; + + public QueryUserRoleBo() { + + } + + public QueryUserRoleBo(SysRole dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/SysUserSelectorBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/SysUserSelectorBo.java new file mode 100644 index 0000000..4a05f61 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/system/user/SysUserSelectorBo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.bo.system.user; + +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.starter.web.bo.BaseBo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysUserSelectorBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + public SysUserSelectorBo() { + + } + + public SysUserSelectorBo(SysUser dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/usercenter/UserInfoBo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/usercenter/UserInfoBo.java new file mode 100644 index 0000000..834854f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/bo/usercenter/UserInfoBo.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.template.inner.bo.usercenter; + +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.xingyun.template.inner.dto.UserInfoDto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class UserInfoBo extends BaseBo { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 登录名 + */ + @ApiModelProperty("登录名") + private String username; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱") + private String email; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 性别 + */ + @ApiModelProperty("性别") + private Integer gender; + + public UserInfoBo() { + + } + + public UserInfoBo(UserInfoDto dto) { + + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/components/qrtz/DynamicQrtzJob.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/components/qrtz/DynamicQrtzJob.java new file mode 100644 index 0000000..401764a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/components/qrtz/DynamicQrtzJob.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.template.inner.components.qrtz; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.xingyun.template.core.components.qrtz.QrtzJob; +import com.lframework.xingyun.template.inner.enums.QrtzJobType; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.GroovyUtil; +import java.lang.reflect.Method; +import java.util.List; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; + +/** + * @author zmj + * @since 2022/8/20 + */ +public class DynamicQrtzJob extends QrtzJob { + + @Override + protected void onExecute(JobExecutionContext context) throws Exception { + + JobDetail jobDetail = context.getJobDetail(); + JobDataMap jobDataMap = jobDetail.getJobDataMap(); + QrtzJobType jobType = EnumUtil.getByCode(QrtzJobType.class, jobDataMap.getInt("jobType")); + if (jobType == QrtzJobType.EXCUTE_CLASS) { + String targetClassName = jobDataMap.getString("targetClassName"); + String targetMethodName = jobDataMap.getString("targetMethodName"); + List targetParamTypes = (List) jobDataMap.get("targetParamTypes"); + List targetParams = (List) jobDataMap.get("targetParams"); + + Class clazz = Class.forName(targetClassName); + Object target = ReflectUtil.newInstance(clazz); + Class[] paramTypes = null; + if (!CollectionUtil.isEmpty(targetParamTypes)) { + paramTypes = new Class[targetParamTypes.size()]; + for (int i = 0; i < targetParamTypes.size(); i++) { + String targetParamType = targetParamTypes.get(i); + paramTypes[i] = Class.forName(targetParamType); + } + } + Object[] params = null; + if (!CollectionUtil.isEmpty(targetParams)) { + params = new Object[targetParams.size()]; + for (int i = 0; i < targetParams.size(); i++) { + String targetParamType = targetParams.get(i); + params[i] = targetParamType; + } + } + + Method method = ReflectUtil.getMethod(clazz, targetMethodName, paramTypes); + ReflectUtil.invoke(target, method, params); + } else { + String script = jobDataMap.getString("script"); + GroovyUtil.excuteScript(script); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/config/OpLogTimerConfiguration.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/config/OpLogTimerConfiguration.java new file mode 100644 index 0000000..8b09f6a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/config/OpLogTimerConfiguration.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.template.inner.config; + +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.xingyun.template.core.components.qrtz.QrtzJob; +import com.lframework.starter.web.utils.TenantUtil; +import com.lframework.xingyun.template.core.components.qrtz.QrtzHandler; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.xingyun.template.inner.service.TenantService; +import java.time.LocalDateTime; +import java.util.List; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Component +public class OpLogTimerConfiguration implements ApplicationListener { + + private static final String JOB_NAME = "OP_LOG_TIMER"; + + private static final String JOB_GROUP_NAME = "OP_LOG_TIMER_GROUP"; + + private static final String TRIGGER_NAME = "OP_LOG_TIMER_TRIGGER"; + + private static final String TRIGGER_GROUP_NAME = "OP_LOG_TIMER_TRIGGER_GROUP"; + + @Value("${op-logs.enabled:'true'}") + private Boolean enabled; + + @Override + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { + + // 没有使用@Bean的配置方式是因为当enabled==false时,需要移除定时任务 + JobDetail jobDetail = QrtzHandler.getJob(JOB_NAME, JOB_GROUP_NAME); + if (jobDetail == null) { + // 没有任务 + if (!this.enabled) { + return; + } + + QrtzHandler.addJob(JOB_NAME, JOB_GROUP_NAME, OpLogClearJob.class, TRIGGER_NAME, + TRIGGER_GROUP_NAME, + "0 0 * * * ? *"); + } else { + if (!this.enabled) { + QrtzHandler.deleteJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME); + } + } + } + + public static class OpLogClearJob extends QrtzJob { + + @Autowired + private OpLogsService opLogsService; + + @Autowired + private TenantService tenantService; + + /** + * 操作日志保留天数 + */ + @Value("${op-logs.retain-days:7}") + private Integer retainDays; + + @Override + public void onExecute(JobExecutionContext context) { + + LocalDateTime now = LocalDateTime.now(); + LocalDateTime endTime = now.minusDays(retainDays); + + if (TenantUtil.enableTenant()) { + List tenants = tenantService.list(); + for (Tenant tenant : tenants) { + TenantContextHolder.setTenantId(tenant.getId()); + opLogsService.clearLogs(endTime); + } + } else { + opLogsService.clearLogs(endTime); + } + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/AuthController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/AuthController.java new file mode 100644 index 0000000..2f8bfdc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/AuthController.java @@ -0,0 +1,575 @@ +package com.lframework.xingyun.template.inner.controller; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.codec.Base64; +import com.google.code.kaptcha.Producer; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.UserLoginException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.annotations.OpenApi; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.CaptchaValidator; +import com.lframework.starter.web.components.redis.RedisHandler; +import com.lframework.starter.web.components.security.IUserTokenResolver; +import com.lframework.starter.web.components.security.PasswordEncoderWrapper; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.config.properties.KaptchaProperties; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.dto.GenerateCaptchaDto; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.JsonUtil; +import com.lframework.starter.web.utils.TenantUtil; +import com.lframework.xingyun.template.core.components.permission.SysDataPermissionDataPermissionType; +import com.lframework.xingyun.template.core.entity.SysDataPermissionData; +import com.lframework.xingyun.template.core.enums.SysDataPermissionDataBizType; +import com.lframework.xingyun.template.core.service.SysDataPermissionModelDetailService; +import com.lframework.xingyun.template.core.vo.permission.SysDataPermissionModelDetailVo; +import com.lframework.xingyun.template.inner.bo.auth.CollectMenuBo; +import com.lframework.xingyun.template.inner.bo.auth.LoginBo; +import com.lframework.xingyun.template.inner.bo.auth.MenuBo; +import com.lframework.xingyun.template.inner.bo.auth.MenuBo.MetaBo; +import com.lframework.xingyun.template.inner.dto.LoginDto; +import com.lframework.xingyun.template.inner.dto.MenuDto; +import com.lframework.xingyun.template.inner.entity.SysUserDept; +import com.lframework.xingyun.template.inner.entity.SysUserRole; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.xingyun.template.inner.enums.system.SysMenuComponentType; +import com.lframework.xingyun.template.inner.enums.system.SysMenuDisplay; +import com.lframework.xingyun.template.inner.events.LoginEvent; +import com.lframework.xingyun.template.inner.events.LogoutEvent; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.service.TenantService; +import com.lframework.xingyun.template.inner.service.system.SysDataPermissionDataService; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import com.lframework.xingyun.template.inner.service.system.SysUserDeptService; +import com.lframework.xingyun.template.inner.service.system.SysUserRoleService; +import com.lframework.xingyun.template.inner.service.system.SysUserService; +import com.lframework.xingyun.template.inner.vo.system.user.LoginVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.imageio.ImageIO; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.FastByteArrayOutputStream; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 默认用户认证Controller + * + * @author zmj + */ +@Api(tags = "用户认证") +@Slf4j +@Validated +@RestController +public class AuthController extends DefaultBaseController { + + @Autowired + private Producer producer; + + @Autowired + private KaptchaProperties kaptchaProperties; + + @Autowired + private RedisHandler redisHandler; + + @Autowired + private CaptchaValidator captchaValidator; + + @Autowired + private PasswordEncoderWrapper passwordEncoderWrapper; + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private IUserTokenResolver userTokenResolver; + + @Autowired + private TenantService tenantService; + + @Autowired + private SysDataPermissionDataService sysDataPermissionDataService; + + @Autowired + private SysDataPermissionModelDetailService sysDataPermissionModelDetailService; + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 获取登录验证码 + */ + @ApiOperation(value = "获取登录验证码") + @OpenApi + @GetMapping("/auth/captcha") + public InvokeResult generateCaptcha() { + + String code = producer.createText(); + BufferedImage image = producer.createImage(code); + + // 转换流信息写出 + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try { + ImageIO.write(image, "jpg", os); + } catch (IOException e) { + throw new DefaultClientException("验证码生成失败,请稍后重试!"); + } + + String sn = IdUtil.getUUID(); + //将验证码存至redis + redisHandler.set(StringUtil.format(StringPool.LOGIN_CAPTCHA_KEY, sn), code, + kaptchaProperties.getExpireTime() * 60 * 1000L); + + GenerateCaptchaDto resp = new GenerateCaptchaDto(); + resp.setSn(sn); + resp.setImage("data:image/jpeg;base64," + Base64.encode(os.toByteArray())); + + log.debug("获取验证码成功, SN={}, code={}", sn, code); + + return InvokeResultBuilder.success(resp); + } + + @ApiOperation("登录") + @OpenApi + @PostMapping("/auth/login") + public InvokeResult login(@Valid LoginVo vo) { + + String username = vo.getUsername(); + String password = vo.getPassword(); + String tenantId = null; + if (TenantUtil.enableTenant()) { + String[] tmpArr = username.split("@"); + if (tmpArr.length <= 1) { + throw new DefaultClientException("用户名或密码错误!"); + } + + tenantId = tmpArr[0]; + username = tmpArr[1]; + + // 检查租户是否存在 + Tenant tenant = tenantService.getById(tenantId); + if (tenant == null) { + throw new DefaultClientException("用户名或密码错误!"); + } + + if (!tenant.getAvailable()) { + throw new DefaultClientException("用户已停用,无法登录!"); + } + + TenantContextHolder.setTenantId(tenant.getId()); + } + + log.info("用户 {} {} 开始登录", tenantId, username); + + String sn = vo.getSn(); + String captcha = vo.getCaptcha(); + captchaValidator.validate(sn, captcha); + + this.checkUserLogin(tenantId == null ? null : Integer.valueOf(tenantId), username, password); + + AbstractUserDetails user = userDetailsService.loadUserByUsername(username); + + LoginDto dto = this.doLogin(user); + + this.addAttributesToSession(user); + + return InvokeResultBuilder.success(new LoginBo(dto)); + } + + @ApiOperation("退出登录") + @OpenApi + @PostMapping("/auth/logout") + public InvokeResult logout() { + + AbstractUserDetails user = getCurrentUser(); + + String token = null; + if (user != null) { + token = userTokenResolver.getToken(); + } + + StpUtil.logout(); + + if (user != null) { + ApplicationUtil.publishEvent(new LogoutEvent(this, user, token)); + } + + return InvokeResultBuilder.success(); + } + + @ApiOperation(value = "获取用户信息") + @GetMapping("/auth/info") + public InvokeResult info() { + + AbstractUserDetails user = getCurrentUser(); + LoginDto info = new LoginDto(null, user.getName(), user.getPermissions()); + + return InvokeResultBuilder.success(new LoginBo(info)); + } + + @ApiOperation("获取用户菜单") + @GetMapping("/auth/menus") + public InvokeResult> menus() { + + AbstractUserDetails user = getCurrentUser(); + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + List menus = sysMenuService.getMenuByUserId(user.getId(), user.isAdmin(), moduleIds); + + // 组装成树形菜单 + List topMenus = menus.stream().filter(t -> StringUtil.isBlank(t.getParentId())) + .collect(Collectors.toList()); + + List results = new ArrayList<>(); + for (MenuDto topMenu : topMenus) { + MenuBo menuBo = new MenuBo(); + menuBo.setName(topMenu.getName()); + menuBo.setComponent("LAYOUT"); + menuBo.setChildren(parseChildrenMenu(topMenu, menus)); + menuBo.setPath(topMenu.getPath()); + + MenuBo.MetaBo meta = new MetaBo(); + meta.setId(topMenu.getId()); + meta.setTitle(topMenu.getMeta().getTitle()); + meta.setIcon(topMenu.getMeta().getIcon()); + meta.setHideMenu(topMenu.getHidden()); + meta.setIgnoreKeepAlive(topMenu.getMeta().getNoCache()); + meta.setIsCollect(topMenu.getIsCollect()); + + menuBo.setMeta(meta); + + results.add(menuBo); + } + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("验证当前登录人的登录密码") + @PostMapping("/auth/check/password") + public InvokeResult checkPassword( + @NotBlank(message = "登录密码不能为空!") String password) { + return InvokeResultBuilder.success(passwordEncoderWrapper.getEncoder() + .matches(password, SecurityUtil.getCurrentUser().getPassword())); + } + + private List parseChildrenMenu(MenuDto topMenu, List menus) { + List children = menus.stream() + .filter(t -> StringUtil.equals(t.getParentId(), topMenu.getId())).map(t -> { + MenuBo menuBo = new MenuBo(); + menuBo.setName(t.getName()); + menuBo.setChildren(parseChildrenMenu(t, menus)); + + menuBo.setComponent(t.getComponent()); + menuBo.setPath( + StringUtil.startWith(t.getPath(), "/") ? t.getPath().substring(1) : t.getPath()); + MenuBo.MetaBo meta = new MetaBo(); + meta.setId(t.getId()); + meta.setTitle(t.getMeta().getTitle()); + meta.setIcon(t.getMeta().getIcon()); + meta.setHideMenu(t.getHidden()); + meta.setIgnoreKeepAlive(t.getMeta().getNoCache()); + meta.setIsCollect(t.getIsCollect()); + if (RegUtil.isMatch(PatternPool.PATTERN_HTTP_URL, menuBo.getPath())) { + meta.setIsLink(Boolean.TRUE); + } + + // 如果是功能 + if (SysMenuDisplay.FUNCTION.getCode().equals(t.getDisplay())) { + // 普通 + if (SysMenuComponentType.NORMAL.getCode().equals(t.getComponentType())) { + if ("/iframes/index".equalsIgnoreCase(t.getComponent())) { + menuBo.setComponent(null); + meta.setFrameSrc(menuBo.getPath().substring(menuBo.getPath().indexOf("?src=") + 5)); + menuBo.setPath(menuBo.getPath().substring(0, menuBo.getPath().indexOf("?src="))); + } + } else if (SysMenuComponentType.CUSTOM_LIST.getCode().equals(t.getComponentType())) { + // 自定义列表 + menuBo.setComponent("CUSTOMLIST"); + meta.setCustomListId(t.getComponent()); + } else if (SysMenuComponentType.CUSTOM_PAGE.getCode().equals(t.getComponentType())) { + // 自定义页面 + menuBo.setComponent("CUSTOMPAGE"); + meta.setCustomPageId(t.getComponent()); + } + } + + menuBo.setMeta(meta); + + return menuBo; + }).collect(Collectors.toList()); + + return children; + } + + @ApiOperation("收藏菜单") + @ApiImplicitParam(value = "菜单ID", name = "menuId", paramType = "query") + @PostMapping("/menu/collect") + public InvokeResult collectMenu(String menuId) { + + AbstractUserDetails user = getCurrentUser(); + sysMenuService.collect(user.getId(), menuId); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("获取已收藏的菜单") + @GetMapping("/menu/collect") + public InvokeResult> getCollectMenus() { + AbstractUserDetails user = getCurrentUser(); + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + List menus = sysMenuService.getMenuByUserId(user.getId(), user.isAdmin(), moduleIds); + + List collectMenus = menus.stream().filter(t -> t.getIsCollect()).collect(Collectors.toList()); + List results = collectMenus.stream().map(t -> { + CollectMenuBo result = new CollectMenuBo(); + result.setId(t.getId()); + result.setTitle(t.getMeta().getTitle()); + result.setIcon(t.getMeta().getIcon()); + if (StringUtil.isBlank(result.getIcon())) { + // 如果没有图标 那么就往上级找 + String icon = null; + String parentId = t.getParentId(); + while (StringUtil.isNotEmpty(parentId)) { + MenuDto parentMenu = null; + for (MenuDto m : menus) { + if (m.getId().equals(parentId)) { + parentMenu = m; + } + } + + if (parentMenu == null) { + break; + } + + if (StringUtil.isNotBlank(parentMenu.getMeta().getIcon())) { + icon = parentMenu.getMeta().getIcon(); + break; + } + + parentId = parentMenu.getParentId(); + } + result.setIcon(icon); + } + + List pathList = new ArrayList<>(); + pathList.add(t.getPath()); + String parentId = t.getParentId(); + while (StringUtil.isNotEmpty(parentId)) { + MenuDto parentMenu = null; + for (MenuDto m : menus) { + if (m.getId().equals(parentId)) { + parentMenu = m; + } + } + + if (parentMenu == null) { + break; + } + + if (StringUtil.isNotBlank(parentMenu.getPath())) { + pathList.add(parentMenu.getPath()); + } + + parentId = parentMenu.getParentId(); + } + + pathList = CollectionUtil.reverse(pathList); + result.setPath(CollectionUtil.join(pathList, "")); + + return result; + }).collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("取消收藏菜单") + @ApiImplicitParam(value = "菜单ID", name = "menuId", paramType = "query") + @PostMapping("/menu/collect/cancel") + public InvokeResult cancelCollectMenu(String menuId) { + + AbstractUserDetails user = getCurrentUser(); + sysMenuService.cancelCollect(user.getId(), menuId); + + return InvokeResultBuilder.success(); + } + + public LoginDto doLogin(AbstractUserDetails user) { + + if (!user.isAccountNonExpired()) { + throw new UserLoginException("账户已过期,不允许登录!"); + } + + if (!user.isAccountNonLocked()) { + throw new UserLoginException("账户已过期,不允许登录!"); + } + + if (!user.isAccountNonLocked()) { + throw new UserLoginException("账户已锁定,不允许登录!"); + } + + if (!user.isEnabled()) { + throw new UserLoginException("账户已停用,不允许登录!"); + } + + if (user.isNoPermission()) { + throw new UserLoginException("账户未授权,不允许登录!"); + } + // 登录 + StpUtil.login( + (user.getTenantId() == null ? "" : user.getTenantId() + "@") + user.getUsername()); + + StpUtil.getSession().set(SecurityConstants.USER_INFO_KEY, user); + + String token = userTokenResolver.getToken(); + ApplicationUtil.publishEvent(new LoginEvent(this, SecurityUtil.getCurrentUser(), token)); + + LoginDto dto = new LoginDto(token, user.getName(), user.getPermissions()); + + return dto; + } + + private void checkUserLogin(Integer tenantId, String username, String password) { + AbstractUserDetails user = userDetailsService.loadUserByUsername(username); + String lockKey = + (tenantId == null ? "noTenant" : tenantId) + "_" + username + "_" + DateUtil.formatDate( + LocalDate.now()) + "_LOGIN_LOCK"; + if (!passwordEncoderWrapper.getEncoder().matches(password, user.getPassword())) { + long loginErrorNum = redisHandler.incr(lockKey, 1); + redisHandler.expire(lockKey, 86400000L); + int failNum = 5; + if (loginErrorNum < failNum) { + throw new UserLoginException( + "您已经登录失败" + loginErrorNum + "次,您还可以尝试" + (failNum - loginErrorNum) + + "次!"); + } else { + sysUserService.lockById(user.getId()); + + sysUserService.cleanCacheByKey(user.getId()); + + redisHandler.expire(lockKey, 1L); + // 锁定用户 + throw new UserLoginException("用户已锁定,无法登录!"); + } + } else { + redisHandler.expire(lockKey, 1L); + } + } + + public void addAttributesToSession(AbstractUserDetails user) { + Map dataPermissionMap = new HashMap<>(); + SysDataPermissionDataPermissionType[] permissionTypes = SysDataPermissionDataPermissionType.values(); + for (SysDataPermissionDataPermissionType permissionType : permissionTypes) { + List sqlTemplates = new ArrayList<>(); + + List userRoles = sysUserRoleService.getByUserId(user.getId()); + if (CollectionUtil.isNotEmpty(userRoles)) { + for (SysUserRole userRole : userRoles) { + SysDataPermissionData permissionData = sysDataPermissionDataService.getByBizId( + userRole.getRoleId(), + SysDataPermissionDataBizType.ROLE.getCode(), permissionType.getCode()); + if (permissionData != null) { + String sqlTemplate = sysDataPermissionModelDetailService.toSql( + JsonUtil.parseList(permissionData.getPermission(), + SysDataPermissionModelDetailVo.class)); + if (StringUtil.isNotBlank(sqlTemplate)) { + sqlTemplates.add(sqlTemplate); + } + } + } + } + + List userDepts = sysUserDeptService.getByUserId(user.getId()); + if (CollectionUtil.isNotEmpty(userDepts)) { + for (SysUserDept userDept : userDepts) { + SysDataPermissionData permissionData = sysDataPermissionDataService.getByBizId( + userDept.getDeptId(), + SysDataPermissionDataBizType.DEPT.getCode(), permissionType.getCode()); + if (permissionData != null) { + String sqlTemplate = sysDataPermissionModelDetailService.toSql( + JsonUtil.parseList(permissionData.getPermission(), + SysDataPermissionModelDetailVo.class)); + if (StringUtil.isNotBlank(sqlTemplate)) { + sqlTemplates.add(sqlTemplate); + } + } + } + } + + SysDataPermissionData permissionData = sysDataPermissionDataService.getByBizId( + user.getId(), + SysDataPermissionDataBizType.USER.getCode(), permissionType.getCode()); + if (permissionData != null) { + String sqlTemplate = sysDataPermissionModelDetailService.toSql( + JsonUtil.parseList(permissionData.getPermission(), + SysDataPermissionModelDetailVo.class)); + if (StringUtil.isNotBlank(sqlTemplate)) { + sqlTemplates.add(sqlTemplate); + } + } + + if (CollectionUtil.isNotEmpty(sqlTemplates)) { + dataPermissionMap.put(permissionType.getCode().toString(), + "(" + CollectionUtil.join(sqlTemplates, " AND ") + ")"); + } + } + + StpUtil.getSession().set(SecurityConstants.DATA_PERMISSION_SQL_MAP, dataPermissionMap); + + Map dataPermissionVar = new HashMap<>(); + List userDepts = sysUserDeptService.getByUserId(user.getId()); + List curDeptIds = userDepts.stream().map(SysUserDept::getDeptId) + .map(t -> "'" + t + "'").collect( + Collectors.toList()); + dataPermissionVar.put("curDeptIds", + CollectionUtil.isEmpty(curDeptIds) ? IdUtil.getId() : CollectionUtil.join(curDeptIds, ",")); + + StpUtil.getSession().set(SecurityConstants.DATA_PERMISSION_SQL_VAR, dataPermissionVar); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/QrtzController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/QrtzController.java new file mode 100644 index 0000000..9178670 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/QrtzController.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.template.inner.controller; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.bo.qrtz.GetQrtzBo; +import com.lframework.xingyun.template.inner.bo.qrtz.QueryQrtzBo; +import com.lframework.xingyun.template.inner.service.QrtzService; +import com.lframework.xingyun.template.inner.vo.qrtz.CreateQrtzVo; +import com.lframework.xingyun.template.inner.vo.qrtz.QueryQrtzVo; +import com.lframework.xingyun.template.inner.vo.qrtz.UpdateQrtzVo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.template.inner.dto.qrtz.QrtzDto; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "定时器管理") +@RestController +@RequestMapping("/qrtz") +public class QrtzController extends DefaultBaseController { + + @Autowired + private QrtzService qrtzService; + + /** + * 查询列表 + * + * @param vo + * @return + */ + @ApiOperation("查询列表") + @HasPermission({"development:qrtz:manage"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryQrtzVo vo) { + + PageResult pageResult = qrtzService.query(getPageIndex(vo), getPageSize(vo), vo); + List datas = pageResult.getDatas(); + + List results = null; + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryQrtzBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询 + * + * @return + */ + @ApiOperation("查询") + @HasPermission({"development:qrtz:manage"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + QrtzDto data = qrtzService.findById(name, group); + if (data == null) { + throw new DefaultClientException("任务不存在!"); + } + + return InvokeResultBuilder.success(new GetQrtzBo(data)); + } + + /** + * 创建 + * + * @param vo + * @return + */ + @ApiOperation("创建") + @HasPermission({"development:qrtz:manage"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateQrtzVo vo) { + qrtzService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + * + * @param vo + * @return + */ + @ApiOperation("修改") + @HasPermission({"development:qrtz:manage"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateQrtzVo vo) { + qrtzService.update(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 暂停 + * + * @return + */ + @ApiOperation("暂停") + @HasPermission({"development:qrtz:manage"}) + @PutMapping("/pause") + public InvokeResult pause(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.pause(name, group); + + return InvokeResultBuilder.success(); + } + + /** + * 恢复 + * + * @return + */ + @ApiOperation("恢复") + @HasPermission({"development:qrtz:manage"}) + @PutMapping("/resume") + public InvokeResult resume(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.resume(name, group); + + return InvokeResultBuilder.success(); + } + + /** + * 触发 + * + * @return + */ + @ApiOperation("触发") + @HasPermission({"development:qrtz:manage"}) + @PutMapping("/trigger") + public InvokeResult trigger(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.trigger(name, group); + + return InvokeResultBuilder.success(); + } + + /** + * 删除 + * + * @return + */ + @ApiOperation("删除") + @HasPermission({"development:qrtz:manage"}) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "名称不能为空!") String name, + @NotBlank(message = "组不能为空!") String group) { + qrtzService.delete(name, group); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/UserCenterController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/UserCenterController.java new file mode 100644 index 0000000..48bb6f9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/UserCenterController.java @@ -0,0 +1,192 @@ +package com.lframework.xingyun.template.inner.controller; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.bo.usercenter.UserInfoBo; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.vo.QueryOpLogsVo; +import com.lframework.xingyun.template.inner.events.UpdateUserEvent; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.bo.oplog.OpLogInUserCenterBo; +import com.lframework.xingyun.template.inner.dto.UserInfoDto; +import com.lframework.xingyun.template.inner.service.system.SysUserService; +import com.lframework.starter.web.components.security.PasswordEncoderWrapper; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户中心 + * + * @author zmj + */ +@Api(tags = "个人中心") +@Validated +@RestController +@RequestMapping("/center") +public class UserCenterController extends DefaultBaseController { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private OpLogsService opLogsService; + + @Autowired + private PasswordEncoderWrapper encoderWrapper; + + /** + * 获取用户信息 + */ + @ApiOperation(value = "获取用户信息") + @GetMapping("/info") + public InvokeResult getInfo() { + + String userId = getCurrentUser().getId(); + UserInfoDto info = sysUserService.getInfo(userId); + + return InvokeResultBuilder.success(new UserInfoBo(info)); + } + + /** + * 修改密码 + */ + @ApiOperation("修改密码") + @ApiImplicitParams({ + @ApiImplicitParam(value = "旧密码", name = "oldPsw", paramType = "query", required = true), + @ApiImplicitParam(value = "新密码", name = "newPsw", paramType = "query", required = true), + @ApiImplicitParam(value = "确认密码", name = "confirmPsw", paramType = "query", required = true)}) + @OpLog(type = DefaultOpLogType.AUTH, name = "修改密码,原密码:{},新密码:{}", params = {"#oldPsw", "#newPsw"}) + @PatchMapping("/password") + public InvokeResult updatePassword(@NotBlank(message = "旧密码不能为空!") String oldPsw, + @NotBlank(message = "新密码不能为空!") String newPsw, + @NotBlank(message = "确认密码不能为空!") String confirmPsw) { + + AbstractUserDetails user = getCurrentUser(); + if (!encoderWrapper.getEncoder().matches(oldPsw, user.getPassword())) { + throw new InputErrorException("旧密码不正确,请重新输入!"); + } + + if (!StringUtil.equals(newPsw, confirmPsw)) { + throw new InputErrorException("两次密码输入不一致,请检查!"); + } + + if (!RegUtil.isMatch(PatternPool.PATTERN_PASSWORD, newPsw)) { + throw new InputErrorException("密码格式不正确,请检查!"); + } + + sysUserService.updatePassword(user.getId(), newPsw); + + //修改密码后,退出登录状态 + SecurityUtil.logout(); + + return InvokeResultBuilder.success(); + } + + /** + * 修改邮箱 + */ + @ApiOperation("修改邮箱") + @ApiImplicitParams({ + @ApiImplicitParam(value = "新邮箱地址", name = "newEmail", paramType = "query", required = true), + @ApiImplicitParam(value = "确认邮箱地址", name = "confirmEmail", paramType = "query", required = true)}) + @OpLog(type = DefaultOpLogType.AUTH, name = "修改邮箱,新邮箱:{}", params = "#newEmail") + @PatchMapping("/email") + public InvokeResult updateEmail(@NotBlank(message = "新邮箱地址不能为空!") String newEmail, + @NotBlank(message = "确认邮箱地址不能为空!") String confirmEmail) { + + AbstractUserDetails user = getCurrentUser(); + + if (!StringUtil.equals(newEmail, confirmEmail)) { + throw new InputErrorException("两次邮箱地址输入不一致,请检查!"); + } + + if (!RegUtil.isMatch(PatternPool.EMAIL, newEmail)) { + throw new InputErrorException("邮箱地址格式不正确,请检查!"); + } + + sysUserService.updateEmail(user.getId(), newEmail); + + sysUserService.cleanCacheByKey(user.getId()); + + ApplicationUtil.publishEvent(new UpdateUserEvent(this, user.getId())); + + return InvokeResultBuilder.success(); + } + + /** + * 修改联系电话 + */ + @ApiOperation("修改联系电话") + @ApiImplicitParams({ + @ApiImplicitParam(value = "新联系电话", name = "newTelephone", paramType = "query", required = true), + @ApiImplicitParam(value = "确认联系电话", name = "confirmTelephone", paramType = "query", required = true)}) + @OpLog(type = DefaultOpLogType.AUTH, name = "修改联系电话,新联系电话:{}", params = "#newTelephone") + @PatchMapping("/telephone") + public InvokeResult updateTelephone(@NotBlank(message = "新联系电话不能为空!") String newTelephone, + @NotBlank(message = "确认联系电话不能为空!") String confirmTelephone) { + + AbstractUserDetails user = getCurrentUser(); + + if (!StringUtil.equals(newTelephone, confirmTelephone)) { + throw new InputErrorException("两次联系电话输入不一致,请检查!"); + } + + if (!RegUtil.isMatch(PatternPool.PATTERN_CN_TEL, newTelephone)) { + throw new InputErrorException("联系电话格式不正确,请检查!"); + } + + sysUserService.updateTelephone(user.getId(), newTelephone); + + sysUserService.cleanCacheByKey(user.getId()); + + ApplicationUtil.publishEvent(new UpdateUserEvent(this, user.getId())); + + return InvokeResultBuilder.success(); + } + + /** + * 查询操作日志 + */ + @ApiOperation("查询操作日志") + @GetMapping("/oplog") + public InvokeResult> oplog(@Valid QueryOpLogsVo vo) { + + vo.setCreateBy(SecurityUtil.getCurrentUser().getId()); + + PageResult pageResult = opLogsService.query(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(OpLogInUserCenterBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/DefaultSysSelectorController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/DefaultSysSelectorController.java new file mode 100644 index 0000000..b59898a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/DefaultSysSelectorController.java @@ -0,0 +1,414 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.bo.system.dept.SysDeptSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.dic.SysDataDicSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.menu.SysMenuSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.open.SysOpenDomainSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.position.SysPositionSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.role.SysRoleSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.tenant.TenantSelectorBo; +import com.lframework.xingyun.template.inner.bo.system.user.SysUserSelectorBo; +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import com.lframework.xingyun.template.inner.service.system.SysPositionService; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.vo.system.dic.SysDataDicSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import com.lframework.xingyun.template.inner.vo.system.menu.SysMenuSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.position.SysPositionSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.TenantSelectorVo; +import com.lframework.xingyun.template.inner.service.TenantService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicCategoryService; +import com.lframework.xingyun.template.inner.service.system.SysDeptService; +import com.lframework.xingyun.template.inner.service.system.SysOpenDomainService; +import com.lframework.xingyun.template.inner.service.system.SysUserService; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.vo.system.open.SysOpenDomainSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserSelectorVo; +import com.lframework.xingyun.template.inner.bo.system.dic.category.SysDataDicCategorySelectorBo; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.TenantUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据选择器 + * + * @author zmj + */ +@Api(tags = "数据选择器") +@Validated +@RestController +@RequestMapping("/selector") +public class DefaultSysSelectorController extends DefaultBaseController { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysDeptService sysDeptService; + + @Autowired + private SysPositionService sysPositionService; + + @Autowired + private SysRoleService sysRoleService; + + @Autowired + private SysDataDicCategoryService sysDataDicCategoryService; + + @Autowired + private SysDataDicService sysDataDicService; + + @Autowired + private SysOpenDomainService sysOpenDomainService; + + @Autowired + private TenantService tenantService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 系统菜单 + */ + @ApiOperation("系统菜单") + @GetMapping("/menu") + public InvokeResult> menu(@Valid SysMenuSelectorVo vo) { + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId(TenantContextHolder.getTenantId()); + } + + List results = CollectionUtil.emptyList(); + List datas = sysMenuService.selector(vo, moduleIds); + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysMenuSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("部门") + @GetMapping("/dept") + public InvokeResult> dept() { + + List results = CollectionUtil.emptyList(); + List datas = sysDeptService.selector(); + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysDeptSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("角色") + @GetMapping("/role") + public InvokeResult> role(@Valid SysRoleSelectorVo vo) { + + PageResult pageResult = sysRoleService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(SysRoleSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载角色 + */ + @ApiOperation("加载角色") + @PostMapping("/role/load") + public InvokeResult> loadRole( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysRoleService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(SysRoleSelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("租户") + @GetMapping("/tenant") + public InvokeResult> tenant(@Valid TenantSelectorVo vo) { + + PageResult pageResult = tenantService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(TenantSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载租户 + */ + @ApiOperation("加载租户") + @PostMapping("/tenant/load") + public InvokeResult> loadTenant( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(Objects::nonNull) + .map(t -> tenantService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(TenantSelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("用户") + @GetMapping("/user") + public InvokeResult> user(@Valid SysUserSelectorVo vo) { + + PageResult pageResult = sysUserService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysUserSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载用户 + */ + @ApiOperation("加载用户") + @PostMapping("/user/load") + public InvokeResult> loadUser( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysUserService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(SysUserSelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("岗位") + @GetMapping("/position") + public InvokeResult> position(@Valid SysPositionSelectorVo vo) { + + PageResult pageResult = sysPositionService.selector(getPageIndex(vo), + getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysPositionSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载岗位 + */ + @ApiOperation("加载岗位") + @PostMapping("/position/load") + public InvokeResult> loadPosition( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysPositionService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(SysPositionSelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据字典分类") + @GetMapping("/dic/category") + public InvokeResult> dataDicCategory( + @Valid SysDataDicCategorySelectorVo vo) { + + PageResult pageResult = sysDataDicCategoryService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysDataDicCategorySelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据字典分类 + */ + @ApiOperation("加载数据字典分类") + @PostMapping("/dic/category/load") + public InvokeResult> loadDataDicCategory( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysDataDicCategoryService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(SysDataDicCategorySelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("数据字典") + @GetMapping("/dic") + public InvokeResult> dataDic( + @Valid SysDataDicSelectorVo vo) { + + PageResult pageResult = sysDataDicService.selector(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysDataDicSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载数据字典 + */ + @ApiOperation("加载数据字典") + @PostMapping("/dic/load") + public InvokeResult> loadDataDic( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(StringUtil::isNotBlank) + .map(t -> sysDataDicService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream() + .map(SysDataDicSelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 开放域 + */ + @ApiOperation("开放域") + @GetMapping("/openDomain") + public InvokeResult> openDomain( + @Valid SysOpenDomainSelectorVo vo) { + + PageResult pageResult = sysOpenDomainService.selector(vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(SysOpenDomainSelectorBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 加载开放域 + */ + @ApiOperation("加载开放域") + @PostMapping("/openDomain/load") + public InvokeResult> openDomain( + @RequestBody(required = false) List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List datas = ids.stream().filter(Objects::nonNull) + .map(t -> sysOpenDomainService.findById(t)) + .filter(Objects::nonNull).collect(Collectors.toList()); + List results = datas.stream().map(SysOpenDomainSelectorBo::new) + .collect( + Collectors.toList()); + + return InvokeResultBuilder.success(results); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/OpLogController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/OpLogController.java new file mode 100644 index 0000000..f0a194d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/OpLogController.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.template.inner.bo.system.oplog.GetOpLogBo; +import com.lframework.xingyun.template.inner.bo.system.oplog.QueryOpLogBo; +import com.lframework.xingyun.template.core.entity.OpLogs; +import com.lframework.xingyun.template.core.service.OpLogsService; +import com.lframework.xingyun.template.core.vo.QueryOpLogsVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 操作日志 + * + * @author zmj + */ +@Api(tags = "操作日志") +@Validated +@RestController +@RequestMapping("/system/oplog") +public class OpLogController extends DefaultBaseController { + + @Autowired + private OpLogsService opLogsService; + + /** + * 操作日志列表 + */ + @ApiOperation("操作日志列表") + @HasPermission({"system:oplog:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryOpLogsVo vo) { + + PageResult pageResult = opLogsService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryOpLogBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 操作日志详情 + */ + @ApiOperation("操作日志详情") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:oplog:query"}) + @GetMapping + public InvokeResult findById(@NotBlank(message = "ID不能为空") String id) { + + OpLogs data = opLogsService.findById(id); + + if (data == null) { + throw new DefaultClientException("操作日志不存在!"); + } + + GetOpLogBo result = new GetOpLogBo(data); + + return InvokeResultBuilder.success(result); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicCategoryController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicCategoryController.java new file mode 100644 index 0000000..c8e97bf --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicCategoryController.java @@ -0,0 +1,122 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.bo.system.dic.category.QuerySysDataDicCategoryBo; +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.xingyun.template.inner.service.system.SysDataDicCategoryService; +import com.lframework.xingyun.template.inner.vo.system.dic.category.CreateSysDataDicCategoryVo; +import com.lframework.xingyun.template.inner.vo.system.dic.category.UpdateSysDataDicCategoryVo; +import com.lframework.xingyun.template.inner.bo.system.dic.category.GetSysDataDicCategoryBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据字典分类 + * + * @author zmj + */ +@Api(tags = "数据字典分类") +@Validated +@RestController +@RequestMapping("/system/dic/category") +public class SysDataDicCategoryController extends DefaultBaseController { + + @Autowired + private SysDataDicCategoryService sysDataDicCategoryService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"system:dic-category:*"}) + @GetMapping("/query") + public InvokeResult> query() { + List datas = sysDataDicCategoryService.queryList(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysDataDicCategoryBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:dic-category:*"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysDataDicCategory data = sysDataDicCategoryService.findById(id); + if (data == null) { + throw new DefaultClientException("数据字典分类不存在!"); + } + + GetSysDataDicCategoryBo result = new GetSysDataDicCategoryBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增数据字典分类 + */ + @ApiOperation("新增数据字典分类") + @HasPermission({"system:dic-category:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysDataDicCategoryVo vo) { + + sysDataDicCategoryService.create(vo); + + sysDataDicCategoryService.cleanCacheByKey("all"); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据字典分类 + */ + @ApiOperation("修改数据字典分类") + @HasPermission({"system:dic-category:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysDataDicCategoryVo vo) { + + sysDataDicCategoryService.update(vo); + + sysDataDicCategoryService.cleanCacheByKeys(Arrays.asList("all", vo.getId())); + + return InvokeResultBuilder.success(); + } + + @ApiOperation("删除数据字典分类") + @HasPermission({"system:dic-category:delete"}) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + sysDataDicCategoryService.deleteById(id); + + sysDataDicCategoryService.cleanCacheByKeys(Arrays.asList("all", id)); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicController.java new file mode 100644 index 0000000..30b727e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicController.java @@ -0,0 +1,127 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.bo.system.dic.GetSysDataDicBo; +import com.lframework.xingyun.template.inner.bo.system.dic.QuerySysDataDicBo; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.xingyun.template.inner.vo.system.dic.CreateSysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.UpdateSysDataDicVo; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据字典 + * + * @author zmj + */ +@Api(tags = "数据字典") +@Validated +@RestController +@RequestMapping("/system/dic") +public class SysDataDicController extends DefaultBaseController { + + @Autowired + private SysDataDicService sysDataDicService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"system:dic:*"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysDataDicVo vo) { + PageResult pageResult = sysDataDicService.query(getPageIndex(vo), getPageSize(vo), + vo); + List datas = pageResult.getDatas(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysDataDicBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:dic:*"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysDataDic data = sysDataDicService.findById(id); + if (data == null) { + throw new DefaultClientException("数据字典不存在!"); + } + + GetSysDataDicBo result = new GetSysDataDicBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增数据字典 + */ + @ApiOperation("新增数据字典") + @HasPermission({"system:dic:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysDataDicVo vo) { + + sysDataDicService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据字典 + */ + @ApiOperation("修改数据字典") + @HasPermission({"system:dic:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysDataDicVo vo) { + + sysDataDicService.update(vo); + + sysDataDicService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 删除数据字典 + */ + @ApiOperation("删除数据字典") + @HasPermission({"system:dic:delete"}) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + sysDataDicService.deleteById(id); + + sysDataDicService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicItemController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicItemController.java new file mode 100644 index 0000000..b567a50 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataDicItemController.java @@ -0,0 +1,162 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysDataDicItemService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.xingyun.template.inner.vo.system.dic.item.CreateSysDataDicItemVo; +import com.lframework.xingyun.template.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import com.lframework.xingyun.template.inner.vo.system.dic.item.UpdateSysDataDicItemVo; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.bo.system.dic.item.GetSysDataDicItemBo; +import com.lframework.xingyun.template.inner.bo.system.dic.item.QuerySysDataDicItemBo; +import com.lframework.xingyun.template.inner.bo.system.dic.item.SysDataDicItemBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据字典值 + * + * @author zmj + */ +@Api(tags = "数据字典值") +@Validated +@RestController +@RequestMapping("/system/dic/item") +public class SysDataDicItemController extends DefaultBaseController { + + @Autowired + private SysDataDicItemService sysDataDicItemService; + + @Autowired + private SysDataDicService sysDataDicService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"system:dic-item:*"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysDataDicItemVo vo) { + PageResult pageResult = sysDataDicItemService.query(getPageIndex(vo), + getPageSize(vo), vo); + List datas = pageResult.getDatas(); + List results = CollectionUtil.emptyList(); + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysDataDicItemBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:dic-item:*"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysDataDicItem data = sysDataDicItemService.findById(id); + if (data == null) { + throw new DefaultClientException("数据字典值不存在!"); + } + + GetSysDataDicItemBo result = new GetSysDataDicItemBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 根据字典编号查询 + */ + @ApiOperation("根据字典编号查询") + @ApiImplicitParam(value = "字典编号", name = "code", paramType = "query", required = true) + @GetMapping("/bydic") + public InvokeResult> getByDicCode( + @NotBlank(message = "字典编号不能为空!") String code) { + List datas = sysDataDicItemService.findByDicCode(code); + + List results = datas.stream().map(SysDataDicItemBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 新增数据字典值 + */ + @ApiOperation("新增数据字典值") + @HasPermission({"system:dic-item:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysDataDicItemVo vo) { + + sysDataDicItemService.create(vo); + + SysDataDic dic = sysDataDicService.findById(vo.getDicId()); + sysDataDicItemService.cleanCacheByKey(dic.getCode()); + + return InvokeResultBuilder.success(); + } + + /** + * 修改数据字典值 + */ + @ApiOperation("修改数据字典值") + @HasPermission({"system:dic-item:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysDataDicItemVo vo) { + + SysDataDicItem item = sysDataDicItemService.findById(vo.getId()); + + sysDataDicItemService.update(vo); + + SysDataDic dic = sysDataDicService.findById(item.getDicId()); + sysDataDicItemService.cleanCacheByKey(dic.getCode()); + + sysDataDicItemService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 删除数据字典值 + */ + @ApiOperation("删除数据字典值") + @HasPermission({"system:dic-item:delete"}) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + SysDataDicItem item = sysDataDicItemService.findById(id); + + sysDataDicItemService.deleteById(id); + + SysDataDic dic = sysDataDicService.findById(item.getDicId()); + sysDataDicItemService.cleanCacheByKey(dic.getCode()); + + sysDataDicItemService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionDataController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionDataController.java new file mode 100644 index 0000000..69ffc0d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionDataController.java @@ -0,0 +1,94 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.core.vo.permission.CreateSysDataPermissionDataVo; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.core.entity.SysDataPermissionData; +import com.lframework.xingyun.template.core.enums.SysDataPermissionDataBizType; +import com.lframework.xingyun.template.inner.service.system.SysDataPermissionDataService; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据权限数据 + * + * @author zmj + */ +@Api(tags = "数据权限数据") +@Validated +@RestController +@RequestMapping("/system/data/permission/data") +public class SysDataPermissionDataController extends DefaultBaseController { + + @Autowired + private SysDataPermissionDataService sysDataPermissionDataService; + + @Autowired + private SysRoleService sysRoleService; + + @ApiOperation("保存") + @PostMapping + public InvokeResult save(@Valid @RequestBody List data) { + if (CollectionUtil.isEmpty(data)) { + return InvokeResultBuilder.success(); + } + + for (CreateSysDataPermissionDataVo vo : data) { + if (EnumUtil.getByCode(SysDataPermissionDataBizType.class, vo.getBizType()) + == SysDataPermissionDataBizType.ROLE) { + List roles = vo.getBizIds().stream().map(t -> sysRoleService.findById(t)) + .filter( + Objects::nonNull) + .filter(t -> SecurityConstants.PERMISSION_ADMIN_NAME.equals(t.getPermission())) + .collect(Collectors.toList()); + + if (CollectionUtil.isNotEmpty(roles)) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】为内置权限,不允许设置数据权限!"); + } + } + } + + List records = data.stream() + .flatMap(t -> t.getBizIds().stream() + .map(bizId -> { + SysDataPermissionData record = sysDataPermissionDataService.getByBizId(bizId, + t.getBizType(), + t.getPermissionType()); + if (record == null) { + record = new SysDataPermissionData(); + record.setId(IdUtil.getId()); + record.setBizId(bizId); + record.setBizType( + EnumUtil.getByCode(SysDataPermissionDataBizType.class, t.getBizType())); + record.setPermissionType(t.getPermissionType()); + } + record.setPermission(t.getPermission()); + return record; + })) + .collect(Collectors.toList()); + + sysDataPermissionDataService.saveOrUpdateAllColumnBatch(records); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionModelDetailController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionModelDetailController.java new file mode 100644 index 0000000..471d68b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDataPermissionModelDetailController.java @@ -0,0 +1,153 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.JsonUtil; +import com.lframework.xingyun.template.inner.bo.system.permission.QuerySysDataPermissionModelDetailBo; +import com.lframework.xingyun.template.inner.bo.system.permission.SysDataPermissionModelDetailBo; +import com.lframework.xingyun.template.core.entity.SysDataPermissionData; +import com.lframework.xingyun.template.core.entity.SysDataPermissionModelDetail; +import com.lframework.xingyun.template.core.enums.SysDataPermissionDataBizType; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailCalcType; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailConditionType; +import com.lframework.xingyun.template.core.enums.SysDataPermissionModelDetailNodeType; +import com.lframework.xingyun.template.core.service.SysDataPermissionModelDetailService; +import com.lframework.xingyun.template.core.vo.permission.SysDataPermissionModelDetailVo; +import com.lframework.xingyun.template.inner.service.system.SysDataPermissionDataService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据权限Model明细 + * + * @author zmj + */ +@Api(tags = "数据权限Model明细") +@Validated +@RestController +@RequestMapping("/system/data/permission/model/detail") +public class SysDataPermissionModelDetailController extends DefaultBaseController { + + @Autowired + private SysDataPermissionModelDetailService sysDataPermissionModelDetailService; + + @Autowired + private SysDataPermissionDataService sysDataPermissionDataService; + + @ApiOperation("根据模型ID查询") + @ApiImplicitParam(value = "模型ID", name = "modelId", paramType = "query", required = true) + @GetMapping + public InvokeResult> getByModelId( + @NotNull(message = "模型ID不能为空!") Integer modelId) { + + Wrapper queryWrapper = Wrappers.lambdaQuery( + SysDataPermissionModelDetail.class).eq(SysDataPermissionModelDetail::getModelId, modelId); + List datas = sysDataPermissionModelDetailService.list( + queryWrapper); + List results = datas.stream() + .map(SysDataPermissionModelDetailBo::new).collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + @ApiOperation("预览SQL") + @PostMapping("/preview") + public InvokeResult preview( + @Valid @RequestBody List models) { + + String sql = sysDataPermissionModelDetailService.toSql(models); + + return InvokeResultBuilder.success(sql); + } + + @ApiOperation("根据业务ID查询") + @ApiImplicitParam(value = "模型ID", name = "modelId", paramType = "query", required = true) + @GetMapping("/query") + public InvokeResult> queryByBizId( + @NotBlank(message = "业务ID不能为空!") String bizId, + @NotNull(message = "业务类型不能为空!") @IsEnum(message = "业务类型格式错误!", enumClass = SysDataPermissionDataBizType.class) Integer bizType, + @NotNull(message = " 权限类型不能为空!") Integer permissionType) { + + SysDataPermissionData data = sysDataPermissionDataService.getByBizId(bizId, bizType, + permissionType); + if (data == null) { + return InvokeResultBuilder.success(Collections.emptyList()); + } + + List voList = JsonUtil.parseList(data.getPermission(), + SysDataPermissionModelDetailVo.class); + if (CollectionUtil.isEmpty(voList)) { + return InvokeResultBuilder.success(Collections.emptyList()); + } + + List results = this.buildChildren(voList); + + return InvokeResultBuilder.success(results); + } + + private List buildChildren( + List children) { + if (CollectionUtil.isEmpty(children)) { + return Collections.emptyList(); + } + + List results = new ArrayList<>(children.size()); + for (SysDataPermissionModelDetailVo vo : children) { + SysDataPermissionModelDetail modelDetail = sysDataPermissionModelDetailService.getById( + vo.getDetailId()); + QuerySysDataPermissionModelDetailBo result = new QuerySysDataPermissionModelDetailBo(); + result.setId(vo.getId()); + result.setDetailId(vo.getDetailId()); + result.setCalcType(vo.getCalcType()); + result.setNodeType(vo.getNodeType()); + result.setValue(vo.getValue()); + result.setValues(vo.getValues()); + result.setConditionType(vo.getConditionType()); + SysDataPermissionModelDetailNodeType nodeType = EnumUtil.getByCode( + SysDataPermissionModelDetailNodeType.class, vo.getNodeType()); + if (nodeType == SysDataPermissionModelDetailNodeType.CALC) { + SysDataPermissionModelDetailCalcType calcType = EnumUtil.getByCode( + SysDataPermissionModelDetailCalcType.class, vo.getCalcType()); + result.setName(calcType.getDesc()); + result.setChildren(this.buildChildren(vo.getChildren())); + } else { + result.setName(modelDetail.getName()); + result.setModelId(modelDetail.getModelId()); + result.setConditionTypes( + Arrays.stream(modelDetail.getConditionType().split(StringPool.STR_SPLIT)) + .map(t -> EnumUtil.getByCode( + SysDataPermissionModelDetailConditionType.class, t).getCode()) + .toArray(Integer[]::new)); + result.setInputType(modelDetail.getInputType().getCode()); + result.setEnumName(modelDetail.getEnumName()); + } + + results.add(result); + } + + return results; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDeptController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDeptController.java new file mode 100644 index 0000000..153cc32 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysDeptController.java @@ -0,0 +1,179 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.xingyun.template.inner.enums.system.SysDeptNodeType; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.inner.service.system.SysDeptService; +import com.lframework.xingyun.template.inner.vo.system.dept.CreateSysDeptVo; +import com.lframework.xingyun.template.inner.vo.system.dept.UpdateSysDeptVo; +import com.lframework.xingyun.template.inner.bo.system.dept.GetSysDeptBo; +import com.lframework.xingyun.template.inner.bo.system.dept.SysDeptTreeBo; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 部门管理 + * + * @author zmj + */ +@Api(tags = "部门管理") +@Validated +@RestController +@RequestMapping("/system/dept") +public class SysDeptController extends DefaultBaseController { + + @Autowired + private SysDeptService sysDeptService; + + @Autowired + private RecursionMappingService recursionMappingService; + + /** + * 部门树形菜单数据 + */ + @ApiOperation("部门树形菜单数据") + @HasPermission({"system:dept:query", "system:dept:add", "system:dept:modify"}) + @GetMapping("/trees") + public InvokeResult> trees() { + + List datas = sysDeptService.selector(); + if (CollectionUtil.isEmpty(datas)) { + return InvokeResultBuilder.success(CollectionUtil.emptyList()); + } + + List results = datas.stream().map(SysDeptTreeBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(results); + } + + /** + * 查询部门 + */ + @ApiOperation("部门详情") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:dept:query", "system:dept:add", "system:dept:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysDept data = sysDeptService.findById(id); + if (data == null) { + throw new DefaultClientException("部门不存在!"); + } + + GetSysDeptBo result = new GetSysDeptBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用部门 + */ + @ApiOperation("批量停用部门") + @HasPermission({"system:dept:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "部门ID", required = true) @NotEmpty(message = "请选择需要停用的部门!") @RequestBody List ids) { + + sysDeptService.batchUnable(ids); + + List batchIds = new ArrayList<>(ids); + + for (String id : ids) { + List tmp = recursionMappingService.getNodeChildIds(id, + ApplicationUtil.getBean(SysDeptNodeType.class)); + batchIds.addAll(tmp); + } + sysDeptService.cleanCacheByKeys(batchIds); + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用部门 + */ + @ApiOperation("批量启用部门") + @HasPermission({"system:dept:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "部门ID", required = true) @NotEmpty(message = "请选择需要启用的部门!") @RequestBody List ids) { + + sysDeptService.batchEnable(ids); + + List batchIds = new ArrayList<>(ids); + + for (String id : ids) { + List tmp = recursionMappingService.getNodeParentIds(id, + ApplicationUtil.getBean(SysDeptNodeType.class)); + batchIds.addAll(tmp); + } + sysDeptService.cleanCacheByKeys(batchIds); + + return InvokeResultBuilder.success(); + } + + /** + * 新增部门 + */ + @ApiOperation("新增部门") + @HasPermission({"system:dept:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysDeptVo vo) { + + sysDeptService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改部门 + */ + @ApiOperation("修改部门") + @HasPermission({"system:dept:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysDeptVo vo) { + + sysDeptService.update(vo); + + List batchIds = new ArrayList<>(); + batchIds.add(vo.getId()); + + if (vo.getAvailable()) { + List ids = recursionMappingService.getNodeParentIds(vo.getId(), + ApplicationUtil.getBean(SysDeptNodeType.class)); + batchIds.addAll(ids); + } else { + List ids = recursionMappingService.getNodeChildIds(vo.getId(), + ApplicationUtil.getBean(SysDeptNodeType.class)); + batchIds.addAll(ids); + } + + sysDeptService.cleanCacheByKeys(batchIds); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysMenuController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysMenuController.java new file mode 100644 index 0000000..488be59 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysMenuController.java @@ -0,0 +1,245 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.InputErrorException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.xingyun.template.inner.enums.system.SysMenuDisplay; +import com.lframework.xingyun.template.inner.bo.system.menu.GetSysMenuBo; +import com.lframework.xingyun.template.inner.bo.system.menu.QuerySysMenuBo; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import com.lframework.xingyun.template.inner.vo.system.menu.CreateSysMenuVo; +import com.lframework.xingyun.template.inner.vo.system.menu.UpdateSysMenuVo; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.utils.TenantUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 系统菜单管理 + * + * @author zmj + */ +@Api(tags = "系统菜单管理") +@Validated +@RestController +@RequestMapping("/system/menu") +public class SysMenuController extends DefaultBaseController { + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 系统菜单列表 + */ + @ApiOperation("系统菜单列表") + @HasPermission({"system:menu:query", "system:menu:add"}) + @GetMapping("/query") + public InvokeResult> query() { + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId(TenantContextHolder.getTenantId()); + } + + List results = CollectionUtil.emptyList(); + List datas = sysMenuService.queryList(moduleIds); + if (CollectionUtil.isNotEmpty(datas)) { + results = datas.stream().map(QuerySysMenuBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 新增系统菜单 + */ + @ApiOperation("新增系统菜单") + @HasPermission({"system:menu:add"}) + @PostMapping + public InvokeResult add(@Valid CreateSysMenuVo vo) { + + this.validVo(vo); + + sysMenuService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 查看系统菜单 + */ + @ApiOperation("查看系统菜单") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:menu:query", "system:menu:add", "system:menu:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysMenu data = sysMenuService.findById(id); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("菜单不存在!"); + } + + return InvokeResultBuilder.success(new GetSysMenuBo(data)); + } + + /** + * 修改系统菜单 + */ + @ApiOperation("修改系统菜单") + @HasPermission({"system:menu:modify"}) + @PutMapping + public InvokeResult modify(@Valid UpdateSysMenuVo vo) { + + this.validVo(vo); + + sysMenuService.update(vo); + + sysMenuService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:menu:delete"}) + @DeleteMapping + public InvokeResult delete(@NotBlank(message = "ID不能为空!") String id) { + + sysMenuService.deleteById(id); + + sysMenuService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用 + */ + @ApiOperation("批量启用") + @HasPermission({"system:menu:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "菜单ID", required = true) @NotEmpty(message = "请选择需要启用的菜单!") @RequestBody List ids) { + + sysMenuService.batchEnable(ids, SecurityUtil.getCurrentUser().getId()); + + for (String id : ids) { + sysMenuService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量停用 + */ + @ApiOperation("批量停用") + @HasPermission({"system:menu:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "菜单ID", required = true) @NotEmpty(message = "请选择需要停用的菜单!") @RequestBody List ids) { + + sysMenuService.batchUnable(ids, SecurityUtil.getCurrentUser().getId()); + + for (String id : ids) { + sysMenuService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + private void validVo(CreateSysMenuVo vo) { + + SysMenuDisplay sysMenuDisplay = EnumUtil.getByCode(SysMenuDisplay.class, vo.getDisplay()); + + if (sysMenuDisplay == SysMenuDisplay.CATALOG || sysMenuDisplay == SysMenuDisplay.FUNCTION) { + if (StringUtil.isBlank(vo.getName())) { + throw new InputErrorException("请输入路由名称!"); + } + + if (StringUtil.isBlank(vo.getPath())) { + throw new InputErrorException("请输入路由路径!"); + } + + if (ObjectUtil.isNull(vo.getHidden())) { + throw new InputErrorException("请选择是否隐藏!"); + } + + if (sysMenuDisplay == SysMenuDisplay.FUNCTION) { + if (vo.getComponentType() == null) { + throw new InputErrorException("请选择组件类型!"); + } + if (StringUtil.isBlank(vo.getComponent())) { + throw new InputErrorException("请输入组件!"); + } + if (ObjectUtil.isNull(vo.getNoCache())) { + throw new InputErrorException("请选择是否不缓存!"); + } + + if (!StringUtil.isBlank(vo.getParentId())) { + SysMenu parentMenu = sysMenuService.findById(vo.getParentId()); + + if (parentMenu.getDisplay() != SysMenuDisplay.CATALOG) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.FUNCTION.getDesc() + "”时,父级菜单类型必须是“" + + SysMenuDisplay.CATALOG.getDesc() + "”!"); + } + } + } + } else if (sysMenuDisplay == SysMenuDisplay.PERMISSION) { + if (StringUtil.isBlank(vo.getParentId())) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.PERMISSION.getDesc() + "”时,父级菜单不能为空!"); + } + + SysMenu parentMenu = sysMenuService.findById(vo.getParentId()); + if (ObjectUtil.isNull(parentMenu)) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.PERMISSION.getDesc() + "”时,父级菜单不能为空!"); + } + + if (parentMenu.getDisplay() != SysMenuDisplay.FUNCTION) { + throw new InputErrorException( + "当菜单类型是“" + SysMenuDisplay.PERMISSION.getDesc() + "”时,父级菜单类型必须是“" + + SysMenuDisplay.FUNCTION.getDesc() + "”!"); + } + if (StringUtil.isBlank(vo.getPermission())) { + throw new InputErrorException("请输入权限!"); + } + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysModuleController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysModuleController.java new file mode 100644 index 0000000..9ebd5a5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysModuleController.java @@ -0,0 +1,101 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.xingyun.template.inner.bo.system.module.QuerySysModuleBo; +import com.lframework.xingyun.template.inner.entity.SysModule; +import com.lframework.xingyun.template.inner.entity.SysModuleTenant; +import com.lframework.xingyun.template.inner.service.SysModuleService; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.vo.system.module.SysModuleTenantVo; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.TenantUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 系统模块管理 + * + * @author zmj + */ +@Api(tags = "系统模块管理") +@Validated +@RestController +@RequestMapping("/system/module") +public class SysModuleController extends DefaultBaseController { + + @Autowired + private SysModuleService sysModuleService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission(value = {"system:tenant:module"}) + @GetMapping("/query") + public InvokeResult> query(@NotNull(message = "租户ID不能为空!") Integer tenantId) { + + if (!TenantUtil.enableTenant()) { + return InvokeResultBuilder.success(Collections.emptyList()); + } + + // 先查询所有模块 + List sysModules = sysModuleService.list(); + List results = sysModules.stream().map(QuerySysModuleBo::new) + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(results)) { + return InvokeResultBuilder.success(results); + } + + List sysModuleTenants = sysModuleTenantService.getByTenantId(tenantId); + + for (QuerySysModuleBo result : results) { + SysModuleTenant sysModuleTenant = sysModuleTenants.stream() + .filter(t -> ObjectUtil.equal(t.getModuleId(), result.getId())).findFirst().orElse(null); + result.setEnabled(sysModuleTenant != null); + if (sysModuleTenant == null) { + continue; + } + result.setExpireTime(sysModuleTenant.getExpireTime()); + } + + return InvokeResultBuilder.success(results); + } + + /** + * 模块授权 + */ + @ApiOperation("模块授权") + @HasPermission(value = {"system:tenant:module"}) + @PostMapping("/setting") + public InvokeResult setting( + @RequestBody(required = false) @Valid SysModuleTenantVo vo) { + + if (!TenantUtil.enableTenant()) { + return InvokeResultBuilder.success(); + } + sysModuleTenantService.setting(vo); + + sysModuleTenantService.cleanCacheByKey(vo.getTenantId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysNoticeController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysNoticeController.java new file mode 100644 index 0000000..56c1f9c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysNoticeController.java @@ -0,0 +1,175 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.starter.web.common.threads.DefaultRunnable; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.template.inner.bo.system.notice.GetSysNoticeBo; +import com.lframework.xingyun.template.inner.bo.system.notice.QueryMySysNoticeBo; +import com.lframework.xingyun.template.inner.bo.system.notice.QuerySysNoticeBo; +import com.lframework.xingyun.template.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.xingyun.template.inner.dto.system.notice.SysNoticeDto; +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.xingyun.template.inner.vo.system.notice.CreateSysNoticeVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeVo; +import com.lframework.xingyun.template.inner.vo.system.notice.UpdateSysNoticeVo; +import com.lframework.xingyun.template.inner.service.system.SysNoticeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 系统通知 Controller + * + * @author zmj + */ +@Api(tags = "系统通知") +@Validated +@RestController +@RequestMapping("/system/notice") +public class SysNoticeController extends DefaultBaseController { + + @Autowired + private SysNoticeService sysNoticeService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"system:notice:publish"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysNoticeVo vo) { + + PageResult pageResult = sysNoticeService.query(getPageIndex(vo), getPageSize(vo), + vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysNoticeBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询我的通知 + */ + @ApiOperation("查询我的通知") + @GetMapping("/query/my") + public InvokeResult> queryMyNotice( + @Valid QuerySysNoticeByUserVo vo) { + + vo.setUserId(SecurityUtil.getCurrentUser().getId()); + + PageResult pageResult = sysNoticeService.queryByUser(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QueryMySysNoticeBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询内容 + */ + @ApiOperation("根据ID查询内容") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @GetMapping("/content") + public InvokeResult getContent(@NotBlank(message = "id不能为空!") String id) { + + SysNoticeDto data = sysNoticeService.getContent(id); + if (data == null) { + throw new DefaultClientException("系统通知不存在!"); + } + + String currentUserId = SecurityUtil.getCurrentUser().getId(); + ThreadUtil.execAsync(new DefaultRunnable(() -> { + sysNoticeService.setReaded(id, currentUserId); + + sysNoticeService.noticeForWs(currentUserId); + })); + + return InvokeResultBuilder.success(data); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @HasPermission({"system:notice:query"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "id不能为空!") String id) { + + SysNotice data = sysNoticeService.findById(id); + if (data == null) { + throw new DefaultClientException("系统通知不存在!"); + } + + GetSysNoticeBo result = new GetSysNoticeBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"system:notice:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysNoticeVo vo) { + + sysNoticeService.create(vo); + + if (vo.getPublished()) { + sysNoticeService.noticeForWs(); + } + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"system:notice:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysNoticeVo vo) { + + sysNoticeService.update(vo); + + sysNoticeService.cleanCacheByKey(vo.getId()); + + if (vo.getPublished()) { + sysNoticeService.noticeForWs(); + } + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysOpenDomainController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysOpenDomainController.java new file mode 100644 index 0000000..ebda9e4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysOpenDomainController.java @@ -0,0 +1,129 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.bo.system.open.GetSysOpenDomainBo; +import com.lframework.xingyun.template.inner.bo.system.open.QuerySysOpenDomainBo; +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysOpenDomainService; +import com.lframework.xingyun.template.inner.vo.system.open.QuerySysOpenDomainVo; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.vo.system.open.CreateSysOpenDomainVo; +import com.lframework.xingyun.template.inner.vo.system.open.UpdateSysOpenDomainSecretVo; +import com.lframework.xingyun.template.inner.vo.system.open.UpdateSysOpenDomainVo; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 开放域 + * + * @author zmj + */ +@Api(tags = "开放域") +@Validated +@RestController +@RequestMapping("/system/open/domain") +public class SysOpenDomainController extends DefaultBaseController { + + @Autowired + private SysOpenDomainService sysOpenDomainService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"system:open-domain:config"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysOpenDomainVo vo) { + + PageResult pageResult = sysOpenDomainService.query(vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysOpenDomainBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 详情 + */ + @ApiOperation("详情") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:open-domain:config"}) + @GetMapping + public InvokeResult get(@NotNull(message = "ID不能为空!") Integer id) { + + SysOpenDomain data = sysOpenDomainService.findById(id); + if (data == null) { + throw new DefaultClientException("开放域不存在!"); + } + + GetSysOpenDomainBo result = new GetSysOpenDomainBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"system:open-domain:config"}) + @PostMapping + public InvokeResult create(@Valid CreateSysOpenDomainVo vo) { + + sysOpenDomainService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"system:open-domain:config"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysOpenDomainVo vo) { + + sysOpenDomainService.update(vo); + + sysOpenDomainService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 修改Api密钥 + */ + @ApiOperation("修改Api密钥") + @HasPermission({"system:open-domain:config"}) + @PutMapping("/secret") + public InvokeResult updateSecret(@Valid UpdateSysOpenDomainSecretVo vo) { + + sysOpenDomainService.updateApiSecret(vo); + + sysOpenDomainService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysParameterController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysParameterController.java new file mode 100644 index 0000000..cb03f96 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysParameterController.java @@ -0,0 +1,138 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.entity.SysParameter; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysParameterService; +import com.lframework.xingyun.template.inner.vo.system.parameter.CreateSysParameterVo; +import com.lframework.xingyun.template.inner.vo.system.parameter.QuerySysParameterVo; +import com.lframework.xingyun.template.inner.vo.system.parameter.UpdateSysParameterVo; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.bo.system.parameter.GetSysParameterBo; +import com.lframework.xingyun.template.inner.bo.system.parameter.QuerySysParameterBo; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 系统参数 Controller + * + * @author zmj + */ +@Api(tags = "系统参数") +@Validated +@RestController +@RequestMapping("/system/parameter") +public class SysParameterController extends DefaultBaseController { + + @Autowired + private SysParameterService sysParameterService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"system:parameter:query"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysParameterVo vo) { + + PageResult pageResult = sysParameterService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysParameterBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @HasPermission({"system:parameter:query"}) + @GetMapping + public InvokeResult get(@NotNull(message = "id不能为空!") Long id) { + + SysParameter data = sysParameterService.getById(id); + if (data == null) { + throw new DefaultClientException("系统参数不存在!"); + } + + GetSysParameterBo result = new GetSysParameterBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"system:parameter:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysParameterVo vo) { + + sysParameterService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"system:parameter:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysParameterVo vo) { + + sysParameterService.update(vo); + + sysParameterService.cleanCacheByKey(vo.getId()); + + SysParameter data = sysParameterService.findById(vo.getId()); + sysParameterService.cleanCacheByKey(data.getPmKey()); + + return InvokeResultBuilder.success(); + } + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true) + @HasPermission({"system:parameter:delete"}) + @DeleteMapping + public InvokeResult deleteById(@NotNull(message = "id不能为空!") Long id) { + + SysParameter data = sysParameterService.findById(id); + + sysParameterService.deleteById(id); + + sysParameterService.cleanCacheByKey(id); + + sysParameterService.cleanCacheByKey(data.getPmKey()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysPositionController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysPositionController.java new file mode 100644 index 0000000..f0a97c2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysPositionController.java @@ -0,0 +1,154 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysPositionService; +import com.lframework.xingyun.template.inner.vo.system.position.CreateSysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.QuerySysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.UpdateSysPositionVo; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.bo.system.position.GetSysPositionBo; +import com.lframework.xingyun.template.inner.bo.system.position.QuerySysPositionBo; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 岗位管理 + * + * @author zmj + */ +@Api(tags = "岗位管理") +@Validated +@RestController +@RequestMapping("/system/position") +public class SysPositionController extends DefaultBaseController { + + @Autowired + private SysPositionService sysPositionService; + + /** + * 岗位列表 + */ + @ApiOperation("岗位列表") + @HasPermission({"system:position:query","system:position:add","system:position:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysPositionVo vo) { + + PageResult pageResult = sysPositionService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysPositionBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询岗位 + */ + @ApiOperation("查询岗位") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:position:query","system:position:add","system:position:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysPosition data = sysPositionService.findById(id); + if (data == null) { + throw new DefaultClientException("岗位不存在!"); + } + + GetSysPositionBo result = new GetSysPositionBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用岗位 + */ + @ApiOperation("批量停用岗位") + @HasPermission({"system:position:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "岗位ID", required = true) @NotEmpty(message = "请选择需要停用的岗位!") @RequestBody List ids) { + + sysPositionService.batchUnable(ids); + + for (String id : ids) { + sysPositionService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用岗位 + */ + @ApiOperation("批量启用岗位") + @HasPermission({"system:position:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "岗位ID", required = true) @NotEmpty(message = "请选择需要启用的岗位!") @RequestBody List ids) { + + sysPositionService.batchEnable(ids); + + for (String id : ids) { + sysPositionService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增岗位 + */ + @ApiOperation("新增岗位") + @HasPermission({"system:position:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysPositionVo vo) { + + sysPositionService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改岗位 + */ + @ApiOperation("修改岗位") + @HasPermission({"system:position:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysPositionVo vo) { + + sysPositionService.update(vo); + + sysPositionService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleController.java new file mode 100644 index 0000000..a98384e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleController.java @@ -0,0 +1,154 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.bo.system.role.GetSysRoleBo; +import com.lframework.xingyun.template.inner.bo.system.role.QuerySysRoleBo; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.vo.system.role.CreateSysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.UpdateSysRoleVo; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 角色管理 + * + * @author zmj + */ +@Api(tags = "角色管理") +@Validated +@RestController +@RequestMapping("/system/role") +public class SysRoleController extends DefaultBaseController { + + @Autowired + private SysRoleService sysRoleService; + + /** + * 角色列表 + */ + @ApiOperation("角色列表") + @HasPermission({"system:role:query","system:role:add","system:role:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysRoleVo vo) { + + PageResult pageResult = sysRoleService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysRoleBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询角色 + */ + @ApiOperation("查询角色") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:role:query","system:role:add","system:role:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysRole data = sysRoleService.findById(id); + if (data == null) { + throw new DefaultClientException("角色不存在!"); + } + + GetSysRoleBo result = new GetSysRoleBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用角色 + */ + @ApiOperation("批量停用角色") + @HasPermission({"system:role:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "角色ID", required = true) @NotEmpty(message = "请选择需要停用的角色!") @RequestBody List ids) { + + sysRoleService.batchUnable(ids); + + for (String id : ids) { + sysRoleService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用角色 + */ + @ApiOperation("批量启用角色") + @HasPermission({"system:role:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "角色ID", required = true) @NotEmpty(message = "请选择需要启用的角色!") @RequestBody List ids) { + + sysRoleService.batchEnable(ids); + + for (String id : ids) { + sysRoleService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增角色 + */ + @ApiOperation("新增角色") + @HasPermission({"system:role:add"}) + @PostMapping + public InvokeResult create(@Valid CreateSysRoleVo vo) { + + sysRoleService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改角色 + */ + @ApiOperation("修改角色") + @HasPermission({"system:role:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateSysRoleVo vo) { + + sysRoleService.update(vo); + + sysRoleService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleMenuController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleMenuController.java new file mode 100644 index 0000000..7babd7a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysRoleMenuController.java @@ -0,0 +1,98 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.bo.system.role.QueryRoleMenuBo; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import com.lframework.xingyun.template.inner.service.system.SysRoleMenuService; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleMenuSettingVo; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.starter.web.utils.TenantUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 角色授权 + * + * @author zmj + */ +@Api(tags = "角色授权") +@Validated +@RestController +@RequestMapping("/system/role/menu") +public class SysRoleMenuController extends DefaultBaseController { + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysRoleMenuService sysRoleMenuService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + /** + * 查询角色菜单列表 + */ + @ApiOperation("查询角色菜单列表") + @ApiImplicitParam(value = "角色ID", name = "roleId", paramType = "query") + @HasPermission({"system:role:permission"}) + @GetMapping("/menus") + public InvokeResult> menus(String roleId) { + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId(TenantContextHolder.getTenantId()); + } + + List results = CollectionUtil.emptyList(); + //查询所有菜单 + List allMenu = sysMenuService.queryList(moduleIds); + if (!CollectionUtil.isEmpty(allMenu)) { + results = allMenu.stream().map(QueryRoleMenuBo::new).collect(Collectors.toList()); + + if (!StringUtil.isBlank(roleId)) { + List menus = sysMenuService.getByRoleId(roleId, moduleIds); + if (!CollectionUtil.isEmpty(menus)) { + //当角色的菜单存在时,设置已选择属性 + for (QueryRoleMenuBo result : results) { + result.setSelected( + menus.stream().anyMatch(t -> StringUtil.equals(t.getId(), result.getId()))); + } + } + } + } + + return InvokeResultBuilder.success(results); + } + + /** + * 授权角色菜单 + */ + @ApiOperation("授权角色菜单") + @HasPermission({"system:role:permission"}) + @PostMapping("/setting") + public InvokeResult setting(@Valid @RequestBody SysRoleMenuSettingVo vo) { + + sysRoleMenuService.setting(vo); + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserController.java new file mode 100644 index 0000000..792112c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserController.java @@ -0,0 +1,170 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import com.lframework.xingyun.template.inner.bo.system.user.GetSysUserBo; +import com.lframework.xingyun.template.inner.bo.system.user.QuerySysUserBo; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.inner.service.system.SysUserService; +import com.lframework.xingyun.template.inner.vo.system.user.CreateSysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.QuerySysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.UpdateSysUserVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户管理 + * + * @author zmj + */ +@Api(tags = "用户管理") +@Validated +@RestController +@RequestMapping("/system/user") +public class SysUserController extends DefaultBaseController { + + @Autowired + private SysUserService sysUserService; + + /** + * 用户列表 + */ + @ApiOperation("用户列表") + @HasPermission({"system:user:query", "system:user:add", "system:user:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QuerySysUserVo vo) { + + PageResult pageResult = sysUserService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(QuerySysUserBo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询用户 + */ + @ApiOperation("查询用户") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:user:query", "system:user:add", "system:user:modify"}) + @GetMapping + public InvokeResult get(@NotBlank(message = "ID不能为空!") String id) { + + SysUser data = sysUserService.findById(id); + if (data == null) { + throw new DefaultClientException("用户不存在!"); + } + + GetSysUserBo result = new GetSysUserBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 批量停用用户 + */ + @ApiOperation("批量停用用户") + @HasPermission({"system:user:modify"}) + @PatchMapping("/unable/batch") + public InvokeResult batchUnable( + @ApiParam(value = "用户ID", required = true) @NotEmpty(message = "请选择需要停用的用户!") @RequestBody List ids) { + + sysUserService.batchUnable(ids); + + for (String id : ids) { + sysUserService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 批量启用用户 + */ + @ApiOperation("批量启用用户") + @HasPermission({"system:user:modify"}) + @PatchMapping("/enable/batch") + public InvokeResult batchEnable( + @ApiParam(value = "用户ID", required = true) @NotEmpty(message = "请选择需要启用的用户!") @RequestBody List ids) { + + sysUserService.batchEnable(ids); + + for (String id : ids) { + sysUserService.cleanCacheByKey(id); + } + + return InvokeResultBuilder.success(); + } + + /** + * 新增用户 + */ + @ApiOperation("新增用户") + @HasPermission({"system:user:add"}) + @PostMapping + public InvokeResult create(@Valid @RequestBody CreateSysUserVo vo) { + + sysUserService.create(vo); + + return InvokeResultBuilder.success(); + } + + /** + * 修改用户 + */ + @ApiOperation("修改用户") + @HasPermission({"system:user:modify"}) + @PutMapping + public InvokeResult update(@Valid @RequestBody UpdateSysUserVo vo) { + + sysUserService.update(vo); + + sysUserService.cleanCacheByKey(vo.getId()); + + return InvokeResultBuilder.success(); + } + + /** + * 解锁用户 + */ + @ApiOperation("解锁用户") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission({"system:user:modify"}) + @PatchMapping("/unlock") + public InvokeResult unlock(@NotBlank(message = "ID不能为空!") String id) { + + sysUserService.unlockById(id); + + sysUserService.cleanCacheByKey(id); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserRoleController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserRoleController.java new file mode 100644 index 0000000..329696d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/SysUserRoleController.java @@ -0,0 +1,91 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.bo.system.user.QueryUserRoleBo; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.service.system.SysUserRoleService; +import com.lframework.xingyun.template.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserRoleSettingVo; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户授权 + * + * @author zmj + */ +@Api(tags = "用户授权") +@Validated +@RestController +@RequestMapping("/system/user/role") +public class SysUserRoleController extends DefaultBaseController { + + @Autowired + private SysRoleService sysRoleService; + + @Autowired + private SysUserRoleService sysUserRoleService; + + /** + * 查询角色列表 + */ + @ApiOperation("查询角色列表") + @ApiImplicitParams({@ApiImplicitParam(value = "用户ID", name = "userId", paramType = "query")}) + @HasPermission({"system:user:permission"}) + @GetMapping("/roles") + public InvokeResult> roles(String userId) { + + List results = CollectionUtil.emptyList(); + //查询所有角色 + QuerySysRoleVo sysRoleVo = new QuerySysRoleVo(); + sysRoleVo.setAvailable(Boolean.TRUE); + List allRole = sysRoleService.query(sysRoleVo); + if (!CollectionUtil.isEmpty(allRole)) { + results = allRole.stream().map(QueryUserRoleBo::new).collect(Collectors.toList()); + + if (!StringUtil.isBlank(userId)) { + List menus = sysRoleService.getByUserId(userId); + if (!CollectionUtil.isEmpty(menus)) { + //当用户角色存在时,设置已选择属性 + for (QueryUserRoleBo result : results) { + result.setSelected( + menus.stream().anyMatch(t -> StringUtil.equals(t.getId(), result.getId()))); + } + } + } + } + + return InvokeResultBuilder.success(results); + } + + /** + * 用户授权 + */ + @ApiOperation("用户授权") + @HasPermission({"system:user:permission"}) + @PostMapping("/setting") + public InvokeResult setting(@Valid @RequestBody SysUserRoleSettingVo vo) { + + sysUserRoleService.setting(vo); + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/TenantController.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/TenantController.java new file mode 100644 index 0000000..fc3659b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/controller/system/TenantController.java @@ -0,0 +1,143 @@ +package com.lframework.xingyun.template.inner.controller.system; + +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.utils.EncryptUtil; +import com.lframework.xingyun.template.inner.bo.system.tenant.GetTenantBo; +import com.lframework.xingyun.template.inner.bo.system.tenant.QueryTenantBo; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.TenantService; +import com.lframework.xingyun.template.inner.vo.system.tenant.CreateTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.UpdateTenantVo; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.annotations.security.HasPermission; +import com.lframework.starter.web.common.event.ReloadTenantEvent; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.controller.DefaultBaseController; +import com.lframework.starter.web.resp.InvokeResult; +import com.lframework.starter.web.resp.InvokeResultBuilder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 租户管理 + * + * @author zmj + */ +@Slf4j +@Api(tags = "租户管理") +@Validated +@RestController +@RequestMapping("/system/tenant") +public class TenantController extends DefaultBaseController { + + @Autowired + private TenantService tenantService; + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission(value = {"system:tenant:query", "system:tenant:add", + "system:tenant:modify"}) + @GetMapping("/query") + public InvokeResult> query(@Valid QueryTenantVo vo) { + + PageResult pageResult = tenantService.query(getPageIndex(vo), + getPageSize(vo), vo); + + List datas = pageResult.getDatas(); + List results = datas.stream().map(QueryTenantBo::new) + .collect(Collectors.toList()); + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + /** + * 查询详情 + */ + @ApiOperation("查询详情") + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true) + @HasPermission(value = {"system:tenant:query", "system:tenant:add", + "system:tenant:modify"}) + @GetMapping + public InvokeResult get(@NotNull(message = "ID不能为空!") Integer id) { + + Tenant data = tenantService.findById(id); + if (data == null) { + throw new DefaultClientException("租户不存在!"); + } + + GetTenantBo result = new GetTenantBo(data); + + return InvokeResultBuilder.success(result); + } + + /** + * 新增租户 + */ + @ApiOperation("新增租户") + @HasPermission(value = {"system:tenant:add"}) + @PostMapping + public InvokeResult create(@Valid CreateTenantVo vo) { + + Integer tenantId = tenantService.create(vo); + + try { + ReloadTenantEvent event = new ReloadTenantEvent(this, tenantId, vo.getJdbcUrl(), + vo.getJdbcUsername(), vo.getJdbcPassword()); + ApplicationUtil.publishEvent(event); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultClientException( + "动态加载租户数据源失败,请检查配置项!注意:虽然加载数据源失败,但是租户已经新增,请勿重复新增!"); + } + + return InvokeResultBuilder.success(); + } + + /** + * 修改租户 + */ + @ApiOperation("修改租户") + @HasPermission(value = {"system:tenant:modify"}) + @PutMapping + public InvokeResult update(@Valid UpdateTenantVo vo) { + + tenantService.update(vo); + + tenantService.cleanCacheByKey(vo.getId()); + + if (StringUtil.isNotBlank(vo.getJdbcUrl()) || StringUtil.isNotBlank(vo.getJdbcUsername()) + || StringUtil.isNotBlank(vo.getJdbcPassword())) { + // 这里不走缓存 + Tenant tenant = tenantService.getById(vo.getId()); + try { + ReloadTenantEvent event = new ReloadTenantEvent(this, tenant.getId(), tenant.getJdbcUrl(), + tenant.getJdbcUsername(), EncryptUtil.decrypt(tenant.getJdbcPassword())); + ApplicationUtil.publishEvent(event); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new DefaultClientException( + "动态加载租户数据源失败,请检查配置项!"); + } + } + + return InvokeResultBuilder.success(); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/LoginDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/LoginDto.java new file mode 100644 index 0000000..09a1a28 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/LoginDto.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.template.inner.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.util.Set; +import lombok.Data; + +/** + * 用户登录Dto + * + * @author zmj + */ +@Data +public class LoginDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Token + */ + private String token; + + /** + * 用户信息 + */ + private UserInfoDto user; + + /** + * 角色 + */ + private Set roles; + + public LoginDto(String token, String name, Set roles) { + + this.token = token; + this.setRoles(roles); + + UserInfoDto userInfo = new UserInfoDto(); + userInfo.setName(name); + this.setUser(userInfo); + } + + @Data + public static class UserInfoDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 姓名 + */ + private String name; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuDto.java new file mode 100644 index 0000000..a21b06f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuDto.java @@ -0,0 +1,82 @@ +package com.lframework.xingyun.template.inner.dto; + +import com.lframework.starter.web.dto.BaseDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +/** + * 菜单Dto + * + * @author zmj + */ +@Data +public class MenuDto implements BaseDto, Serializable { + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 菜单名称 + */ + @ApiModelProperty("菜单名称") + private String name; + + /** + * 路径 + */ + @ApiModelProperty("路径") + private String path; + + /** + * 是否隐藏 + */ + @ApiModelProperty("是否隐藏") + private Boolean hidden; + + /** + * 类型 0-目录 1-功能菜单 2-权限 + */ + @ApiModelProperty("类型 0-目录 1-功能菜单 2-权限") + private Integer display; + + /** + * 组件类型 + */ + @ApiModelProperty("组件类型") + private Integer componentType; + + /** + * 组件 + */ + @ApiModelProperty("组件") + private String component; + + /** + * 自定义请求参数 + */ + @ApiModelProperty("自定义请求参数") + private String requestParam; + + + /** + * meta + */ + @ApiModelProperty("meta") + private MenuMetaDto meta; + + /** + * 父节点ID + */ + @ApiModelProperty("父节点ID") + private String parentId; + + /** + * 是否收藏 + */ + @ApiModelProperty("是否收藏") + private Boolean isCollect = Boolean.FALSE; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuMetaDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuMetaDto.java new file mode 100644 index 0000000..94cf8d8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/MenuMetaDto.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.dto; + +import com.lframework.starter.web.dto.BaseDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +/** + * 菜单Meta Dto + * + * @author zmj + */ +@Data +public class MenuMetaDto implements BaseDto, Serializable { + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 是否不缓存 + */ + @ApiModelProperty("是否不缓存") + private Boolean noCache; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/UserInfoDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/UserInfoDto.java new file mode 100644 index 0000000..1e0533e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/UserInfoDto.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.template.inner.dto; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import lombok.Data; + +/** + * 用户信息 Dto + * + * @author zmj + */ +@Data +public class UserInfoDto implements BaseDto, Serializable { + + public static final String CACHE_NAME = "UserInfoDto"; + + /** + * ID + */ + private String id; + + /** + * 登录名 + */ + private String username; + + /** + * 编号 + */ + private String code; + + /** + * 姓名 + */ + private String name; + + /** + * 邮箱 + */ + private String email; + + /** + * 联系电话 + */ + private String telephone; + + /** + * 性别 + */ + private Integer gender; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/message/SysNoticeTaskDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/message/SysNoticeTaskDto.java new file mode 100644 index 0000000..15d14e0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/message/SysNoticeTaskDto.java @@ -0,0 +1,49 @@ +package com.lframework.xingyun.template.inner.dto.message; + +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.BaseDto; +import com.lframework.xingyun.template.inner.dto.system.notice.QuerySysNoticeByUserDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysNoticeTaskDto extends BaseBo implements BaseDto, + Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 是否已读 + */ + @ApiModelProperty("是否已读") + private Boolean readed; + + /** + * 发布时间 + */ + @ApiModelProperty("发布时间") + private String publishTime; + + public SysNoticeTaskDto(QuerySysNoticeByUserDto dto) { + super(dto); + } + + @Override + protected void afterInit(QuerySysNoticeByUserDto dto) { + this.publishTime = DateUtil.formatDateTime(dto.getPublishTime()); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/qrtz/QrtzDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/qrtz/QrtzDto.java new file mode 100644 index 0000000..bf02889 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/qrtz/QrtzDto.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.template.inner.dto.qrtz; + +import com.lframework.xingyun.template.inner.enums.QrtzJobType; +import com.lframework.xingyun.template.inner.enums.TriggerState; +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class QrtzDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + private String name; + + /** + * 分组 + */ + private String group; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 备注 + */ + private String description; + + /** + * 执行类名 + */ + private String targetClassName; + + /** + * 执行方法名 + */ + private String targetMethodName; + + /** + * 执行参数类型 + */ + private List targetParamTypes; + + /** + * 执行参数 + */ + private List targetParams; + + /** + * 脚本 + */ + private String script; + + /** + * 任务类型 + */ + private QrtzJobType jobType; + + /** + * Cron表达式 + */ + private String cron; + + /** + * 状态 + */ + private TriggerState state; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/QuerySysNoticeByUserDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/QuerySysNoticeByUserDto.java new file mode 100644 index 0000000..debd7c9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/QuerySysNoticeByUserDto.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.inner.dto.system.notice; + +import com.lframework.starter.web.dto.BaseDto; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/19 + */ +@Data +public class QuerySysNoticeByUserDto implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 是否已读 + */ + private Boolean readed; + + /** + * 发布时间 + */ + private LocalDateTime publishTime; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/SysNoticeDto.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/SysNoticeDto.java new file mode 100644 index 0000000..4697977 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/dto/system/notice/SysNoticeDto.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.inner.dto.system.notice; + +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.dto.BaseDto; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/18 + */ +@Data +public class SysNoticeDto extends BaseBo implements BaseDto, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 内容 + */ + @ApiModelProperty("内容") + private String content; + + public SysNoticeDto(SysNotice dto) { + super(dto); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDic.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDic.java new file mode 100644 index 0000000..fa5cd1c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDic.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据字典 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_dic") +public class SysDataDic extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysDataDic"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 分类ID + */ + private String categoryId; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicCategory.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicCategory.java new file mode 100644 index 0000000..bd47a83 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicCategory.java @@ -0,0 +1,76 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据字典分类 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_dic_category") +public class SysDataDicCategory extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysDataDicCategory"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicItem.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicItem.java new file mode 100644 index 0000000..8d9f2cb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDataDicItem.java @@ -0,0 +1,86 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 数据字典值 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_data_dic_item") +public class SysDataDicItem extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysDataDicItem"; + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 字典ID + */ + private String dicId; + + /** + * 排序编号 + */ + private Integer orderNo; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDept.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDept.java new file mode 100644 index 0000000..f1f4fdd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysDept.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 部门 + *

+ * + * @author zmj + * @since 2021-06-26 + */ +@Data +@TableName("sys_dept") +public class SysDept extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysDept"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 简称 + */ + private String shortName; + + /** + * 父级ID + */ + @TableField + private String parentId; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysMenu.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysMenu.java new file mode 100644 index 0000000..5b6419f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysMenu.java @@ -0,0 +1,149 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.xingyun.template.inner.enums.system.SysMenuComponentType; +import com.lframework.xingyun.template.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统菜单 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +@Data +@TableName("sys_menu") +public class SysMenu extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysMenu"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称(前端使用) + */ + private String name; + + /** + * 标题 + */ + private String title; + + /** + * 图标 + */ + private String icon; + + /** + * 组件类型 + */ + private SysMenuComponentType componentType; + + /** + * 组件(前端使用) + */ + private String component; + + /** + * 自定义请求参数 + */ + private String requestParam; + + /** + * 父级ID + */ + private String parentId; + + /** + * 路由路径(前端使用) + */ + private String path; + + /** + * 是否缓存(前端使用) + */ + private Boolean noCache; + + /** + * 类型 0-目录 1-菜单 2-功能 + */ + private SysMenuDisplay display; + + /** + * 是否隐藏(前端使用) + */ + private Boolean hidden; + + /** + * 权限 + */ + private String permission; + + /** + * 是否特殊菜单 + */ + private Boolean isSpecial; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModule.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModule.java new file mode 100644 index 0000000..1ad1cad --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModule.java @@ -0,0 +1,78 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统模块 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_module") +public class SysModule extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysModule"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModuleTenant.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModuleTenant.java new file mode 100644 index 0000000..a5048e2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysModuleTenant.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 租户和系统模块关系表 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_module_tenant") +public class SysModuleTenant extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysModuleTenant"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 模块ID + */ + private Integer moduleId; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 过期时间 + */ + private LocalDateTime expireTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNotice.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNotice.java new file mode 100644 index 0000000..e7d90c5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNotice.java @@ -0,0 +1,100 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统通知 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_notice") +public class SysNotice extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysNotice"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 状态 + */ + private Boolean available; + + /** + * 是否发布 + */ + private Boolean published; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 已读人数 + */ + private Integer readedNum; + + /** + * 未读人数 + */ + private Integer unReadNum; + + /** + * 发布时间 + */ + private LocalDateTime publishTime; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNoticeLog.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNoticeLog.java new file mode 100644 index 0000000..7b0821f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysNoticeLog.java @@ -0,0 +1,47 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统通知记录 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_notice_log") +public class SysNoticeLog extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysNoticeLog"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + private String id; + + /** + * 标题 + */ + private String noticeId; + + /** + * 用户ID + */ + private String userId; + + /** + * 是否已读 + */ + private Boolean readed; + + /** + * 已读时间 + */ + private LocalDateTime readTime; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysOpenDomain.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysOpenDomain.java new file mode 100644 index 0000000..a102dc6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysOpenDomain.java @@ -0,0 +1,95 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 开放域 + *

+ * + * @author zmj + * @since 2021-07-02 + */ +@Data +@TableName("sys_open_domain") +public class SysOpenDomain extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysOpenDomain"; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private String id; + + /** + * 名称 + */ + private String name; + + /** + * API密钥 + */ + private String apiSecret; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 租户ID + */ + private Integer tenantId; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysParameter.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysParameter.java new file mode 100644 index 0000000..be23f72 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysParameter.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统参数 + *

+ * + * @author zmj + */ +@Data +@TableName("sys_parameter") +public class SysParameter extends BaseEntity implements BaseDto { + + public static final String CACHE_NAME = "SysParameter"; + private static final long serialVersionUID = 1L; + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 键 + */ + private String pmKey; + + /** + * 值 + */ + private String pmValue; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysPosition.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysPosition.java new file mode 100644 index 0000000..4345805 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysPosition.java @@ -0,0 +1,87 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 系统岗位 + *

+ * + * @author zmj + * @since 2021-07-01 + */ +@Data +@TableName("sys_position") +public class SysPosition extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysPosition"; + + /** + * ID + */ + private String id; + + /** + * 岗位编号 + */ + private String code; + + /** + * 岗位名称 + */ + private String name; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRole.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRole.java new file mode 100644 index 0000000..7559505 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRole.java @@ -0,0 +1,92 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-02 + */ +@Data +@TableName("sys_role") +public class SysRole extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysRole"; + + /** + * ID + */ + private String id; + + /** + * 编号 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 权限 + */ + private String permission; + + /** + * 状态 + */ + private Boolean available; + + /** + * 备注 + */ + private String description; + + /** + * 创建人ID 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createById; + + /** + * 创建人 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** + * 修改人ID 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateById; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRoleMenu.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRoleMenu.java new file mode 100644 index 0000000..c78adf9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysRoleMenu.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_role_menu") +public class SysRoleMenu extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 角色ID + */ + private String roleId; + + /** + * 菜单ID + */ + private String menuId; + + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserDept.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserDept.java new file mode 100644 index 0000000..9a9579b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserDept.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user_dept") +public class SysUserDept extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "SysUserDept"; + + /** + * ID + */ + private String id; + + /** + * 用户ID + */ + private String userId; + + /** + * 部门ID + */ + private String deptId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserPosition.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserPosition.java new file mode 100644 index 0000000..a433770 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserPosition.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user_position") +public class SysUserPosition extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 用户ID + */ + private String userId; + + /** + * 岗位ID + */ + private String positionId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserRole.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserRole.java new file mode 100644 index 0000000..29a6b26 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserRole.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author zmj + * @since 2021-07-04 + */ +@Data +@TableName("sys_user_role") +public class SysUserRole extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 用户ID + */ + private String userId; + + /** + * 角色ID + */ + private String roleId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserTelephone.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserTelephone.java new file mode 100644 index 0000000..2d9be92 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/SysUserTelephone.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import lombok.Data; + +@Data +@TableName("sys_user_telephone") +public class SysUserTelephone extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 手机号 + */ + private String telephone; + + /** + * 用户ID + */ + private String userId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/Tenant.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/Tenant.java new file mode 100644 index 0000000..b421235 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/entity/Tenant.java @@ -0,0 +1,71 @@ +package com.lframework.xingyun.template.inner.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lframework.starter.web.entity.BaseEntity; +import com.lframework.starter.web.dto.BaseDto; +import java.time.LocalDateTime; +import lombok.Data; + +/** + *

+ * 租户 + *

+ * + * @author zmj + * @since 2023-03-05 + */ +@Data +@TableName("tenant") +public class Tenant extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "Tenant"; + + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * JdbcUrl + */ + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + private String jdbcUsername; + + /** + * Jdbc密码 + */ + private String jdbcPassword; + + /** + * 状态 + */ + private Boolean available; + + /** + * 创建时间 新增时赋值 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改时间 新增和修改时赋值 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/QrtzJobType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/QrtzJobType.java new file mode 100644 index 0000000..30469f0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/QrtzJobType.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +/** + * @author zmj + * @since 2022/8/20 + */ +public enum QrtzJobType implements BaseEnum { + EXCUTE_CLASS(1, "指定类"), + GROOVY(2, "Groovy脚本"); + + @EnumValue + private final Integer code; + + private final String desc; + + QrtzJobType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/TriggerState.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/TriggerState.java new file mode 100644 index 0000000..f0b2066 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/TriggerState.java @@ -0,0 +1,34 @@ +package com.lframework.xingyun.template.inner.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum TriggerState implements BaseEnum { + WAITING("WAITING", "等待执行"), + PAUSED("PAUSED", "暂停执行"), + ACQUIRED("ACQUIRED", "正常执行"), + BLOCKED("BLOCKED", "阻塞"), + ERROR("ERROR", "执行错误"), + COMPLETE("COMPLETE", "执行完毕"), + PAUSED_BLOCKED("PAUSED_BLOCKED", "阻塞暂停"); + + @EnumValue + private final String code; + + private final String desc; + + TriggerState(String code, String desc) { + this.code = code; + this.desc = desc; + } + + @Override + public String getCode() { + return this.code; + } + + @Override + public String getDesc() { + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysDeptNodeType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysDeptNodeType.java new file mode 100644 index 0000000..179f7e8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysDeptNodeType.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.inner.enums.system; + +import com.lframework.xingyun.template.core.enums.NodeType; +import java.io.Serializable; +import org.springframework.stereotype.Component; + +@Component +public final class SysDeptNodeType implements NodeType, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public Integer getCode() { + + return 1; + } + + @Override + public String getDesc() { + + return "部门"; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuComponentType.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuComponentType.java new file mode 100644 index 0000000..961bce1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuComponentType.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysMenuComponentType implements BaseEnum { + + NORMAL(0, "普通"), CUSTOM_LIST(1, "自定义列表"), CUSTOM_PAGE(3, "自定义页面"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysMenuComponentType(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuDisplay.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuDisplay.java new file mode 100644 index 0000000..10bdfde --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/enums/system/SysMenuDisplay.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.inner.enums.system; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.lframework.starter.web.enums.BaseEnum; + +public enum SysMenuDisplay implements BaseEnum { + + CATALOG(0, "目录"), FUNCTION(1, "菜单"), PERMISSION(2, "权限"); + + @EnumValue + private final Integer code; + + private final String desc; + + SysMenuDisplay(Integer code, String desc) { + + this.code = code; + this.desc = desc; + } + + @Override + public Integer getCode() { + + return this.code; + } + + @Override + public String getDesc() { + + return this.desc; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LoginEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LoginEvent.java new file mode 100644 index 0000000..bf2a184 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LoginEvent.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.inner.events; + +import com.lframework.starter.web.common.security.AbstractUserDetails; +import org.springframework.context.ApplicationEvent; + +/** + * 用户登录事件 + * + * @author zmj + */ +public class LoginEvent extends ApplicationEvent { + + private final AbstractUserDetails user; + + private final String token; + + /** + * Create a new {@code ApplicationEvent}. + * + * @param source the object on which the event initially occurred or with which the event is + * associated (never {@code null}) + */ + public LoginEvent(Object source, AbstractUserDetails user, String token) { + + super(source); + + this.user = user; + this.token = token; + } + + public AbstractUserDetails getUser() { + + return user; + } + + public String getToken() { + + return token; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LogoutEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LogoutEvent.java new file mode 100644 index 0000000..5024d49 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/LogoutEvent.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.events; + +import com.lframework.starter.web.common.security.AbstractUserDetails; +import org.springframework.context.ApplicationEvent; + +/** + * 用户退出登录事件 + * + * @author zmj + */ +public class LogoutEvent extends ApplicationEvent { + + private final AbstractUserDetails user; + + private final String token; + + public LogoutEvent(Object source, AbstractUserDetails user, String token) { + + super(source); + this.user = user; + this.token = token; + } + + public AbstractUserDetails getUser() { + + return user; + } + + public String getToken() { + + return token; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/UpdateUserEvent.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/UpdateUserEvent.java new file mode 100644 index 0000000..646a1a9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/events/UpdateUserEvent.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.inner.events; + +import org.springframework.context.ApplicationEvent; + +/** + * 修改用户事件 + * + * @author zmj + */ +public class UpdateUserEvent extends ApplicationEvent { + + /** + * 用户ID + */ + private String id; + + public UpdateUserEvent(Object source, String id) { + + super(source); + this.id = id; + } + + public String getId() { + + return id; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/AbstractUserDetailsService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/AbstractUserDetailsService.java new file mode 100644 index 0000000..d930659 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/AbstractUserDetailsService.java @@ -0,0 +1,91 @@ +package com.lframework.xingyun.template.inner.impl; + +import com.lframework.starter.common.exceptions.impl.UserLoginException; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.components.security.UserDetailsService; +import com.lframework.starter.web.utils.RequestUtil; +import com.lframework.starter.web.utils.TenantUtil; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +/** + * 所有UserDetailsService都需要继承此类 如果需要更改用户表,那么继承此类注册Bean即可 + * + * @author zmj + */ +@Slf4j +public abstract class AbstractUserDetailsService implements UserDetailsService { + + @Autowired + private SysMenuService sysMenuService; + + @Autowired + private SysModuleTenantService sysModuleTenantService; + + @Value("${remove-fixed-permissions:false}") + private Boolean removeFixedPermission; + + @Override + public AbstractUserDetails loadUserByUsername(String username) throws UserLoginException { + + //根据登录名查询 + AbstractUserDetails userDetails = this.findByUsername(username); + + if (ObjectUtil.isEmpty(userDetails)) { + log.debug("用户名 {} 不存在", username); + throw new UserLoginException("用户名或密码错误!"); + } + + userDetails.setTenantId(TenantContextHolder.getTenantId()); + + //获取登录IP + userDetails.setIp(RequestUtil.getRequestIp()); + + // 先查询当前租户使用的module + List moduleIds = null; + if (TenantUtil.enableTenant()) { + moduleIds = sysModuleTenantService.getAvailableModuleIdsByTenantId( + TenantContextHolder.getTenantId()); + } + + // 先取角色的权限 + userDetails.setPermissions(sysMenuService.getRolePermissionByUserId(userDetails.getId())); + userDetails.setIsAdmin( + userDetails.getPermissions().contains(SecurityConstants.PERMISSION_ADMIN_NAME)); + // 再取菜单的权限 + Set permissions = sysMenuService.getPermissionsByUserId(userDetails.getId(), + userDetails.isAdmin(), moduleIds); + // 合并权限 + permissions.addAll(userDetails.getPermissions()); + if (this.removeFixedPermission) { + permissions.remove(SecurityConstants.PERMISSION_ADMIN_NAME); + } + userDetails.setPermissions(permissions); + + return userDetails; + } + + /** + * 根据登录名查询 + * + * @param username + * @return + */ + public abstract AbstractUserDetails findByUsername(String username); + + /** + * 根据用户ID查询编码 + * + * @param userId + * @return + */ + public abstract String codeByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/QrtzServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/QrtzServiceImpl.java new file mode 100644 index 0000000..50079be --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/QrtzServiceImpl.java @@ -0,0 +1,201 @@ +package com.lframework.xingyun.template.inner.impl; + +import cn.hutool.core.exceptions.UtilException; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ReflectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.core.components.qrtz.QrtzHandler; +import com.lframework.xingyun.template.inner.components.qrtz.DynamicQrtzJob; +import com.lframework.xingyun.template.inner.dto.qrtz.QrtzDto; +import com.lframework.xingyun.template.inner.enums.QrtzJobType; +import com.lframework.xingyun.template.inner.mappers.QrtzMapper; +import com.lframework.xingyun.template.inner.service.QrtzService; +import com.lframework.xingyun.template.inner.vo.qrtz.CreateQrtzVo; +import com.lframework.xingyun.template.inner.vo.qrtz.QueryQrtzVo; +import com.lframework.xingyun.template.inner.vo.qrtz.UpdateQrtzVo; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.quartz.JobDetail; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Slf4j +@DS("master") +@Service +public class QrtzServiceImpl implements QrtzService { + + @Autowired + private QrtzMapper qrtzMapper; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryQrtzVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + vo.setJobClasses(new ArrayList<>()); + vo.getJobClasses().add(DynamicQrtzJob.class.getName()); + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = qrtzMapper.query(vo); + PageResult pageResult = PageResultUtil.convert(new PageInfo<>(datas)); + datas.stream().forEach(this::renderDto); + + return pageResult; + } + + @Override + public QrtzDto findById(String name, String group) { + QrtzDto data = qrtzMapper.findById(name, group); + if (data == null) { + return null; + } + + return renderDto(data); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(CreateQrtzVo vo) { + JobDetail jobDetail = QrtzHandler.getJob(vo.getName(), vo.getGroup()); + if (jobDetail != null) { + throw new DefaultClientException("名称、组不允许重复,请重新输入!"); + } + QrtzJobType jobType = EnumUtil.getByCode(QrtzJobType.class, vo.getJobType()); + if (jobType == QrtzJobType.EXCUTE_CLASS) { + if (StringUtil.isBlank(vo.getTargetClassName())) { + throw new DefaultClientException("类名不能为空!"); + } + if (StringUtil.isBlank(vo.getTargetMethodName())) { + throw new DefaultClientException("方法名不能为空!"); + } + + if (!CollectionUtil.isEmpty(vo.getTargetParamTypes()) || !CollectionUtil.isEmpty( + vo.getTargetParams())) { + int typeSize = vo.getTargetParamTypes() == null ? 0 : vo.getTargetParamTypes().size(); + int paramSize = vo.getTargetParams() == null ? 0 : vo.getTargetParams().size(); + if (typeSize != paramSize) { + throw new DefaultClientException("参数类型与参数数量不匹配!"); + } + } + try { + Class clazz = Class.forName(vo.getTargetClassName()); + ReflectUtil.newInstance(clazz); + Class[] paramTypes = null; + if (!CollectionUtil.isEmpty(vo.getTargetParamTypes())) { + paramTypes = new Class[vo.getTargetParamTypes().size()]; + for (int i = 0; i < vo.getTargetParamTypes().size(); i++) { + String targetParamType = vo.getTargetParamTypes().get(i); + try { + paramTypes[i] = Class.forName(targetParamType); + } catch (ClassNotFoundException e) { + throw new DefaultClientException( + "参数类型:" + targetParamType + "不存在,需要输入类型全名称,如:java.lang.String,请检查!"); + } + } + } + // 验证一下参数 + ReflectUtil.getMethod(clazz, vo.getTargetMethodName(), paramTypes); + + Map jobDataMap = new HashMap<>(); + jobDataMap.put("targetClassName", vo.getTargetClassName()); + jobDataMap.put("targetMethodName", vo.getTargetMethodName()); + jobDataMap.put("targetParamTypes", vo.getTargetParamTypes()); + jobDataMap.put("targetParams", vo.getTargetParams()); + jobDataMap.put("jobType", vo.getJobType()); + if (vo.getTenantId() != null) { + jobDataMap.put(StringPool.TENANT_ID_QRTZ, vo.getTenantId()); + } + + QrtzHandler.addJob(vo.getName(), vo.getGroup(), DynamicQrtzJob.class, + "custom_trigger_" + vo.getName(), vo.getGroup(), vo.getCron(), jobDataMap, + vo.getDescription()); + } catch (ClassNotFoundException e) { + throw new DefaultClientException("类:" + vo.getTargetClassName() + "不存在,请检查!"); + } catch (UtilException e) { + throw new DefaultClientException("类:" + vo.getTargetClassName() + "无法加载,请检查!"); + } + } else { + Map jobDataMap = new HashMap<>(); + jobDataMap.put("script", vo.getScript()); + jobDataMap.put("jobType", vo.getJobType()); + if (vo.getTenantId() != null) { + jobDataMap.put(StringPool.TENANT_ID_QRTZ, vo.getTenantId()); + } + + QrtzHandler.addJob(vo.getName(), vo.getGroup(), DynamicQrtzJob.class, + "custom_trigger_" + vo.getName(), vo.getGroup(), vo.getCron(), jobDataMap, + vo.getDescription()); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateQrtzVo vo) { + JobDetail jobDetail = QrtzHandler.getJob(vo.getOriName(), vo.getOriGroup()); + if (jobDetail == null) { + throw new DefaultClientException("任务不存在!"); + } + + this.delete(vo.getOriName(), vo.getOriGroup()); + + this.create(vo); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void resume(String name, String group) { + QrtzHandler.resume(name, group); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void pause(String name, String group) { + QrtzHandler.pause(name, group); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void trigger(String name, String group) { + QrtzHandler.trigger(name, group); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(String name, String group) { + + QrtzHandler.deleteJob(name, group, "custom_trigger_" + name, group); + } + + private QrtzDto renderDto(QrtzDto data) { + JobDetail jobDetail = QrtzHandler.getJob(data.getName(), data.getGroup()); + Integer jobType = jobDetail.getJobDataMap().getIntValue("jobType"); + data.setJobType(EnumUtil.getByCode(QrtzJobType.class, jobType)); + data.setTargetClassName(jobDetail.getJobDataMap().getString("targetClassName")); + data.setTargetMethodName(jobDetail.getJobDataMap().getString("targetMethodName")); + data.setTargetParamTypes((List) jobDetail.getJobDataMap().get("targetParamTypes")); + data.setTargetParams((List) jobDetail.getJobDataMap().get("targetParams")); + data.setScript(jobDetail.getJobDataMap().getString("script")); + Object tenantStr = jobDetail.getJobDataMap().get(StringPool.TENANT_ID_QRTZ); + data.setTenantId(tenantStr == null ? null : Integer.valueOf(String.valueOf(tenantStr))); + + return data; + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleServiceImpl.java new file mode 100644 index 0000000..a782082 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleServiceImpl.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.template.inner.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.inner.entity.SysModule; +import com.lframework.xingyun.template.inner.mappers.SysModuleMapper; +import com.lframework.xingyun.template.inner.service.SysModuleService; +import org.springframework.stereotype.Service; + +@DS("master") +@Service +public class SysModuleServiceImpl extends BaseMpServiceImpl implements + SysModuleService { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleTenantServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleTenantServiceImpl.java new file mode 100644 index 0000000..9e3fd2e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/SysModuleTenantServiceImpl.java @@ -0,0 +1,70 @@ +package com.lframework.xingyun.template.inner.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.DateUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.inner.entity.SysModuleTenant; +import com.lframework.xingyun.template.inner.mappers.SysModuleTenantMapper; +import com.lframework.xingyun.template.inner.service.SysModuleTenantService; +import com.lframework.xingyun.template.inner.vo.system.module.SysModuleTenantVo; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@DS("master") +@Service +public class SysModuleTenantServiceImpl extends + BaseMpServiceImpl implements SysModuleTenantService { + + @Override + public List getAvailableModuleIdsByTenantId(Integer tenantId) { + SysModuleTenantService thisService = getThis(getClass()); + return thisService.getByTenantId(tenantId).stream() + .filter(t -> DateUtil.now().isBefore(t.getExpireTime())).map(SysModuleTenant::getModuleId) + .collect(Collectors.toList()); + } + + @Cacheable(value = SysModuleTenant.CACHE_NAME, key = "#tenantId", unless = "#result == null or #result.isEmpty()") + @Override + public List getByTenantId(Integer tenantId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysModuleTenant.class) + .eq(SysModuleTenant::getTenantId, tenantId); + return this.list(queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysModuleTenantVo vo) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysModuleTenant.class) + .eq(SysModuleTenant::getTenantId, vo.getTenantId()); + this.remove(queryWrapper); + + if (CollectionUtil.isNotEmpty(vo.getModules())) { + List records = vo.getModules().stream().map(t -> { + SysModuleTenant record = new SysModuleTenant(); + record.setId(IdUtil.getId()); + record.setModuleId(t.getModuleId()); + record.setTenantId(vo.getTenantId()); + record.setExpireTime(t.getExpireTime()); + + return record; + }).collect(Collectors.toList()); + + this.saveBatch(records); + } + } + + @CacheEvict(value = SysModuleTenant.CACHE_NAME, key = "#key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/TenantServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/TenantServiceImpl.java new file mode 100644 index 0000000..4b7ee03 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/TenantServiceImpl.java @@ -0,0 +1,108 @@ +package com.lframework.xingyun.template.inner.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.EncryptUtil; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.xingyun.template.inner.service.TenantService; +import com.lframework.xingyun.template.inner.vo.system.tenant.CreateTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.TenantSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.UpdateTenantVo; +import com.lframework.xingyun.template.inner.mappers.TenantMapper; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@DS("master") +@Service +public class TenantServiceImpl extends BaseMpServiceImpl implements + TenantService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QueryTenantVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, TenantSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = Tenant.CACHE_NAME, key = "#id", unless = "#result == null") + @Override + public Tenant findById(Integer id) { + return getById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Integer create(CreateTenantVo data) { + + Tenant record = new Tenant(); + record.setName(data.getName()); + record.setJdbcUrl(data.getJdbcUrl()); + record.setJdbcUsername(data.getJdbcUsername()); + record.setJdbcPassword(EncryptUtil.encrypt(data.getJdbcPassword())); + record.setAvailable(Boolean.TRUE); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateTenantVo data) { + + Tenant record = this.getById(data.getId()); + if (record == null) { + throw new DefaultClientException("租户不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Tenant.class) + .eq(Tenant::getId, data.getId()).set(Tenant::getName, data.getName()) + .set(Tenant::getAvailable, data.getAvailable()); + if (StringUtil.isNotBlank(data.getJdbcUrl())) { + updateWrapper.set(Tenant::getJdbcUrl, data.getJdbcUrl()); + } + if (StringUtil.isNotBlank(data.getJdbcUsername())) { + updateWrapper.set(Tenant::getJdbcUsername, data.getJdbcUsername()); + } + if (StringUtil.isNotBlank(data.getJdbcPassword())) { + updateWrapper.set(Tenant::getJdbcPassword, EncryptUtil.encrypt(data.getJdbcPassword())); + } + + this.update(updateWrapper); + } + + @CacheEvict(value = Tenant.CACHE_NAME, key = "#key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/UserDetailsService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/UserDetailsService.java new file mode 100644 index 0000000..2e0f1e6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/UserDetailsService.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.impl; + +import com.lframework.xingyun.template.inner.mappers.UserDetailsMapper; +import com.lframework.starter.web.common.security.AbstractUserDetails; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * UserDetaisService默认实现 + * + * @author zmj + */ +@Service +public class UserDetailsService extends AbstractUserDetailsService { + + @Autowired + private UserDetailsMapper userDetailsMapper; + + @Override + public AbstractUserDetails findByUsername(String username) { + + AbstractUserDetails user = userDetailsMapper.findByUsername(username); + + return user; + } + + @Override + public String codeByUserId(String userId) { + return userDetailsMapper.codeByUserId(userId); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicCategoryServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicCategoryServiceImpl.java new file mode 100644 index 0000000..eda24c5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicCategoryServiceImpl.java @@ -0,0 +1,130 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.service.system.SysDataDicCategoryService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.xingyun.template.inner.vo.system.dic.category.CreateSysDataDicCategoryVo; +import com.lframework.xingyun.template.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import com.lframework.xingyun.template.inner.vo.system.dic.category.UpdateSysDataDicCategoryVo; +import com.lframework.xingyun.template.inner.mappers.system.SysDataDicCategoryMapper; +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysDataDicCategoryServiceImpl extends + BaseMpServiceImpl implements + SysDataDicCategoryService { + + @Autowired + private SysDataDicService sysDataDicService; + + @Cacheable(value = SysDataDicCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + 'all'") + @Override + public List queryList() { + return getBaseMapper().query(); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysDataDicCategorySelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysDataDicCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDataDicCategory findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDataDicCategoryVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDicCategory record = new SysDataDicCategory(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDataDicCategoryVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getCode, vo.getCode()).ne(SysDataDicCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicCategory.class) + .eq(SysDataDicCategory::getName, vo.getName()).ne(SysDataDicCategory::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDicCategory record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据字典分类不存在!"); + } + + record.setCode(vo.getCode()); + record.setName(vo.getName()); + + this.updateById(record); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + Wrapper queryDicWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCategoryId, id); + if (sysDataDicService.count(queryDicWrapper) > 0) { + throw new DefaultClientException("此分类下存在数据字典,无法删除!"); + } + + this.removeById(id); + } + + @CacheEvict(value = SysDataDicCategory.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicItemServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicItemServiceImpl.java new file mode 100644 index 0000000..55a01bb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicItemServiceImpl.java @@ -0,0 +1,156 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.xingyun.template.inner.vo.system.dic.item.CreateSysDataDicItemVo; +import com.lframework.xingyun.template.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import com.lframework.xingyun.template.inner.vo.system.dic.item.UpdateSysDataDicItemVo; +import com.lframework.xingyun.template.inner.mappers.system.SysDataDicItemMapper; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.service.system.SysDataDicItemService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysDataDicItemServiceImpl extends + BaseMpServiceImpl implements SysDataDicItemService { + + @Autowired + private SysDataDicService sysDataDicService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysDataDicItemVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysDataDicItemVo vo) { + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysDataDicItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDataDicItem findById(String id) { + return getBaseMapper().selectById(id); + } + + @Override + public SysDataDicItem findByCode(String dicCode, String code) { + SysDataDicItemService thisService = getThis(getClass()); + List items = thisService.findByDicCode(dicCode); + if (CollectionUtil.isEmpty(items)) { + return null; + } + + return items.stream().filter(t -> t.getCode().equals(code)).findFirst().orElse(null); + } + + @Cacheable(value = SysDataDicItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #dicCode") + @Override + public List findByDicCode(String dicCode) { + Wrapper queryDicWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCode, dicCode); + SysDataDic dic = sysDataDicService.getOne(queryDicWrapper); + if (dic == null) { + throw new DefaultClientException("数据字典不存在!"); + } + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, dic.getId()).orderByAsc(SysDataDicItem::getOrderNo); + List datas = this.list(queryWrapper); + + return datas; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDataDicItemVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, vo.getDicId()) + .eq(SysDataDicItem::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, vo.getDicId()) + .eq(SysDataDicItem::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDicItem record = new SysDataDicItem(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + record.setDicId(vo.getDicId()); + record.setOrderNo(vo.getOrderNo()); + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDataDicItemVo vo) { + + SysDataDicItem record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据字典值不存在!"); + } + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, record.getDicId()) + .eq(SysDataDicItem::getCode, vo.getCode()).ne(SysDataDicItem::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, record.getDicId()) + .eq(SysDataDicItem::getName, vo.getName()).ne(SysDataDicItem::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDataDicItem.class) + .set(SysDataDicItem::getCode, vo.getCode()).set(SysDataDicItem::getName, vo.getName()) + .set(SysDataDicItem::getOrderNo, vo.getOrderNo()).eq(SysDataDicItem::getId, vo.getId()); + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + this.removeById(id); + } + + @CacheEvict(value = SysDataDicItem.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicServiceImpl.java new file mode 100644 index 0000000..1cb6066 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataDicServiceImpl.java @@ -0,0 +1,145 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.xingyun.template.inner.service.system.SysDataDicItemService; +import com.lframework.xingyun.template.inner.service.system.SysDataDicService; +import com.lframework.xingyun.template.inner.vo.system.dic.CreateSysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.SysDataDicSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.dic.UpdateSysDataDicVo; +import com.lframework.xingyun.template.inner.mappers.system.SysDataDicMapper; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysDataDicServiceImpl extends + BaseMpServiceImpl implements + SysDataDicService { + + @Autowired + private SysDataDicItemService sysDataDicItemService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySysDataDicVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysDataDicVo vo) { + return getBaseMapper().query(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysDataDicSelectorVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().selector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysDataDic.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDataDic findById(String id) { + return getBaseMapper().selectById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDataDicVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCode, vo.getCode()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getName, vo.getName()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDic record = new SysDataDic(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + if (!StringUtil.isBlank(vo.getCategoryId())) { + record.setCategoryId(vo.getCategoryId()); + } + + this.save(record); + + return record.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDataDicVo vo) { + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getCode, vo.getCode()).ne(SysDataDic::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysDataDic.class) + .eq(SysDataDic::getName, vo.getName()).ne(SysDataDic::getId, vo.getId()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDataDic record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("数据字典不存在!"); + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDataDic.class) + .set(SysDataDic::getCode, vo.getCode()).set(SysDataDic::getName, vo.getName()) + .set(SysDataDic::getCategoryId, + StringUtil.isBlank(vo.getCategoryId()) ? null : vo.getCategoryId()) + .eq(SysDataDic::getId, vo.getId()); + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(String id) { + + this.removeById(id); + + Wrapper deleteItemWrapper = Wrappers.lambdaQuery(SysDataDicItem.class) + .eq(SysDataDicItem::getDicId, id); + sysDataDicItemService.remove(deleteItemWrapper); + } + + @CacheEvict(value = SysDataDic.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataPermissionDataServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataPermissionDataServiceImpl.java new file mode 100644 index 0000000..58e7703 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDataPermissionDataServiceImpl.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.core.entity.SysDataPermissionData; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.inner.mappers.system.SysDataPermissionDataMapper; +import com.lframework.xingyun.template.inner.service.system.SysDataPermissionDataService; +import java.util.List; +import org.springframework.stereotype.Service; + +@Service +public class SysDataPermissionDataServiceImpl extends + BaseMpServiceImpl implements + SysDataPermissionDataService { + + @Override + public List getByBizId(String bizId) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDataPermissionData.class) + .eq(SysDataPermissionData::getBizId, bizId); + + return this.list(queryWrapper); + } + + @Override + public SysDataPermissionData getByBizId(String bizId, Integer bizType, Integer permissionType) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysDataPermissionData.class) + .eq(SysDataPermissionData::getBizId, bizId).eq(SysDataPermissionData::getBizType, bizType) + .eq(SysDataPermissionData::getPermissionType, permissionType); + + return this.getOne(queryWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDeptServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDeptServiceImpl.java new file mode 100644 index 0000000..20565b3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysDeptServiceImpl.java @@ -0,0 +1,284 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.service.DeptService; +import com.lframework.xingyun.template.core.service.RecursionMappingService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.xingyun.template.inner.enums.system.SysDeptNodeType; +import com.lframework.xingyun.template.inner.vo.system.dept.CreateSysDeptVo; +import com.lframework.xingyun.template.inner.vo.system.dept.UpdateSysDeptVo; +import com.lframework.xingyun.template.inner.mappers.system.SysDeptMapper; +import com.lframework.xingyun.template.inner.service.system.SysDeptService; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysDeptServiceImpl extends BaseMpServiceImpl implements + SysDeptService { + + @Autowired + private RecursionMappingService recursionMappingService; + + @Autowired + private DeptService deptService; + + @Override + public List selector() { + + return this.doSelector(); + } + + @Cacheable(value = SysDept.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysDept findById(String id) { + + return this.doGetById(id); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "停用部门,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + List batchIds = new ArrayList<>(); + for (String id : ids) { + List nodeChildIds = recursionMappingService.getNodeChildIds(id, + ApplicationUtil.getBean(SysDeptNodeType.class)); + if (CollectionUtil.isEmpty(nodeChildIds)) { + continue; + } + + batchIds.addAll(nodeChildIds); + } + + batchIds.addAll(ids); + + this.doBatchUnable(batchIds); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "启用部门,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + List batchIds = new ArrayList<>(); + for (String id : ids) { + List nodeChildIds = recursionMappingService.getNodeParentIds(id, + ApplicationUtil.getBean(SysDeptNodeType.class)); + if (CollectionUtil.isEmpty(nodeChildIds)) { + continue; + } + + batchIds.addAll(nodeChildIds); + } + + batchIds.addAll(ids); + + this.doBatchEnable(batchIds); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增部门,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysDeptVo vo) { + + SysDept data = this.doCreate(vo); + + this.saveRecursion(data.getId(), data.getParentId()); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改部门,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysDeptVo vo) { + + this.doUpdate(vo); + + this.saveRecursion(vo.getId(), vo.getParentId()); + + OpLogUtil.setVariable("id", vo.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + protected List doSelector() { + + return getBaseMapper().selector(); + } + + protected SysDept doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected void doBatchUnable(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDept.class) + .set(SysDept::getAvailable, Boolean.FALSE).in(SysDept::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected void doBatchEnable(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDept.class) + .set(SysDept::getAvailable, Boolean.TRUE).in(SysDept::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected SysDept doCreate(CreateSysDeptVo vo) { + + //查询Code是否重复 + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + //查询Name是否重复 + checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getName, vo.getName()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysDept parentDept = null; + //如果parentId不为空,查询上级部门是否存在 + if (!StringUtil.isBlank(vo.getParentId())) { + parentDept = this.getById(vo.getParentId()); + if (parentDept == null) { + throw new DefaultClientException("上级部门不存在,请检查!"); + } + } + + SysDept data = new SysDept(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + data.setShortName(vo.getShortName()); + if (!StringUtil.isBlank(vo.getParentId())) { + data.setParentId(vo.getParentId()); + } + data.setAvailable(parentDept == null ? Boolean.TRUE : parentDept.getAvailable()); + data.setDescription(vo.getDescription()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doUpdate(UpdateSysDeptVo vo) { + + SysDept data = this.findById(vo.getId()); + if (data == null) { + throw new DefaultClientException("部门不存在!"); + } + + //查询Code是否重复 + Wrapper checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getCode, vo.getCode()).ne(SysDept::getId, data.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + //查询Name是否重复 + checkWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getName, vo.getName()) + .ne(SysDept::getId, data.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + //如果parentId不为空,查询上级部门是否存在 + if (!StringUtil.isBlank(vo.getParentId())) { + if (ObjectUtil.equals(vo.getParentId(), data.getId())) { + throw new DefaultClientException("上级部门不能是当前部门!"); + } + Wrapper checkParentWrapper = Wrappers.lambdaQuery(SysDept.class) + .eq(SysDept::getId, vo.getParentId()); + if (getBaseMapper().selectCount(checkParentWrapper) == 0) { + throw new DefaultClientException("上级部门不存在,请检查!"); + } + } + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysDept.class) + .set(SysDept::getCode, vo.getCode()).set(SysDept::getName, vo.getName()) + .set(SysDept::getShortName, vo.getShortName()) + .set(SysDept::getParentId, + StringUtil.isBlank(vo.getParentId()) ? null : vo.getParentId()) + .set(SysDept::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(SysDept::getAvailable, vo.getAvailable()).eq(SysDept::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + if (vo.getAvailable()) { + this.batchEnable(Collections.singletonList(vo.getId())); + } else { + this.batchUnable(Collections.singletonList(vo.getId())); + } + } + + /** + * 保存递归信息 + * + * @param deptId + * @param parentId + */ + protected void saveRecursion(String deptId, String parentId) { + + if (!StringUtil.isBlank(parentId)) { + List parentIds = recursionMappingService.getNodeParentIds(parentId, + ApplicationUtil.getBean(SysDeptNodeType.class)); + if (CollectionUtil.isEmpty(parentIds)) { + parentIds = new ArrayList<>(); + } + parentIds.add(parentId); + + recursionMappingService.saveNode(deptId, ApplicationUtil.getBean(SysDeptNodeType.class), + parentIds); + } else { + recursionMappingService.saveNode(deptId, ApplicationUtil.getBean(SysDeptNodeType.class)); + } + } + + @CacheEvict(value = {SysDept.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + deptService.cleanCacheByKey(key); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysMenuServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysMenuServiceImpl.java new file mode 100644 index 0000000..299d8f7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysMenuServiceImpl.java @@ -0,0 +1,443 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.starter.web.components.security.IUserTokenResolver; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.web.utils.SpelUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.inner.dto.MenuDto; +import com.lframework.xingyun.template.inner.enums.system.SysMenuComponentType; +import com.lframework.xingyun.template.inner.enums.system.SysMenuDisplay; +import com.lframework.xingyun.template.inner.vo.system.menu.CreateSysMenuVo; +import com.lframework.xingyun.template.inner.vo.system.menu.SysMenuSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.menu.UpdateSysMenuVo; +import com.lframework.xingyun.template.inner.mappers.system.SysMenuMapper; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 系统菜单 服务实现类 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +@Service +public class SysMenuServiceImpl extends BaseMpServiceImpl implements + SysMenuService { + + private String tokenKey = "X-Auth-Token"; + + @Autowired + private IUserTokenResolver userTokenResolver; + + @Override + public List queryList(List moduleIds) { + + return this.doQuery(moduleIds); + } + + @Override + public List getByRoleId(String roleId, List moduleIds) { + + return this.doGetByRoleId(roleId, moduleIds); + } + + @Cacheable(value = SysMenu.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysMenu findById(@NonNull String id) { + + return this.doGetById(id); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增菜单,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(@NonNull CreateSysMenuVo vo) { + + SysMenu data = this.doCreate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改菜单,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(@NonNull UpdateSysMenuVo vo) { + + SysMenu oriMenu = this.findById(vo.getId()); + + if (!ObjectUtil.equals(vo.getDisplay(), oriMenu.getDisplay().getCode())) { + throw new DefaultClientException("菜单【" + oriMenu.getTitle() + "】" + "不允许更改类型!"); + } + + SysMenu data = this.doUpdate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "删除菜单,ID:{}", params = "#id") + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(@NonNull String id) { + + SysMenu oriMenu = this.findById(id); + + List children = this.doGetChildrenById(id); + if (CollectionUtil.isNotEmpty(children)) { + //如果子节点不为空 + throw new DefaultClientException("菜单【" + oriMenu.getTitle() + "】存在子菜单,无法删除!"); + } + + this.doDeleteById(id); + } + + @Override + public List selector(SysMenuSelectorVo vo, List moduleIds) { + + return this.doSelector(vo, moduleIds); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "启用菜单,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(@NonNull List ids, @NonNull String userId) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + this.doBatchEnable(ids, userId); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "停用菜单,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(@NonNull List ids, @NonNull String userId) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + this.doBatchUnable(ids, userId); + } + + @Override + public Boolean existPermission(String permission) { + Wrapper queryWrapper = Wrappers.lambdaQuery(SysMenu.class) + .eq(SysMenu::getPermission, permission); + return this.count(queryWrapper) > 0; + } + + protected List doQuery(List moduleIds) { + + return getBaseMapper().query(moduleIds); + } + + protected List doGetByRoleId(String roleId, List moduleIds) { + + return getBaseMapper().getByRoleId(roleId, moduleIds); + } + + protected SysMenu doGetById(@NonNull String id) { + + return getBaseMapper().findById(id); + } + + protected SysMenu doCreate(@NonNull CreateSysMenuVo vo) { + + SysMenu data = new SysMenu(); + + data.setId(IdUtil.getId()); + this.setDataForCreate(vo, data); + + getBaseMapper().insert(data); + + return data; + } + + protected SysMenu doUpdate(@NonNull UpdateSysMenuVo vo) { + + SysMenu data = new SysMenu(); + + data.setId(vo.getId()); + + this.setDataForCreate(vo, data); + + data.setAvailable(vo.getAvailable()); + + SysMenuService thisService = getThis(this.getClass()); + + SysMenu record = thisService.findById(vo.getId()); + + data.setIsSpecial(record.getIsSpecial()); + + getBaseMapper().deleteById(vo.getId()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doDeleteById(@NonNull String id) { + + getBaseMapper().deleteById(id); + } + + protected List doSelector(SysMenuSelectorVo vo, List moduleIds) { + + return getBaseMapper().selector(vo, moduleIds); + } + + protected void doBatchEnable(@NonNull List ids, @NonNull String userId) { + + Wrapper wrapper = Wrappers.lambdaUpdate(SysMenu.class) + .set(SysMenu::getAvailable, Boolean.TRUE).in(SysMenu::getId, ids); + getBaseMapper().update(new SysMenu(), wrapper); + } + + protected void doBatchUnable(@NonNull List ids, @NonNull String userId) { + + Wrapper wrapper = Wrappers.lambdaUpdate(SysMenu.class) + .set(SysMenu::getAvailable, Boolean.FALSE).in(SysMenu::getId, ids); + getBaseMapper().update(new SysMenu(), wrapper); + } + + protected void setDataForCreate(@NonNull CreateSysMenuVo vo, @NonNull SysMenu data) { + + SysMenuDisplay sysMenuDisplay = EnumUtil.getByCode(SysMenuDisplay.class, vo.getDisplay()); + + SysMenu parentMenu = null; + if (!StringUtil.isBlank(vo.getParentId())) { + parentMenu = this.findById(vo.getParentId()); + if (parentMenu == null) { + throw new DefaultClientException("父级菜单不存在!"); + } + if (parentMenu.getId().equals(data.getId())) { + throw new DefaultClientException("父级菜单不能是当前菜单!"); + } + } + data.setCode(vo.getCode()); + data.setTitle(vo.getTitle()); + // fix 这里需要用null代替空字符串 + data.setParentId(parentMenu == null ? null: parentMenu.getId()); + data.setDisplay(sysMenuDisplay); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + if (sysMenuDisplay == SysMenuDisplay.CATALOG || sysMenuDisplay == SysMenuDisplay.FUNCTION) { + if (parentMenu != null) { + //父级菜单必须是目录 + if (parentMenu.getDisplay() != SysMenuDisplay.CATALOG) { + throw new DefaultClientException( + "父级菜单类型必须是【" + SysMenuDisplay.CATALOG.getDesc() + "】!"); + } + } + + data.setName(vo.getName()); + data.setIcon(vo.getIcon()); + data.setPath(vo.getPath()); + data.setHidden(vo.getHidden()); + + if (sysMenuDisplay == SysMenuDisplay.FUNCTION) { + // 功能必须有parentId + if (parentMenu == null) { + throw new DefaultClientException( + "此菜单类型是【" + SysMenuDisplay.FUNCTION.getDesc() + "】,父级菜单不能为空!"); + } + data.setComponent(vo.getComponent()); + data.setComponentType( + EnumUtil.getByCode(SysMenuComponentType.class, vo.getComponentType())); + data.setNoCache(vo.getNoCache()); + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + data.setPermission(vo.getPermission()); + } + } else if (sysMenuDisplay == SysMenuDisplay.PERMISSION) { + + if (parentMenu != null) { + //父级菜单必须是目录 + if (parentMenu.getDisplay() != SysMenuDisplay.FUNCTION) { + throw new DefaultClientException( + "父级菜单类型必须是【" + SysMenuDisplay.FUNCTION.getDesc() + "】!"); + } + } else { + throw new DefaultClientException( + "此菜单类型是【" + SysMenuDisplay.PERMISSION.getDesc() + "】,父级菜单不能为空!"); + } + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + data.setPermission(vo.getPermission()); + } + } + + protected List doGetChildrenById(String id) { + + return getBaseMapper().getChildrenById(id); + } + + @Override + public List getMenuByUserId(String userId, boolean isAdmin, List moduleIds) { + + List menus = this.doGetMenus(userId, isAdmin, moduleIds); + + List collectionMenuIds = this.doGetCollectMenuIds(userId); + + if (!CollectionUtil.isEmpty(menus)) { + // 用env渲染${xxx}属性 + menus.forEach(menu -> { + menu.setPath(ApplicationUtil.resolvePlaceholders(menu.getPath())); + }); + + // 渲染spel表达式 + Map vars = getDefaultVars(); + menus.stream().filter(menu -> this.hasSpecExpression(menu.getPath())).forEach(menu -> { + List expressions = this.getAllExpressions(menu.getPath()); + if (!CollectionUtil.isEmpty(expressions)) { + String oriPath = menu.getPath(); + for (String expression : expressions) { + Object parsed = SpelUtil.parse(expression.replaceAll("\\{", "").replaceAll("}", ""), + vars); + oriPath = oriPath.replace(expression, parsed == null ? "" : String.valueOf(parsed)); + } + + menu.setPath(oriPath); + } + }); + + if (!CollectionUtil.isEmpty(collectionMenuIds)) { + menus.forEach(menu -> { + menu.setIsCollect(collectionMenuIds.contains(menu.getId())); + }); + } + } + + return menus; + } + + @Override + public Set getPermissionsByUserId(String userId, boolean isAdmin, List moduleIds) { + + return getBaseMapper().getPermissionsByUserId(userId, isAdmin, moduleIds); + } + + @Override + public Set getRolePermissionByUserId(String userId) { + return getBaseMapper().getRolePermissionByUserId(userId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void collect(String userId, String menuId) { + + if (StringUtil.isBlank(userId) || StringUtil.isBlank(menuId)) { + return; + } + + this.cancelCollect(userId, menuId); + + getBaseMapper().collectMenu(IdUtil.getId(), userId, menuId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void cancelCollect(String userId, String menuId) { + + if (StringUtil.isBlank(userId) || StringUtil.isBlank(menuId)) { + return; + } + + getBaseMapper().cancelCollectMenu(userId, menuId); + } + + private List getAllExpressions(String s) { + + if (!this.hasSpecExpression(s)) { + return null; + } + + List results = new ArrayList<>(); + String[] arr = s.split("#\\{"); + for (int i = 1; i < arr.length; i++) { + if (!arr[i].contains("}")) { + continue; + } + results.add("#{" + arr[i].substring(0, arr[i].indexOf("}")) + "}"); + } + + return results; + } + + private boolean hasSpecExpression(String s) { + + return RegUtil.isMatch(Pattern.compile("^.*#\\{.*}.*$"), s); + } + + protected Map getDefaultVars() { + + Map vars = new HashMap<>(); + + vars.put("_token", userTokenResolver.getToken()); + vars.put("_fullToken", userTokenResolver.getFullToken()); + vars.put("_tokenKey", tokenKey); + + return vars; + } + + protected List doGetMenus(String userId, boolean isAdmin, List moduleIds) { + + return getBaseMapper().getMenuByUserId(userId, isAdmin, moduleIds); + } + + protected List doGetCollectMenuIds(String userId) { + + return getBaseMapper().getCollectMenuIds(userId); + } + + @CacheEvict(value = SysMenu.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeLogServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeLogServiceImpl.java new file mode 100644 index 0000000..1d66064 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeLogServiceImpl.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.xingyun.template.inner.mappers.system.SysNoticeLogMapper; +import com.lframework.xingyun.template.inner.entity.SysNoticeLog; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.inner.service.system.SysNoticeLogService; +import java.time.LocalDateTime; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysNoticeLogServiceImpl extends + BaseMpServiceImpl implements SysNoticeLogService { + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean setReaded(String noticeId, String userId) { + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysNoticeLog.class) + .eq(SysNoticeLog::getNoticeId, noticeId).eq(SysNoticeLog::getUserId, userId) + .eq(SysNoticeLog::getReaded, Boolean.FALSE).set(SysNoticeLog::getReaded, Boolean.TRUE) + .set(SysNoticeLog::getReadTime, + LocalDateTime.now()); + + return this.update(updateWrapper); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeServiceImpl.java new file mode 100644 index 0000000..6c1f966 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysNoticeServiceImpl.java @@ -0,0 +1,259 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.ThreadUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.common.threads.DefaultRunnable; +import com.lframework.starter.web.dto.WsPushData; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.starter.websocket.components.WsDataPusher; +import com.lframework.starter.websocket.events.UserConnectEvent; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.xingyun.template.inner.dto.system.notice.SysNoticeDto; +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.xingyun.template.inner.entity.SysNoticeLog; +import com.lframework.xingyun.template.inner.vo.system.notice.CreateSysNoticeVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeVo; +import com.lframework.xingyun.template.inner.vo.system.notice.UpdateSysNoticeVo; +import com.lframework.xingyun.template.inner.mappers.system.SysNoticeMapper; +import com.lframework.xingyun.template.inner.service.system.SysNoticeLogService; +import com.lframework.xingyun.template.inner.service.system.SysNoticeService; +import com.lframework.xingyun.template.inner.service.system.SysUserService; +import com.lframework.xingyun.template.inner.vo.system.user.QuerySysUserVo; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysNoticeServiceImpl extends BaseMpServiceImpl implements + SysNoticeService { + + @Autowired + private SysUserService sysUserService; + + @Autowired + private SysNoticeLogService sysNoticeLogService; + + @Autowired + private WsDataPusher wsDataPusher; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, QuerySysNoticeVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysNoticeVo vo) { + + return getBaseMapper().query(vo); + } + + @Override + public PageResult queryByUser(Integer pageIndex, Integer pageSize, + QuerySysNoticeByUserVo vo) { + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = getBaseMapper().queryByUser(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysNotice.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysNoticeDto getContent(String id) { + SysNotice record = getBaseMapper().selectById(id); + if (record == null) { + return null; + } + + return new SysNoticeDto(record); + } + + @Override + public SysNotice findById(String id) { + + return getBaseMapper().selectById(id); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增系统通知,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysNoticeVo vo) { + + SysNotice data = new SysNotice(); + data.setId(IdUtil.getId()); + data.setTitle(vo.getTitle()); + data.setContent(vo.getContent()); + data.setPublished(vo.getPublished()); + + getBaseMapper().insert(data); + + if (vo.getPublished()) { + ThreadUtil.execAsync(new DefaultRunnable(() -> { + SysNoticeService thisService = getThis(getClass()); + thisService.publish(data.getId()); + })); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改系统通知,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysNoticeVo vo) { + + SysNotice data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("系统通知不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysNotice.class) + .set(SysNotice::getTitle, vo.getTitle()).set(SysNotice::getContent, vo.getContent()) + .set(SysNotice::getAvailable, vo.getAvailable()) + .set(SysNotice::getPublished, vo.getPublished()).set(SysNotice::getPublishTime, null) + .set(SysNotice::getReadedNum, 0).set(SysNotice::getUnReadNum, 0) + .eq(SysNotice::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + // 无论发布还是不发布 都要删除 + Wrapper deleteLogWrapper = Wrappers.lambdaQuery(SysNoticeLog.class) + .eq(SysNoticeLog::getNoticeId, data.getId()); + sysNoticeLogService.remove(deleteLogWrapper); + + if (vo.getPublished()) { + ThreadUtil.execAsync(new DefaultRunnable(() -> { + SysNoticeService thisService = getThis(getClass()); + thisService.publish(data.getId()); + })); + } + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "发布系统通知,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void publish(String id) { + + // 查询所有用户 + QuerySysUserVo querySysUserVo = new QuerySysUserVo(); + querySysUserVo.setAvailable(true); + List users = sysUserService.query(querySysUserVo); + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysNotice.class) + .eq(SysNotice::getId, id).set(SysNotice::getReadedNum, 0) + .set(SysNotice::getUnReadNum, users.size()).set(SysNotice::getPublished, Boolean.TRUE) + .set(SysNotice::getPublishTime, LocalDateTime.now()); + this.update(updateWrapper); + + Wrapper deleteLogWrapper = Wrappers.lambdaQuery(SysNoticeLog.class) + .eq(SysNoticeLog::getNoticeId, id); + sysNoticeLogService.remove(deleteLogWrapper); + + if (!CollectionUtil.isEmpty(users)) { + List logs = users.stream().map(t -> { + SysNoticeLog log = new SysNoticeLog(); + log.setId(IdUtil.getId()); + log.setNoticeId(id); + log.setUserId(t.getId()); + log.setReaded(Boolean.FALSE); + + return log; + }).collect(Collectors.toList()); + + sysNoticeLogService.saveBatch(logs); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void setReaded(String id, String userId) { + if (sysNoticeLogService.setReaded(id, userId)) { + getBaseMapper().setReaded(id); + } + } + + @Override + public void noticeForWs() { + WsPushData pushData = new WsPushData(); + pushData.setBizType("sysNotice"); + pushData.setAll(Boolean.TRUE); + + wsDataPusher.push(pushData); + } + + @Override + public void noticeForWs(String userId) { + WsPushData pushData = new WsPushData(); + pushData.setBizType("sysNotice"); + pushData.setIncludeUserId(userId); + + wsDataPusher.push(pushData); + } + + @Override + public void noticeForWsWithSessionId(String sessionId) { + WsPushData pushData = new WsPushData(); + pushData.setBizType("sysNotice"); + pushData.setIncludeSessionIds(Collections.singletonList(sessionId)); + + wsDataPusher.push(pushData); + } + + @CacheEvict(value = SysNotice.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } + + @Component + public static class ReloadNoticeListener implements ApplicationListener { + + @Autowired + private SysNoticeService sysNoticeService; + + @Override + public void onApplicationEvent(UserConnectEvent event) { + sysNoticeService.noticeForWsWithSessionId(event.getSessionId()); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysOpenDomainServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysOpenDomainServiceImpl.java new file mode 100644 index 0000000..0dd1c27 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysOpenDomainServiceImpl.java @@ -0,0 +1,113 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.xingyun.template.inner.mappers.system.SysOpenDomainMapper; +import com.lframework.xingyun.template.inner.service.system.SysOpenDomainService; +import com.lframework.xingyun.template.inner.vo.system.open.CreateSysOpenDomainVo; +import com.lframework.xingyun.template.inner.vo.system.open.QuerySysOpenDomainVo; +import com.lframework.xingyun.template.inner.vo.system.open.SysOpenDomainSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.open.UpdateSysOpenDomainSecretVo; +import com.lframework.xingyun.template.inner.vo.system.open.UpdateSysOpenDomainVo; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@DS("master") +@Service +public class SysOpenDomainServiceImpl extends + BaseMpServiceImpl + implements SysOpenDomainService { + + @Override + public PageResult query(QuerySysOpenDomainVo vo) { + PageHelperUtil.startPage(vo); + List datas = getBaseMapper().query(vo); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public PageResult selector(SysOpenDomainSelectorVo vo) { + PageHelperUtil.startPage(vo); + List datas = getBaseMapper().selector(vo); + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysOpenDomain.CACHE_NAME, key = "#id", unless = "#result == null") + @Override + public SysOpenDomain findById(Integer id) { + return this.getById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysOpenDomainVo vo) { + SysOpenDomain data = new SysOpenDomain(); + data.setName(vo.getName()); + data.setApiSecret(vo.getApiSecret()); + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + if (vo.getTenantId() != null) { + data.setTenantId(vo.getTenantId()); + } + + this.save(data); + + return data.getId(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysOpenDomainVo vo) { + + SysOpenDomain record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("开放域不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysOpenDomain.class) + .set(SysOpenDomain::getName, vo.getName()) + .set(SysOpenDomain::getAvailable, vo.getAvailable()) + .set(SysOpenDomain::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .set(SysOpenDomain::getTenantId, vo.getTenantId() == null ? null : vo.getTenantId()) + .eq(SysOpenDomain::getId, vo.getId()); + + this.update(updateWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateApiSecret(UpdateSysOpenDomainSecretVo vo) { + SysOpenDomain record = this.getById(vo.getId()); + if (record == null) { + throw new DefaultClientException("开放域不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysOpenDomain.class) + .set(SysOpenDomain::getApiSecret, vo.getApiSecret()) + .eq(SysOpenDomain::getId, vo.getId()); + + this.update(updateWrapper); + } + + @CacheEvict(value = SysOpenDomain.CACHE_NAME, key = "#key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysParameterServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysParameterServiceImpl.java new file mode 100644 index 0000000..e279c06 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysParameterServiceImpl.java @@ -0,0 +1,197 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.exceptions.impl.ParameterNotFoundException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.inner.entity.SysParameter; +import com.lframework.xingyun.template.inner.vo.system.parameter.CreateSysParameterVo; +import com.lframework.xingyun.template.inner.vo.system.parameter.QuerySysParameterVo; +import com.lframework.xingyun.template.inner.vo.system.parameter.UpdateSysParameterVo; +import com.lframework.xingyun.template.inner.mappers.system.SysParameterMapper; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.inner.service.system.SysParameterService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysParameterServiceImpl extends + BaseMpServiceImpl implements SysParameterService, + com.lframework.starter.web.service.SysParameterService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysParameterVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysParameterVo vo) { + + return getBaseMapper().query(vo); + } + + @Cacheable(value = SysParameter.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysParameter findById(Long id) { + + return getBaseMapper().selectById(id); + } + + @Cacheable(value = SysParameter.CACHE_NAME, key = "@cacheVariables.tenantId() + #key", unless = "#result == null") + @Override + public String findByKey(String key) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysParameter.class) + .eq(SysParameter::getPmKey, key); + SysParameter data = getBaseMapper().selectOne(queryWrapper); + + return data == null ? null : data.getPmValue(); + } + + @Override + public String findRequiredByKey(String key) throws ParameterNotFoundException { + com.lframework.starter.web.service.SysParameterService thisService = getThis(this.getClass()); + String data = thisService.findByKey(key); + if (data == null) { + throw new ParameterNotFoundException(); + } + + return data; + } + + @Override + public String findByKey(String key, String defaultValue) { + com.lframework.starter.web.service.SysParameterService thisService = getThis(this.getClass()); + String data = thisService.findByKey(key); + if (data == null) { + return defaultValue; + } + + return data; + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增系统参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public Long create(CreateSysParameterVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysParameter.class) + .eq(SysParameter::getPmKey, vo.getPmKey()); + if (this.count(checkWrapper) > 0) { + throw new DefaultClientException("键重复,请重新输入!"); + } + SysParameter data = new SysParameter(); + data.setPmKey(vo.getPmKey()); + if (!StringUtil.isEmpty(vo.getPmValue())) { + data.setPmValue(vo.getPmValue()); + } + if (!StringUtil.isBlank(vo.getDescription())) { + data.setDescription(vo.getDescription()); + } + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改系统参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysParameterVo vo) { + + SysParameter data = getBaseMapper().selectById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("系统参数不存在!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysParameter.class) + .set(SysParameter::getPmValue, StringUtil.isBlank(vo.getPmValue()) ? null : vo.getPmValue()) + .set(SysParameter::getDescription, + StringUtil.isBlank(vo.getDescription()) ? null : vo.getDescription()) + .eq(SysParameter::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("id", String.valueOf(data.getId())); + OpLogUtil.setExtra(vo); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "删除系统参数,ID:{}", params = {"#id"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(Long id) { + + getBaseMapper().deleteById(id); + } + + @Override + public Boolean getBoolean(String key) { + com.lframework.starter.web.service.SysParameterService thisService = getThis(getClass()); + String value = thisService.findByKey(key); + return value == null ? null : "true".equalsIgnoreCase(value); + } + + @Override + public Boolean getBoolean(String key, Boolean defaultValue) { + Boolean value = getBoolean(key); + if (value == null) { + return defaultValue; + } + + return value; + } + + @Override + public Integer getInteger(String key) { + com.lframework.starter.web.service.SysParameterService thisService = getThis(getClass()); + String value = thisService.findByKey(key); + try { + return value == null ? null : Integer.valueOf(value); + } catch (NumberFormatException e) { + // 转换失败 + return null; + } + } + + @Override + public Integer getInteger(String key, Integer defaultValue) { + Integer value = getInteger(key); + if (value == null) { + return defaultValue; + } + + return value; + } + + @CacheEvict(value = SysParameter.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysPositionServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysPositionServiceImpl.java new file mode 100644 index 0000000..5927619 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysPositionServiceImpl.java @@ -0,0 +1,219 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.xingyun.template.inner.vo.system.position.CreateSysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.QuerySysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.SysPositionSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.position.UpdateSysPositionVo; +import com.lframework.xingyun.template.inner.mappers.system.SysPositionMapper; +import com.lframework.xingyun.template.inner.service.system.SysPositionService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysPositionServiceImpl extends + BaseMpServiceImpl implements SysPositionService { + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysPositionVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doQuery(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Cacheable(value = SysPosition.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysPosition findById(String id) { + + return this.doGetById(id); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysPositionSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doSelector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "停用岗位,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + this.doBatchUnable(ids); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "启用岗位,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + this.doBatchEnable(ids); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增岗位,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysPositionVo vo) { + + SysPosition data = this.doCreate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改岗位,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysPositionVo vo) { + + this.doUpdate(vo); + + OpLogUtil.setVariable("id", vo.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + protected List doQuery(QuerySysPositionVo vo) { + + return getBaseMapper().query(vo); + } + + protected SysPosition doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected List doSelector(SysPositionSelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + protected void doBatchUnable(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysPosition.class) + .set(SysPosition::getAvailable, Boolean.FALSE).in(SysPosition::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected void doBatchEnable(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysPosition.class) + .set(SysPosition::getAvailable, Boolean.TRUE).in(SysPosition::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected SysPosition doCreate(CreateSysPositionVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysPosition.class) + .eq(SysPosition::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysPosition.class) + .eq(SysPosition::getName, vo.getName()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysPosition data = new SysPosition(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doUpdate(UpdateSysPositionVo vo) { + + SysPosition data = this.findById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("岗位不存在!"); + } + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysPosition.class) + .eq(SysPosition::getCode, vo.getCode()).ne(SysPosition::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysPosition.class) + .eq(SysPosition::getName, vo.getName()) + .ne(SysPosition::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate( + SysPosition.class) + .set(SysPosition::getCode, vo.getCode()) + .set(SysPosition::getName, vo.getName()) + .set(SysPosition::getAvailable, vo.getAvailable()) + .set(SysPosition::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(SysPosition::getId, vo.getId()); + + getBaseMapper().update(updateWrapper); + } + + @CacheEvict(value = SysPosition.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleMenuServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleMenuServiceImpl.java new file mode 100644 index 0000000..610e0c5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleMenuServiceImpl.java @@ -0,0 +1,80 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.inner.entity.SysRoleMenu; +import com.lframework.xingyun.template.inner.mappers.system.SysRoleMenuMapper; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.inner.service.system.SysRoleMenuService; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleMenuSettingVo; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysRoleMenuServiceImpl extends + BaseMpServiceImpl implements SysRoleMenuService { + + @Autowired + private SysRoleService sysRoleService; + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "角色授权菜单,角色ID:{},菜单ID:{}", params = {"#vo.roleIds", + "#vo.menuIds"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysRoleMenuSettingVo vo) { + + for (String roleId : vo.getRoleIds()) { + SysRole role = sysRoleService.findById(roleId); + if (ObjectUtil.isNull(role)) { + throw new DefaultClientException("角色不存在!"); + } + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(role.getPermission())) { + throw new DefaultClientException( + "角色【" + role.getName() + "】的权限为【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】,不允许授权!"); + } + + this.doSetting(roleId, vo.getMenuIds()); + } + } + + protected void doSetting(String roleId, List menuIds) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysRoleMenu.class) + .eq(SysRoleMenu::getRoleId, roleId); + getBaseMapper().delete(deleteWrapper); + + List records = new ArrayList<>(); + if (!CollectionUtil.isEmpty(menuIds)) { + Set menuIdSet = new HashSet<>(menuIds); + + for (String menuId : menuIdSet) { + SysRoleMenu record = new SysRoleMenu(); + record.setId(IdUtil.getId()); + record.setRoleId(roleId); + record.setMenuId(menuId); + + records.add(record); + } + } + + if (CollectionUtil.isNotEmpty(records)) { + this.saveBatch(records); + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleServiceImpl.java new file mode 100644 index 0000000..c0241ee --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysRoleServiceImpl.java @@ -0,0 +1,299 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.common.security.SecurityConstants; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.inner.service.system.SysMenuService; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.mappers.system.SysRoleMapper; +import com.lframework.xingyun.template.inner.vo.system.role.CreateSysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.role.UpdateSysRoleVo; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysRoleServiceImpl extends BaseMpServiceImpl implements + SysRoleService { + + @Autowired + private SysMenuService sysMenuService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysRoleVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysRoleVo vo) { + + return this.doQuery(vo); + } + + @Cacheable(value = SysRole.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysRole findById(String id) { + + return this.doGetById(id); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysRoleSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List datas = this.doSelector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "停用角色,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (String id : ids) { + SysRole role = this.findById(id); + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(role.getPermission())) { + throw new DefaultClientException( + "角色【" + role.getName() + "】的权限为【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】,不允许停用!"); + } + } + + this.doBatchUnable(ids); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "启用角色,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(Collection ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + for (String id : ids) { + SysRole role = this.findById(id); + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(role.getPermission())) { + throw new DefaultClientException( + "角色【" + role.getName() + "】的权限为【" + SecurityConstants.PERMISSION_ADMIN_NAME + + "】,不允许启用!"); + } + } + + this.doBatchEnable(ids); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增角色,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysRoleVo vo) { + + if (!StringUtil.isBlank(vo.getPermission())) { + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + // 这里的权限不能与菜单权限重复 + if (sysMenuService.existPermission(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + vo.getPermission() + "】为菜单权限,请修改!"); + } + } + + SysRole data = this.doCreate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return data.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改角色,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysRoleVo vo) { + + SysRole data = this.findById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("角色不存在!"); + } + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(data.getPermission())) { + throw new DefaultClientException("角色【" + data.getName() + "】为内置角色,不允许修改!"); + } + + if (!StringUtil.isBlank(vo.getPermission())) { + + if (SecurityConstants.PERMISSION_ADMIN_NAME.equals(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + SecurityConstants.PERMISSION_ADMIN_NAME + "】为内置权限,请修改!"); + } + + // 这里的权限不能与菜单权限重复 + if (sysMenuService.existPermission(vo.getPermission())) { + throw new DefaultClientException( + "权限【" + vo.getPermission() + "】为菜单权限,请修改!"); + } + } + + this.doUpdate(vo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public List getByUserId(String userId) { + + return this.doGetByUserId(userId); + } + + protected List doQuery(QuerySysRoleVo vo) { + + return getBaseMapper().query(vo); + } + + protected SysRole doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected List doSelector(SysRoleSelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + protected void doBatchUnable(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysRole.class) + .set(SysRole::getAvailable, Boolean.FALSE).in(SysRole::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected void doBatchEnable(Collection ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysRole.class) + .set(SysRole::getAvailable, Boolean.TRUE).in(SysRole::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected SysRole doCreate(CreateSysRoleVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getName, vo.getName()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + SysRole data = new SysRole(); + data.setId(IdUtil.getId()); + data.setCode(vo.getCode()); + data.setName(vo.getName()); + + if (!StringUtil.isBlank(vo.getPermission())) { + + data.setPermission(vo.getPermission()); + } + + data.setAvailable(Boolean.TRUE); + data.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(data); + + return data; + } + + protected void doUpdate(UpdateSysRoleVo vo) { + + Wrapper checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getCode, vo.getCode()).ne(SysRole::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + checkWrapper = Wrappers.lambdaQuery(SysRole.class) + .eq(SysRole::getName, vo.getName()) + .ne(SysRole::getId, vo.getId()); + if (getBaseMapper().selectCount(checkWrapper) > 0) { + throw new DefaultClientException("名称重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysRole.class) + .set(SysRole::getCode, vo.getCode()).set(SysRole::getName, vo.getName()) + .set(SysRole::getPermission, null) + .set(SysRole::getAvailable, vo.getAvailable()) + .set(SysRole::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()) + .eq(SysRole::getId, vo.getId()); + + if (!StringUtil.isBlank(vo.getPermission())) { + + updateWrapper.set(SysRole::getPermission, vo.getPermission()); + } + + getBaseMapper().update(updateWrapper); + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } + + @CacheEvict(value = SysRole.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserDeptServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserDeptServiceImpl.java new file mode 100644 index 0000000..ba2589d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserDeptServiceImpl.java @@ -0,0 +1,83 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.inner.vo.system.dept.SysUserDeptSettingVo; +import com.lframework.xingyun.template.inner.mappers.system.SysUserDeptMapper; +import com.lframework.xingyun.template.inner.entity.SysUserDept; +import com.lframework.xingyun.template.inner.service.system.SysUserDeptService; +import java.io.Serializable; +import java.util.List; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysUserDeptServiceImpl extends + BaseMpServiceImpl implements SysUserDeptService { + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "用户设置部门,用户ID:{},部门ID:{}", params = {"#vo.userId", + "#vo.positionId"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysUserDeptSettingVo vo) { + + this.doSetting(vo); + + SysUserDeptService thisService = getThis(this.getClass()); + thisService.cleanCacheByKey(vo.getUserId()); + } + + @Cacheable(value = SysUserDept.CACHE_NAME, key = "@cacheVariables.tenantId() + #userId") + @Override + public List getByUserId(String userId) { + + return doGetByUserId(userId); + } + + @Override + public Boolean hasByDeptId(String deptId) { + + return doHasByDeptId(deptId); + } + + protected void doSetting(SysUserDeptSettingVo vo) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserDept.class) + .eq(SysUserDept::getUserId, vo.getUserId()); + getBaseMapper().delete(deleteWrapper); + + if (!CollectionUtil.isEmpty(vo.getDeptIds())) { + for (String deptId : vo.getDeptIds()) { + SysUserDept record = new SysUserDept(); + record.setId(IdUtil.getId()); + record.setUserId(vo.getUserId()); + record.setDeptId(deptId); + + getBaseMapper().insert(record); + } + } + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } + + protected Boolean doHasByDeptId(String deptId) { + + return getBaseMapper().hasByDeptId(deptId) != null; + } + + @CacheEvict(value = SysUserDept.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserPositionServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserPositionServiceImpl.java new file mode 100644 index 0000000..5e22c4c --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserPositionServiceImpl.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.inner.vo.system.position.SysUserPositionSettingVo; +import com.lframework.xingyun.template.inner.mappers.system.SysUserPositionMapper; +import com.lframework.xingyun.template.inner.entity.SysUserPosition; +import com.lframework.xingyun.template.inner.service.system.SysUserPositionService; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysUserPositionServiceImpl + extends BaseMpServiceImpl + implements SysUserPositionService { + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "用户设置岗位,用户ID:{},岗位ID:{}", params = {"#vo.userId", + "#vo.positionIds"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysUserPositionSettingVo vo) { + + this.doSetting(vo); + } + + @Override + public List getByUserId(String userId) { + + return doGetByUserId(userId); + } + + protected void doSetting(SysUserPositionSettingVo vo) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery( + SysUserPosition.class) + .eq(SysUserPosition::getUserId, vo.getUserId()); + getBaseMapper().delete(deleteWrapper); + + if (!CollectionUtil.isEmpty(vo.getPositionIds())) { + for (String positionId : vo.getPositionIds()) { + SysUserPosition record = new SysUserPosition(); + record.setId(IdUtil.getId()); + record.setUserId(vo.getUserId()); + record.setPositionId(positionId); + + getBaseMapper().insert(record); + } + } + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserRoleServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserRoleServiceImpl.java new file mode 100644 index 0000000..370b4c2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserRoleServiceImpl.java @@ -0,0 +1,79 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.inner.entity.SysUserRole; +import com.lframework.xingyun.template.inner.mappers.system.SysUserRoleMapper; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.inner.service.system.SysRoleService; +import com.lframework.xingyun.template.inner.service.system.SysUserRoleService; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserRoleSettingVo; +import com.lframework.starter.web.utils.IdUtil; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysUserRoleServiceImpl extends + BaseMpServiceImpl + implements SysUserRoleService { + + @Autowired + private SysRoleService sysRoleService; + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "用户授权角色,用户ID:{},角色ID:{}", params = {"#vo.userIds", + "#vo.roleIds"}, loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void setting(SysUserRoleSettingVo vo) { + + for (String userId : vo.getUserIds()) { + this.doSetting(userId, vo.getRoleIds()); + } + } + + @Override + public List getByUserId(String userId) { + + return doGetByUserId(userId); + } + + protected void doSetting(String userId, List roleIds) { + + Wrapper deleteWrapper = Wrappers.lambdaQuery(SysUserRole.class) + .eq(SysUserRole::getUserId, userId); + getBaseMapper().delete(deleteWrapper); + + if (!CollectionUtil.isEmpty(roleIds)) { + Set roleIdSet = new HashSet<>(roleIds); + + for (String roleId : roleIdSet) { + SysRole role = sysRoleService.findById(roleId); + if (ObjectUtil.isNull(role)) { + throw new DefaultClientException("角色不存在,请检查!"); + } + + SysUserRole record = new SysUserRole(); + record.setId(IdUtil.getId()); + record.setUserId(userId); + record.setRoleId(role.getId()); + + getBaseMapper().insert(record); + } + } + } + + protected List doGetByUserId(String userId) { + + return getBaseMapper().getByUserId(userId); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserServiceImpl.java new file mode 100644 index 0000000..30a537d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserServiceImpl.java @@ -0,0 +1,468 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.common.exceptions.impl.DefaultClientException; +import com.lframework.starter.common.utils.Assert; +import com.lframework.starter.common.utils.CollectionUtil; +import com.lframework.starter.common.utils.ObjectUtil; +import com.lframework.starter.common.utils.RegUtil; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.utils.PageHelperUtil; +import com.lframework.starter.web.utils.PageResultUtil; +import com.lframework.starter.web.components.code.GenerateCodeType; +import com.lframework.starter.web.components.generator.impl.AbstractFlowGenerator; +import com.lframework.starter.web.components.security.PasswordEncoderWrapper; +import com.lframework.xingyun.template.core.enums.Gender; +import com.lframework.xingyun.template.inner.dto.UserInfoDto; +import com.lframework.starter.web.service.GenerateCodeService; +import com.lframework.starter.web.utils.EnumUtil; +import com.lframework.starter.web.utils.IdUtil; +import com.lframework.xingyun.template.core.annotations.OpLog; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.service.UserService; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.inner.events.UpdateUserEvent; +import com.lframework.xingyun.template.inner.vo.system.dept.SysUserDeptSettingVo; +import com.lframework.xingyun.template.inner.vo.system.position.SysUserPositionSettingVo; +import com.lframework.xingyun.template.inner.mappers.system.SysUserMapper; +import com.lframework.xingyun.template.inner.service.system.SysUserDeptService; +import com.lframework.xingyun.template.inner.service.system.SysUserPositionService; +import com.lframework.xingyun.template.inner.service.system.SysUserRoleService; +import com.lframework.xingyun.template.inner.service.system.SysUserService; +import com.lframework.xingyun.template.inner.vo.system.user.CreateSysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.QuerySysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.RegistUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserRoleSettingVo; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.user.UpdateSysUserVo; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SysUserServiceImpl extends BaseMpServiceImpl implements + SysUserService, ApplicationListener { + + @Autowired + private PasswordEncoderWrapper encoderWrapper; + + @Autowired + private SysUserPositionService sysUserPositionService; + + @Autowired + private SysUserDeptService sysUserDeptService; + + @Autowired + private SysUserRoleService sysUserRoleService; + + @Autowired + private GenerateCodeService generateCodeService; + + @Autowired + private UserService userService; + + @Override + public PageResult query(Integer pageIndex, Integer pageSize, + QuerySysUserVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doQuery(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Override + public List query(QuerySysUserVo vo) { + + return this.doQuery(vo); + } + + @Cacheable(value = SysUser.CACHE_NAME, key = "@cacheVariables.tenantId() + #id", unless = "#result == null") + @Override + public SysUser findById(String id) { + + return this.doGetById(id); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "启用用户,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchEnable(List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + this.doBatchEnable(ids); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "停用用户,ID:{}", params = "#ids", loopFormat = true) + @Transactional(rollbackFor = Exception.class) + @Override + public void batchUnable(List ids) { + + if (CollectionUtil.isEmpty(ids)) { + return; + } + + this.doBatchUnable(ids); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "新增用户,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public String create(CreateSysUserVo vo) { + + SysUser record = this.doCreate(vo); + + SysUserPositionSettingVo positionSettingVo = new SysUserPositionSettingVo(); + positionSettingVo.setUserId(record.getId()); + positionSettingVo.setPositionIds(vo.getPositionIds()); + sysUserPositionService.setting(positionSettingVo); + + SysUserDeptSettingVo deptSettingVo = new SysUserDeptSettingVo(); + deptSettingVo.setUserId(record.getId()); + deptSettingVo.setDeptIds(vo.getDeptIds()); + sysUserDeptService.setting(deptSettingVo); + + SysUserRoleSettingVo roleSettingVo = new SysUserRoleSettingVo(); + roleSettingVo.setUserIds(Collections.singletonList(record.getId())); + roleSettingVo.setRoleIds(vo.getRoleIds()); + sysUserRoleService.setting(roleSettingVo); + + OpLogUtil.setVariable("id", record.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + + return record.getId(); + } + + @OpLog(type = DefaultOpLogType.SYSTEM, name = "修改用户,ID:{}, 编号:{}", params = {"#id", "#code"}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(UpdateSysUserVo vo) { + + SysUser data = this.findById(vo.getId()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("用户不存在!"); + } + + if (!StringUtil.isBlank(vo.getPassword())) { + if (!RegUtil.isMatch(PatternPool.PATTERN_PASSWORD, vo.getPassword())) { + throw new DefaultClientException("密码长度必须为5-16位,只允许包含大写字母、小写字母、数字、下划线!"); + } + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + if (!RegUtil.isMatch(PatternPool.PATTERN_CN_TEL, vo.getTelephone())) { + throw new DefaultClientException("联系电话格式不正确!"); + } + } + + this.doUpdate(vo); + + SysUserPositionSettingVo positionSettingVo = new SysUserPositionSettingVo(); + positionSettingVo.setUserId(vo.getId()); + positionSettingVo.setPositionIds(vo.getPositionIds()); + + sysUserPositionService.setting(positionSettingVo); + + SysUserDeptSettingVo deptSettingVo = new SysUserDeptSettingVo(); + deptSettingVo.setUserId(vo.getId()); + deptSettingVo.setDeptIds(vo.getDeptIds()); + sysUserDeptService.setting(deptSettingVo); + + SysUserRoleSettingVo roleSettingVo = new SysUserRoleSettingVo(); + roleSettingVo.setUserIds(Collections.singletonList(vo.getId())); + roleSettingVo.setRoleIds(vo.getRoleIds()); + sysUserRoleService.setting(roleSettingVo); + + OpLogUtil.setVariable("id", data.getId()); + OpLogUtil.setVariable("code", vo.getCode()); + OpLogUtil.setExtra(vo); + } + + @Override + public PageResult selector(Integer pageIndex, Integer pageSize, + SysUserSelectorVo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + + List datas = this.doSelector(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void regist(RegistUserVo vo) { + + this.doRegist(vo); + } + + protected List doQuery(QuerySysUserVo vo) { + + return getBaseMapper().query(vo); + } + + protected SysUser doGetById(String id) { + + return getBaseMapper().findById(id); + } + + protected void doBatchEnable(List ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysUser.class) + .set(SysUser::getAvailable, Boolean.TRUE).in(SysUser::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected void doBatchUnable(List ids) { + + Wrapper updateWrapper = Wrappers.lambdaUpdate(SysUser.class) + .set(SysUser::getAvailable, Boolean.FALSE).in(SysUser::getId, ids); + getBaseMapper().update(updateWrapper); + } + + protected SysUser doCreate(CreateSysUserVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getCode, vo.getCode()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkUsernameWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getUsername, vo.getUsername()); + if (getBaseMapper().selectCount(checkUsernameWrapper) > 0) { + throw new DefaultClientException("用户名重复,请重新输入!"); + } + + SysUser record = new SysUser(); + record.setId(IdUtil.getId()); + record.setCode(vo.getCode()); + record.setName(vo.getName()); + record.setUsername(vo.getUsername()); + record.setPassword(encoderWrapper.getEncoder().encode(vo.getPassword())); + if (!StringUtil.isBlank(vo.getEmail())) { + record.setEmail(vo.getEmail()); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + record.setTelephone(vo.getTelephone()); + } + + record.setGender(EnumUtil.getByCode(Gender.class, vo.getGender())); + record.setAvailable(Boolean.TRUE); + record.setDescription( + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + getBaseMapper().insert(record); + + return record; + } + + protected void doUpdate(UpdateSysUserVo vo) { + + Wrapper checkCodeWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getCode, vo.getCode()).ne(SysUser::getId, vo.getId()); + if (getBaseMapper().selectCount(checkCodeWrapper) > 0) { + throw new DefaultClientException("编号重复,请重新输入!"); + } + + Wrapper checkUsernameWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getUsername, vo.getUsername()).ne(SysUser::getId, vo.getId()); + if (getBaseMapper().selectCount(checkUsernameWrapper) > 0) { + throw new DefaultClientException("用户名重复,请重新输入!"); + } + + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(SysUser.class) + .eq(SysUser::getId, vo.getId()).set(SysUser::getCode, vo.getCode()) + .set(SysUser::getUsername, vo.getUsername()) + .set(SysUser::getName, vo.getName()) + .set(SysUser::getEmail, null).set(SysUser::getTelephone, null) + .set(SysUser::getGender, EnumUtil.getByCode(Gender.class, vo.getGender())) + .set(SysUser::getAvailable, vo.getAvailable()).set(SysUser::getDescription, + StringUtil.isBlank(vo.getDescription()) ? StringPool.EMPTY_STR : vo.getDescription()); + + if (!StringUtil.isBlank(vo.getPassword())) { + updateWrapper.set(SysUser::getPassword, + encoderWrapper.getEncoder().encode(vo.getPassword())); + } + + if (!StringUtil.isBlank(vo.getEmail())) { + updateWrapper.set(SysUser::getEmail, vo.getEmail()); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + updateWrapper.set(SysUser::getTelephone, vo.getTelephone()); + } + + getBaseMapper().update(updateWrapper); + } + + protected List doSelector(SysUserSelectorVo vo) { + + return getBaseMapper().selector(vo); + } + + protected void doRegist(RegistUserVo vo) { + + Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class) + .eq(SysUser::getUsername, vo.getUsername()); + if (getBaseMapper().selectCount(queryWrapper) > 0) { + throw new DefaultClientException("用户名重复,请重新输入!"); + } + + SysUser record = new SysUser(); + record.setId(IdUtil.getId()); + record.setCode(generateCodeService.generate(new UserCodeType())); + record.setName(vo.getName()); + record.setUsername(vo.getUsername()); + record.setPassword(encoderWrapper.getEncoder().encode(vo.getPassword())); + if (!StringUtil.isBlank(vo.getEmail())) { + record.setEmail(vo.getEmail()); + } + + if (!StringUtil.isBlank(vo.getTelephone())) { + record.setTelephone(vo.getTelephone()); + } + + record.setGender(Gender.UNKNOWN); + record.setAvailable(Boolean.TRUE); + record.setDescription(StringPool.EMPTY_STR); + + getBaseMapper().insert(record); + } + + @Cacheable(value = UserInfoDto.CACHE_NAME, key = "@cacheVariables.tenantId() + #userId", unless = "#result == null") + @Override + public UserInfoDto getInfo(@NonNull String userId) { + + return this.doGetInfo(userId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updatePassword(@NonNull String userId, @NonNull String password) { + + this.doUpdatePassword(userId, this.encodePassword(password)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateEmail(@NonNull String userId, @NonNull String email) { + + this.doUpdateEmail(userId, email); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updateTelephone(@NonNull String userId, @NonNull String telephone) { + + this.doUpdateTelephone(userId, telephone); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void lockById(String id) { + + getBaseMapper().lockById(id); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void unlockById(String id) { + + getBaseMapper().unlockById(id); + } + + protected UserInfoDto doGetInfo(@NonNull String userId) { + + return getBaseMapper().getInfo(userId); + } + + protected void doUpdatePassword(@NonNull String userId, @NonNull String password) { + + getBaseMapper().updatePassword(userId, password); + } + + protected void doUpdateEmail(@NonNull String userId, @NonNull String email) { + + getBaseMapper().updateEmail(userId, email); + } + + protected void doUpdateTelephone(@NonNull String userId, @NonNull String telephone) { + + getBaseMapper().updateTelephone(userId, telephone); + } + + protected String encodePassword(String password) { + + return encoderWrapper.getEncoder().encode(password); + } + + @CacheEvict(value = {UserInfoDto.CACHE_NAME, + SysUser.CACHE_NAME}, key = "@cacheVariables.tenantId() + #key") + @Override + public void cleanCacheByKey(Serializable key) { + + userService.cleanCacheByKey(key); + } + + @Override + public void onApplicationEvent(UpdateUserEvent event) { + + SysUserService thisService = getThis(this.getClass()); + thisService.cleanCacheByKey(event.getId()); + } + + public static class UserCodeType implements GenerateCodeType { + + } + + @Component + public static class UserCodeGenerator extends AbstractFlowGenerator { + + @Override + public GenerateCodeType getType() { + + return new UserCodeType(); + } + + @Override + protected int getCodeLength() { + + return 5; + } + + @Override + protected String getPreffix() { + + return "R"; + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserTelephoneServiceImpl.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserTelephoneServiceImpl.java new file mode 100644 index 0000000..17156ef --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/impl/system/SysUserTelephoneServiceImpl.java @@ -0,0 +1,14 @@ +package com.lframework.xingyun.template.inner.impl.system; + +import com.lframework.starter.web.impl.BaseMpServiceImpl; +import com.lframework.xingyun.template.inner.mappers.system.SysUserTelephoneMapper; +import com.lframework.xingyun.template.inner.entity.SysUserTelephone; +import com.lframework.xingyun.template.inner.service.system.SysUserTelephoneService; +import org.springframework.stereotype.Service; + +@Service +public class SysUserTelephoneServiceImpl extends + BaseMpServiceImpl implements + SysUserTelephoneService { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LoginListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LoginListener.java new file mode 100644 index 0000000..ab436dd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LoginListener.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.inner.listeners; + +import com.lframework.starter.web.common.security.AbstractUserDetails; +import com.lframework.starter.web.common.security.SecurityUtil; +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.core.vo.CreateOpLogsVo; +import com.lframework.xingyun.template.inner.events.LoginEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Component +public class LoginListener implements ApplicationListener { + + @Override + public void onApplicationEvent(LoginEvent loginEvent) { + + AbstractUserDetails currentUser = SecurityUtil.getCurrentUser(); + CreateOpLogsVo vo = new CreateOpLogsVo(); + vo.setName("用户登录"); + vo.setLogType(DefaultOpLogType.AUTH); + vo.setCreateBy(currentUser.getName()); + vo.setCreateById(currentUser.getId()); + vo.setIp(currentUser.getIp()); + + OpLogUtil.addLog(vo); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LogoutListener.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LogoutListener.java new file mode 100644 index 0000000..91f6065 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/listeners/LogoutListener.java @@ -0,0 +1,25 @@ +package com.lframework.xingyun.template.inner.listeners; + +import com.lframework.xingyun.template.core.enums.DefaultOpLogType; +import com.lframework.xingyun.template.core.utils.OpLogUtil; +import com.lframework.xingyun.template.core.vo.CreateOpLogsVo; +import com.lframework.xingyun.template.inner.events.LogoutEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +@Component +public class LogoutListener implements ApplicationListener { + + @Override + public void onApplicationEvent(LogoutEvent event) { + + CreateOpLogsVo vo = new CreateOpLogsVo(); + vo.setName("退出登录"); + vo.setLogType(DefaultOpLogType.AUTH); + vo.setCreateBy(event.getUser().getName()); + vo.setCreateById(event.getUser().getId()); + vo.setIp(event.getUser().getIp()); + + OpLogUtil.addLog(vo); + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/QrtzMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/QrtzMapper.java new file mode 100644 index 0000000..020f1c1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/QrtzMapper.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.template.inner.mappers; + +import com.lframework.xingyun.template.inner.dto.qrtz.QrtzDto; +import com.lframework.xingyun.template.inner.vo.qrtz.QueryQrtzVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @author zmj + * @since 2022/8/20 + */ +public interface QrtzMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QueryQrtzVo vo); + + /** + * 根据ID查询 + * + * @param name + * @param group + * @return + */ + QrtzDto findById(@Param("name") String name, @Param("group") String group); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleMapper.java new file mode 100644 index 0000000..9262e57 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.template.inner.mappers; + +import com.lframework.xingyun.template.inner.entity.SysModule; +import com.lframework.starter.web.mapper.BaseMapper; + +public interface SysModuleMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleTenantMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleTenantMapper.java new file mode 100644 index 0000000..5a19efe --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/SysModuleTenantMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.template.inner.mappers; + +import com.lframework.xingyun.template.inner.entity.SysModuleTenant; +import com.lframework.starter.web.mapper.BaseMapper; + +public interface SysModuleTenantMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/TenantMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/TenantMapper.java new file mode 100644 index 0000000..6260397 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/TenantMapper.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.mappers; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.TenantSelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface TenantMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "id", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QueryTenantVo vo); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") TenantSelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/UserDetailsMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/UserDetailsMapper.java new file mode 100644 index 0000000..91f3fa7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/UserDetailsMapper.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.inner.mappers; + +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.starter.web.common.security.DefaultUserDetails; + +/** + * 用于登录的用户信息查询Mapper + * + * @author zmj + */ +public interface UserDetailsMapper extends BaseMapper { + + /** + * 根据登录名查询 + * + * @param username + * @return + */ + DefaultUserDetails findByUsername(String username); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + String codeByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicCategoryMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicCategoryMapper.java new file mode 100644 index 0000000..4bcba41 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicCategoryMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据字典分类 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysDataDicCategoryMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + List query(); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysDataDicCategorySelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicItemMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicItemMapper.java new file mode 100644 index 0000000..8104ebd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicItemMapper.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据字典值 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysDataDicItemMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysDataDicItemVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicMapper.java new file mode 100644 index 0000000..e83e7aa --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataDicMapper.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.SysDataDicSelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 数据字典 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysDataDicMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "tb", autoParse = true), + @Sort(value = "name", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysDataDicVo vo); + + /** + * 选择器 + * + * @return + */ + List selector(@Param("vo") SysDataDicSelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataPermissionDataMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataPermissionDataMapper.java new file mode 100644 index 0000000..aae7a6e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDataPermissionDataMapper.java @@ -0,0 +1,9 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.entity.SysDataPermissionData; +import com.lframework.starter.web.mapper.BaseMapper; + +public interface SysDataPermissionDataMapper extends + BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDeptMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDeptMapper.java new file mode 100644 index 0000000..a1648b4 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysDeptMapper.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; + +/** + *

+ * 部门 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-06-26 + */ +public interface SysDeptMapper extends BaseMapper { + + /** + * 选择器 + * + * @return + */ + List selector(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDept findById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysMenuMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysMenuMapper.java new file mode 100644 index 0000000..522e09e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysMenuMapper.java @@ -0,0 +1,113 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.dto.MenuDto; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.menu.SysMenuSelectorVo; +import java.util.List; +import java.util.Set; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 系统菜单 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +public interface SysMenuMapper extends BaseMapper { + + /** + * 系统菜单列表 + * + * @return + */ + List query(@Param("moduleIds") List moduleIds); + + /** + * 根据角色ID查询已授权的菜单 + * + * @param roleId + * @return + */ + List getByRoleId(@Param("roleId") String roleId, + @Param("moduleIds") List moduleIds); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysMenu findById(String id); + + /** + * 系统菜单选择器数据 + * + * @return + */ + List selector(@Param("vo") SysMenuSelectorVo vo, @Param("moduleIds") List moduleIds); + + /** + * 根据ID查询子节点 + * + * @param id + * @return + */ + List getChildrenById(String id); + + /** + * 根据用户ID查询菜单 + * + * @param userId + * @param isAdmin 是否为管理员 + * @return + */ + List getMenuByUserId(@Param("userId") String userId, @Param("isAdmin") boolean isAdmin, + @Param("moduleIds") List moduleIds); + + /** + * 根据用户ID查询收藏的菜单 + * + * @param userId + * @return + */ + List getCollectMenuIds(@Param("userId") String userId); + + /** + * 根据用户ID查询权限 + * + * @param userId + * @return + */ + Set getPermissionsByUserId(@Param("userId") String userId, + @Param("isAdmin") boolean isAdmin, + @Param("moduleIds") List moduleIds); + + /** + * 根据用户ID查询角色权限 + * + * @param userId + * @return + */ + Set getRolePermissionByUserId(@Param("userId") String userId); + + /** + * 收藏菜单 + * + * @param id + * @param userId + * @param menuId + */ + void collectMenu(@Param("id") String id, @Param("userId") String userId, + @Param("menuId") String menuId); + + /** + * 取消收藏菜单 + * + * @param userId + * @param menuId + */ + void cancelCollectMenu(@Param("userId") String userId, @Param("menuId") String menuId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeLogMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeLogMapper.java new file mode 100644 index 0000000..5c3ac7a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeLogMapper.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysNoticeLog; +import com.lframework.starter.web.mapper.BaseMapper; + +/** + *

+ * 系统通知记录 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysNoticeLogMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeMapper.java new file mode 100644 index 0000000..ea30410 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysNoticeMapper.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.xingyun.template.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 系统通知 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysNoticeMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(@Param("vo") QuerySysNoticeVo vo); + + /** + * 设置已读 + * + * @param id + */ + void setReaded(String id); + + /** + * 根据用户查询 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + List queryByUser(@Param("vo") QuerySysNoticeByUserVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysOpenDomainMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysOpenDomainMapper.java new file mode 100644 index 0000000..0db5ea8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysOpenDomainMapper.java @@ -0,0 +1,40 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.open.QuerySysOpenDomainVo; +import com.lframework.xingyun.template.inner.vo.system.open.SysOpenDomainSelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-02 + */ +public interface SysOpenDomainMapper extends BaseMapper { + + /** + * 查询列表 + * + * @return + */ + @Sorts({ + @Sort(value = "id", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "tenantId", autoParse = true), + }) + List query(@Param("vo") QuerySysOpenDomainVo vo); + + /** + * 选择器 + * + * @return + */ + List selector(@Param("vo") SysOpenDomainSelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysParameterMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysParameterMapper.java new file mode 100644 index 0000000..46a2b94 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysParameterMapper.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.SysParameter; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.parameter.QuerySysParameterVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 系统参数 Mapper 接口 + *

+ * + * @author zmj + */ +public interface SysParameterMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "pmKey", alias = "tb", autoParse = true), + @Sort(value = "createTime", alias = "tb", autoParse = true), + }) + List query(@Param("vo") QuerySysParameterVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysPositionMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysPositionMapper.java new file mode 100644 index 0000000..1459e5a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysPositionMapper.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.position.QuerySysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.SysPositionSelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 系统岗位 Mapper 接口 + *

+ * + * @author zmj + * @since 2021-06-30 + */ +public interface SysPositionMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QuerySysPositionVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysPosition findById(String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysPositionSelectorVo vo); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMapper.java new file mode 100644 index 0000000..844a623 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMapper.java @@ -0,0 +1,59 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleSelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-02 + */ +public interface SysRoleMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", autoParse = true), + @Sort(value = "name", autoParse = true), + @Sort(value = "createTime", autoParse = true), + @Sort(value = "updateTime", autoParse = true), + }) + List query(@Param("vo") QuerySysRoleVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysRole findById(String id); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysRoleSelectorVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMenuMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMenuMapper.java new file mode 100644 index 0000000..e2311c7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysRoleMenuMapper.java @@ -0,0 +1,16 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysRoleMenu; +import com.lframework.starter.web.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysRoleMenuMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserDeptMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserDeptMapper.java new file mode 100644 index 0000000..cbe0081 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserDeptMapper.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysUserDept; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserDeptMapper extends BaseMapper { + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 根据部门ID查询是否存在 + * + * @param deptId + * @return + */ + SysUserDept hasByDeptId(String deptId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserMapper.java new file mode 100644 index 0000000..05c1ea1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserMapper.java @@ -0,0 +1,99 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.core.annotations.sort.Sort; +import com.lframework.xingyun.template.core.annotations.sort.Sorts; +import com.lframework.xingyun.template.inner.dto.UserInfoDto; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.starter.web.mapper.BaseMapper; +import com.lframework.xingyun.template.inner.vo.system.user.QuerySysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserSelectorVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserMapper extends BaseMapper { + + /** + * 查询列表 + * + * @param vo + * @return + */ + @Sorts({ + @Sort(value = "code", alias = "u", autoParse = true), + @Sort(value = "username", alias = "u", autoParse = true), + @Sort(value = "name", alias = "u", autoParse = true), + @Sort(value = "createTime", alias = "u", autoParse = true), + @Sort(value = "updateTime", alias = "u", autoParse = true), + }) + List query(@Param("vo") QuerySysUserVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysUser findById(String id); + + /** + * 选择器 + * + * @param vo + * @return + */ + List selector(@Param("vo") SysUserSelectorVo vo); + + /** + * 获取用户信息 + * + * @param userId 用户ID + * @return + */ + UserInfoDto getInfo(String userId); + + /** + * 修改用户密码 + * + * @param userId 用户ID + * @param password 新密码(密文) + */ + void updatePassword(@Param("userId") String userId, @Param("password") String password); + + /** + * 修改邮箱 + * + * @param userId 用户ID + * @param email 邮箱 + */ + void updateEmail(@Param("userId") String userId, @Param("email") String email); + + /** + * 修改联系电话 + * + * @param userId 用户ID + * @param telephone 联系电话 + */ + void updateTelephone(@Param("userId") String userId, @Param("telephone") String telephone); + + /** + * 根据ID锁定 + * + * @param id + */ + void lockById(String id); + + /** + * 根据ID解锁 + * + * @param id + */ + void unlockById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserPositionMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserPositionMapper.java new file mode 100644 index 0000000..0431f3a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserPositionMapper.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysUserPosition; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserPositionMapper extends BaseMapper { + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserRoleMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserRoleMapper.java new file mode 100644 index 0000000..c4fafa7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserRoleMapper.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysUserRole; +import com.lframework.starter.web.mapper.BaseMapper; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zmj + * @since 2021-07-04 + */ +public interface SysUserRoleMapper extends BaseMapper { + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserTelephoneMapper.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserTelephoneMapper.java new file mode 100644 index 0000000..95144fd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/mappers/system/SysUserTelephoneMapper.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.template.inner.mappers.system; + +import com.lframework.xingyun.template.inner.entity.SysUserTelephone; +import com.lframework.starter.web.mapper.BaseMapper; + +public interface SysUserTelephoneMapper extends BaseMapper { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/QrtzService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/QrtzService.java new file mode 100644 index 0000000..4c015e6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/QrtzService.java @@ -0,0 +1,80 @@ +package com.lframework.xingyun.template.inner.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.xingyun.template.inner.vo.qrtz.CreateQrtzVo; +import com.lframework.xingyun.template.inner.vo.qrtz.UpdateQrtzVo; +import com.lframework.xingyun.template.inner.vo.qrtz.QueryQrtzVo; +import com.lframework.starter.web.service.BaseService; +import com.lframework.xingyun.template.inner.dto.qrtz.QrtzDto; + +/** + * @author zmj + * @since 2022/8/20 + */ +public interface QrtzService extends BaseService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryQrtzVo vo); + + /** + * 根据ID查询 + * + * @param name + * @param group + * @return + */ + QrtzDto findById(String name, String group); + + /** + * 创建 + * + * @param vo + */ + void create(CreateQrtzVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateQrtzVo vo); + + /** + * 恢复 + * + * @param name + * @param group + */ + void resume(String name, String group); + + /** + * 暂停 + * + * @param name + * @param group + */ + void pause(String name, String group); + + /** + * 触发 + * + * @param name + * @param group + */ + void trigger(String name, String group); + + /** + * 删除 + * + * @param name + * @param group + */ + void delete(String name, String group); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleService.java new file mode 100644 index 0000000..d5a006f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleService.java @@ -0,0 +1,7 @@ +package com.lframework.xingyun.template.inner.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.entity.SysModule; + +public interface SysModuleService extends BaseMpService { +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleTenantService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleTenantService.java new file mode 100644 index 0000000..42c4378 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/SysModuleTenantService.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.template.inner.service; + +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.entity.SysModuleTenant; +import com.lframework.xingyun.template.inner.vo.system.module.SysModuleTenantVo; +import java.util.List; + +public interface SysModuleTenantService extends BaseMpService { + + /** + * 根据租户ID查询可用模块ID + * + * @param tenantId + * @return + */ + List getAvailableModuleIdsByTenantId(Integer tenantId); + + /** + * 根据租户ID查询 + * @param tenantId + * @return + */ + List getByTenantId(Integer tenantId); + + /** + * 设置模块 + * @param vo + */ + void setting(SysModuleTenantVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/TenantService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/TenantService.java new file mode 100644 index 0000000..75f73ae --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/TenantService.java @@ -0,0 +1,60 @@ +package com.lframework.xingyun.template.inner.service; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.entity.Tenant; +import com.lframework.xingyun.template.inner.vo.system.tenant.CreateTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.QueryTenantVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.TenantSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.tenant.UpdateTenantVo; + +/** + * 租户Service + * + * @author zmj + */ +public interface TenantService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QueryTenantVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, TenantSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + Tenant findById(Integer id); + + /** + * 新增 + * + * @param data + * @return + */ + Integer create(CreateTenantVo data); + + /** + * 修改 + * + * @param data + */ + void update(UpdateTenantVo data); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicCategoryService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicCategoryService.java new file mode 100644 index 0000000..9cccf9f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicCategoryService.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysDataDicCategory; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.dic.category.CreateSysDataDicCategoryVo; +import com.lframework.xingyun.template.inner.vo.system.dic.category.SysDataDicCategorySelectorVo; +import com.lframework.xingyun.template.inner.vo.system.dic.category.UpdateSysDataDicCategoryVo; +import java.util.List; + +/** + * 数据字典分类 Service + * + * @author zmj + */ +public interface SysDataDicCategoryService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + List queryList(); + + /** + * 选择器 + * + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + SysDataDicCategorySelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDataDicCategory findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDataDicCategoryVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDataDicCategoryVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicItemService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicItemService.java new file mode 100644 index 0000000..0a1ef70 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicItemService.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysDataDicItem; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.dic.item.CreateSysDataDicItemVo; +import com.lframework.xingyun.template.inner.vo.system.dic.item.QuerySysDataDicItemVo; +import com.lframework.xingyun.template.inner.vo.system.dic.item.UpdateSysDataDicItemVo; +import java.util.List; + +/** + * 数据字典值 Service + * + * @author zmj + */ +public interface SysDataDicItemService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysDataDicItemVo vo); + + /** + * 查询列表 + * + * @return + */ + List query(QuerySysDataDicItemVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDataDicItem findById(String id); + + /** + * 根据字典Code、字典值Code查询 + * + * @param dicCode + * @param code + * @return + */ + SysDataDicItem findByCode(String dicCode, String code); + + /** + * 根据字典编号查询 + * + * @param dicCode + * @return + */ + List findByDicCode(String dicCode); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDataDicItemVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDataDicItemVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicService.java new file mode 100644 index 0000000..441d59e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataDicService.java @@ -0,0 +1,75 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysDataDic; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.dic.CreateSysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.QuerySysDataDicVo; +import com.lframework.xingyun.template.inner.vo.system.dic.SysDataDicSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.dic.UpdateSysDataDicVo; +import java.util.List; + +/** + * 数据字典 Service + * + * @author zmj + */ +public interface SysDataDicService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysDataDicVo vo); + + /** + * 查询列表 + * + * @return + */ + List query(QuerySysDataDicVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SysDataDicSelectorVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDataDic findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDataDicVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDataDicVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataPermissionDataService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataPermissionDataService.java new file mode 100644 index 0000000..a3ce753 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDataPermissionDataService.java @@ -0,0 +1,26 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.core.entity.SysDataPermissionData; +import com.lframework.starter.web.service.BaseMpService; +import java.util.List; + +public interface SysDataPermissionDataService extends + BaseMpService { + + /** + * 根据业务ID查询 + * + * @param bizId + * @return + */ + List getByBizId(String bizId); + + /** + * 根据业务ID查询 + * + * @param bizId + * @param bizType + * @return + */ + SysDataPermissionData getByBizId(String bizId, Integer bizType, Integer permissionType); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDeptService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDeptService.java new file mode 100644 index 0000000..24ed8c2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysDeptService.java @@ -0,0 +1,55 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysDept; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.dept.CreateSysDeptVo; +import com.lframework.xingyun.template.inner.vo.system.dept.UpdateSysDeptVo; +import java.util.Collection; +import java.util.List; + +public interface SysDeptService extends BaseMpService { + + /** + * 选择器 + * + * @return + */ + List selector(); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysDept findById(String id); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysDeptVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysDeptVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysMenuService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysMenuService.java new file mode 100644 index 0000000..92b44f5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysMenuService.java @@ -0,0 +1,136 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.dto.MenuDto; +import com.lframework.xingyun.template.inner.entity.SysMenu; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.menu.CreateSysMenuVo; +import com.lframework.xingyun.template.inner.vo.system.menu.SysMenuSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.menu.UpdateSysMenuVo; +import java.util.List; +import java.util.Set; + +/** + *

+ * 系统菜单 服务类 + *

+ * + * @author zmj + * @since 2021-05-10 + */ +public interface SysMenuService extends BaseMpService { + + /** + * 系统菜单列表 + * + * @return + */ + List queryList(List moduleIds); + + /** + * 根据角色ID查询已授权的菜单 + * + * @param roleId + * @return + */ + List getByRoleId(String roleId, List moduleIds); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysMenu findById(String id); + + /** + * 创建系统菜单 + * + * @param vo + */ + String create(CreateSysMenuVo vo); + + /** + * 修改系统菜单 + * + * @param vo + */ + void update(UpdateSysMenuVo vo); + + /** + * 根据ID删除 + * + * @param id + */ + void deleteById(String id); + + /** + * 系统菜单选择器数据 + * + * @return + */ + List selector(SysMenuSelectorVo vo, List moduleIds); + + /** + * 批量启用 + * + * @param ids + * @param userId + */ + void batchEnable(List ids, String userId); + + /** + * 批量停用 + * + * @param ids + * @param userId + */ + void batchUnable(List ids, String userId); + + /** + * 是否存在权限 + * + * @param permission + * @return + */ + Boolean existPermission(String permission); + + /** + * 根据用户ID查询菜单 + * + * @param userId + * @param isAdmin 是否为管理员 + * @return + */ + List getMenuByUserId(String userId, boolean isAdmin, List moduleIds); + + /** + * 根据用户ID查询权限 + * + * @param userId + * @return + */ + Set getPermissionsByUserId(String userId, boolean isAdmin, List moduleIds); + + /** + * 根据用户ID查询角色权限 + * @param userId + * @return + */ + Set getRolePermissionByUserId(String userId); + + /** + * 收藏菜单 + * + * @param userId + * @param menuId + */ + void collect(String userId, String menuId); + + /** + * 取消收藏菜单 + * + * @param userId + * @param menuId + */ + void cancelCollect(String userId, String menuId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeLogService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeLogService.java new file mode 100644 index 0000000..acd1d5a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeLogService.java @@ -0,0 +1,20 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysNoticeLog; +import com.lframework.starter.web.service.BaseMpService; + +/** + * 系统通知记录 Service + * + * @author zmj + */ +public interface SysNoticeLogService extends BaseMpService { + + /** + * 设置已读 + * + * @param noticeId + * @param userId + */ + boolean setReaded(String noticeId, String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeService.java new file mode 100644 index 0000000..550d752 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysNoticeService.java @@ -0,0 +1,108 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.dto.system.notice.QuerySysNoticeByUserDto; +import com.lframework.xingyun.template.inner.dto.system.notice.SysNoticeDto; +import com.lframework.xingyun.template.inner.entity.SysNotice; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.notice.CreateSysNoticeVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeByUserVo; +import com.lframework.xingyun.template.inner.vo.system.notice.QuerySysNoticeVo; +import com.lframework.xingyun.template.inner.vo.system.notice.UpdateSysNoticeVo; +import java.util.List; + +/** + * 系统通知 Service + * + * @author zmj + */ +public interface SysNoticeService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysNoticeVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysNoticeVo vo); + + /** + * 根据用户查询 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult queryByUser(Integer pageIndex, Integer pageSize, + QuerySysNoticeByUserVo vo); + + /** + * 根据ID查询内容 + * + * @param id + * @return + */ + SysNoticeDto getContent(String id); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysNotice findById(String id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysNoticeVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysNoticeVo vo); + + /** + * 发布 + * + * @param id + */ + void publish(String id); + + /** + * 设置已读 + * + * @param id + * @param userId + */ + void setReaded(String id, String userId); + + /** + * 发送通知 + */ + void noticeForWs(); + + /** + * 发送通知 + */ + void noticeForWs(String userId); + + /** + * 发送通知 + */ + void noticeForWsWithSessionId(String sessionId); + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysOpenDomainService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysOpenDomainService.java new file mode 100644 index 0000000..7843c42 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysOpenDomainService.java @@ -0,0 +1,58 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.xingyun.template.inner.vo.system.open.QuerySysOpenDomainVo; +import com.lframework.xingyun.template.inner.vo.system.open.CreateSysOpenDomainVo; +import com.lframework.xingyun.template.inner.vo.system.open.SysOpenDomainSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.open.UpdateSysOpenDomainSecretVo; +import com.lframework.xingyun.template.inner.vo.system.open.UpdateSysOpenDomainVo; + +public interface SysOpenDomainService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(QuerySysOpenDomainVo vo); + + /** + * 选择器 + * + * @return + */ + PageResult selector(SysOpenDomainSelectorVo vo); + + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysOpenDomain findById(Integer id); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysOpenDomainVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysOpenDomainVo vo); + + /** + * 修改Api密钥 + * + * @param vo + */ + void updateApiSecret(UpdateSysOpenDomainSecretVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysParameterService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysParameterService.java new file mode 100644 index 0000000..ae2b239 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysParameterService.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.entity.SysParameter; +import com.lframework.xingyun.template.inner.vo.system.parameter.CreateSysParameterVo; +import com.lframework.xingyun.template.inner.vo.system.parameter.QuerySysParameterVo; +import com.lframework.xingyun.template.inner.vo.system.parameter.UpdateSysParameterVo; +import java.util.List; + +/** + * 系统参数 Service + * + * @author zmj + */ +public interface SysParameterService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysParameterVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysParameterVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysParameter findById(Long id); + + /** + * 创建 + * + * @param vo + * @return + */ + Long create(CreateSysParameterVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysParameterVo vo); + + /** + * 根据ID删除 + * + * @param id + * @return + */ + void deleteById(Long id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysPositionService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysPositionService.java new file mode 100644 index 0000000..20bfb6a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysPositionService.java @@ -0,0 +1,66 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysPosition; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.position.CreateSysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.QuerySysPositionVo; +import com.lframework.xingyun.template.inner.vo.system.position.SysPositionSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.position.UpdateSysPositionVo; +import java.util.Collection; + +public interface SysPositionService extends BaseMpService { + + /** + * 查询全部岗位信息 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, + QuerySysPositionVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysPosition findById(String id); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, + SysPositionSelectorVo vo); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysPositionVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysPositionVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleMenuService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleMenuService.java new file mode 100644 index 0000000..8b3d104 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleMenuService.java @@ -0,0 +1,15 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysRoleMenu; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleMenuSettingVo; + +public interface SysRoleMenuService extends BaseMpService { + + /** + * 授权角色菜单 + * + * @param vo + */ + void setting(SysRoleMenuSettingVo vo); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleService.java new file mode 100644 index 0000000..03c5467 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysRoleService.java @@ -0,0 +1,81 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysRole; +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.role.CreateSysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.QuerySysRoleVo; +import com.lframework.xingyun.template.inner.vo.system.role.SysRoleSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.role.UpdateSysRoleVo; +import java.util.Collection; +import java.util.List; + +public interface SysRoleService extends BaseMpService { + + /** + * 查询列表 + * + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysRoleVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysRoleVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysRole findById(String id); + + /** + * 选择器 + * + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SysRoleSelectorVo vo); + + /** + * 根据ID停用 + * + * @param ids + */ + void batchUnable(Collection ids); + + /** + * 根据ID启用 + * + * @param ids + */ + void batchEnable(Collection ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysRoleVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysRoleVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserDeptService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserDeptService.java new file mode 100644 index 0000000..da1ad32 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserDeptService.java @@ -0,0 +1,32 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysUserDept; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.dept.SysUserDeptSettingVo; +import java.util.List; + +public interface SysUserDeptService extends BaseMpService { + + /** + * 设置部门 + * + * @param vo + */ + void setting(SysUserDeptSettingVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); + + /** + * 根据部门ID查询是否存在 + * + * @param deptId + * @return + */ + Boolean hasByDeptId(String deptId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserPositionService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserPositionService.java new file mode 100644 index 0000000..c3d3cc1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserPositionService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysUserPosition; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.position.SysUserPositionSettingVo; +import java.util.List; + +public interface SysUserPositionService extends BaseMpService { + + /** + * 设置岗位 + * + * @param vo + */ + void setting(SysUserPositionSettingVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserRoleService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserRoleService.java new file mode 100644 index 0000000..c40e19a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserRoleService.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysUserRole; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserRoleSettingVo; +import java.util.List; + +public interface SysUserRoleService extends BaseMpService { + + /** + * 用户授权 + * + * @param vo + */ + void setting(SysUserRoleSettingVo vo); + + /** + * 根据用户ID查询 + * + * @param userId + * @return + */ + List getByUserId(String userId); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserService.java new file mode 100644 index 0000000..b414057 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserService.java @@ -0,0 +1,133 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.starter.web.resp.PageResult; +import com.lframework.starter.web.service.BaseMpService; +import com.lframework.xingyun.template.inner.dto.UserInfoDto; +import com.lframework.xingyun.template.core.entity.SysUser; +import com.lframework.xingyun.template.inner.vo.system.user.CreateSysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.QuerySysUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.RegistUserVo; +import com.lframework.xingyun.template.inner.vo.system.user.SysUserSelectorVo; +import com.lframework.xingyun.template.inner.vo.system.user.UpdateSysUserVo; +import java.util.List; + +public interface SysUserService extends BaseMpService { + + /** + * 查询列表 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult query(Integer pageIndex, Integer pageSize, QuerySysUserVo vo); + + /** + * 查询列表 + * + * @param vo + * @return + */ + List query(QuerySysUserVo vo); + + /** + * 根据ID查询 + * + * @param id + * @return + */ + SysUser findById(String id); + + /** + * 批量启用 + * + * @param ids + */ + void batchEnable(List ids); + + /** + * 批量停用 + * + * @param ids + */ + void batchUnable(List ids); + + /** + * 创建 + * + * @param vo + * @return + */ + String create(CreateSysUserVo vo); + + /** + * 修改 + * + * @param vo + */ + void update(UpdateSysUserVo vo); + + /** + * 选择器 + * + * @param pageIndex + * @param pageSize + * @param vo + * @return + */ + PageResult selector(Integer pageIndex, Integer pageSize, SysUserSelectorVo vo); + + /** + * 注册 + * + * @param vo + */ + void regist(RegistUserVo vo); + + /** + * 获取用户信息 + * + * @param userId 用户ID + * @return + */ + UserInfoDto getInfo(String userId); + + /** + * 修改用户密码 + * + * @param userId 用户ID + * @param password 新密码(明文) + */ + void updatePassword(String userId, String password); + + /** + * 修改邮箱 + * + * @param userId 用户ID + * @param email 邮箱 + */ + void updateEmail(String userId, String email); + + /** + * 修改联系电话 + * + * @param userId 用户ID + * @param telephone 联系电话 + */ + void updateTelephone(String userId, String telephone); + + /** + * 根据ID锁定 + * + * @param id + */ + void lockById(String id); + + /** + * 根据ID解锁 + * + * @param id + */ + void unlockById(String id); +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserTelephoneService.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserTelephoneService.java new file mode 100644 index 0000000..a07657d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/service/system/SysUserTelephoneService.java @@ -0,0 +1,8 @@ +package com.lframework.xingyun.template.inner.service.system; + +import com.lframework.xingyun.template.inner.entity.SysUserTelephone; +import com.lframework.starter.web.service.BaseMpService; + +public interface SysUserTelephoneService extends BaseMpService { + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/handler/DefaultCheckSignHandler.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/handler/DefaultCheckSignHandler.java new file mode 100644 index 0000000..c2c7417 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/handler/DefaultCheckSignHandler.java @@ -0,0 +1,69 @@ +package com.lframework.xingyun.template.inner.sign.handler; + +import com.lframework.starter.common.exceptions.impl.DefaultSysException; +import com.lframework.starter.common.utils.StringUtil; +import com.lframework.xingyun.template.inner.sign.util.SignUtil; +import com.lframework.xingyun.template.inner.entity.SysOpenDomain; +import com.lframework.xingyun.template.inner.service.system.SysOpenDomainService; +import com.lframework.starter.web.common.tenant.TenantContextHolder; +import com.lframework.starter.web.sign.CheckSignHandler; +import com.lframework.starter.web.utils.TenantUtil; +import com.lframework.starter.web.vo.OpenApiReqVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DefaultCheckSignHandler implements CheckSignHandler { + + @Autowired + private SysOpenDomainService sysOpenDomainService; + + @Override + public boolean check(OpenApiReqVo req) { + Integer clientId = req.getClientId(); + if (clientId == null) { + return false; + } + + String timestamp = req.getTimestamp(); + if (StringUtil.isBlank(timestamp)) { + return false; + } + + String nonceStr = req.getNonceStr(); + if (StringUtil.isBlank(nonceStr)) { + return false; + } + + String params = req.getParams(); + if (StringUtil.isBlank(params)) { + return false; + } + + String sign = req.getSign(); + if (StringUtil.isBlank(params)) { + return false; + } + + SysOpenDomain domain = sysOpenDomainService.findById(clientId); + if (domain == null || !domain.getAvailable()) { + return false; + } + + return SignUtil + .validate(clientId.toString(), domain.getApiSecret(), timestamp, nonceStr, params, sign); + } + + @Override + public void setTenantId(OpenApiReqVo req) { + if (TenantUtil.enableTenant()) { + SysOpenDomain domain = sysOpenDomainService.findById(req.getClientId()); + Integer tenantId = domain.getTenantId(); + if (tenantId == null) { + throw new DefaultSysException("开放域没有设置租户ID"); + } else { + TenantContextHolder.setTenantId(domain.getTenantId()); + } + } + } +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/util/SignUtil.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/util/SignUtil.java new file mode 100644 index 0000000..88ad064 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/sign/util/SignUtil.java @@ -0,0 +1,97 @@ +package com.lframework.xingyun.template.inner.sign.util; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Api加签、验签工具类 + */ +public class SignUtil { + + private static final Logger log = LoggerFactory.getLogger(SignUtil.class); + + /** + * 加签 + * + * @param clientId 客户端ID + * @param apiSecret Api密钥 + * @param timestamp 时间戳 + * @param nonceStr 随机字符串 + * @param json 请求参数 + * @return + */ + public static String sign(String clientId, String apiSecret, String timestamp, String nonceStr, + String json) { + String str = new StringBuilder().append("clientId=").append(clientId).append("&") + .append("apiSecret=").append(apiSecret) + .append("&").append("timestamp=").append(timestamp).append("&").append("nonceStr=") + .append(nonceStr).append("&").append("params=") + .append(json).toString(); + MessageDigest digest = null; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + log.error(e.getMessage(), e); + throw new RuntimeException(e); + } + byte[] bs = digest.digest(str.getBytes(StandardCharsets.UTF_8)); + StringBuilder builder = new StringBuilder(); + for (byte b : bs) { + int x = b & 255; + String s = Integer.toHexString(x); + if (x > 0 && x < 16) { + builder.append("0"); + builder.append(s); + } else { + builder.append(s); + } + } + + return builder.toString(); + } + + /** + * 验签 + * + * @param clientId 客户端ID + * @param apiSecret Api密钥 + * @param timestamp 时间戳 + * @param nonceStr 随机字符串 + * @param json 请求参数 + * @param oriSign 原始签值 + * @return + */ + public static boolean validate(String clientId, String apiSecret, String timestamp, + String nonceStr, String json, + String oriSign) { + return sign(clientId, apiSecret, timestamp, nonceStr, json).equals(oriSign); + } + + // 以下为示例 + /* + public static void main(String[] args) { + String clientId = ""; + String apiSecret = ""; + String ts = String.valueOf(System.currentTimeMillis()); + + //此处为示例的获取字符串算法,此处可以自行替换算法 + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 20; i++) { + int number = random.nextInt(62); + builder.append(str.charAt(number)); + } + + String nonceStr = builder.toString(); + + String json = "{\"key1\":\"value1\", \"key2\":\"value2\"}"; + String sign = SignUtil.sign(clientId, apiSecret, ts, nonceStr, json); // 这里是加签 + + boolean isValidate = SignUtil.validate(clientId, apiSecret, ts, nonceStr, json, sign); // 这里是验签 + } + */ +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/CreateQrtzVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/CreateQrtzVo.java new file mode 100644 index 0000000..44b6c15 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/CreateQrtzVo.java @@ -0,0 +1,91 @@ +package com.lframework.xingyun.template.inner.vo.qrtz; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.template.inner.enums.QrtzJobType; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class CreateQrtzVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 分组 + */ + @ApiModelProperty(value = "分组", required = true) + @NotBlank(message = "分组不能为空!") + private String group; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 执行类名 + */ + @ApiModelProperty("执行类名") + private String targetClassName; + + /** + * 执行方法名 + */ + @ApiModelProperty("执行方法名") + private String targetMethodName; + + /** + * 执行参数类型 + */ + @ApiModelProperty("执行参数类型") + private List targetParamTypes; + + /** + * 执行参数 + */ + @ApiModelProperty("执行参数") + private List targetParams; + + /** + * Cron表达式 + */ + @ApiModelProperty("Cron表达式") + @NotBlank(message = "Cron表达式不能为空!") + private String cron; + + /** + * 任务类型 + */ + @NotNull(message = "任务类型不能为空!") + @IsEnum(message = "任务类型不能为空!", enumClass = QrtzJobType.class) + private Integer jobType; + + /** + * 脚本 + */ + @ApiModelProperty("脚本") + private String script; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/QueryQrtzVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/QueryQrtzVo.java new file mode 100644 index 0000000..7f63702 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/QueryQrtzVo.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.inner.vo.qrtz; + +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.xingyun.template.inner.enums.TriggerState; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class QueryQrtzVo extends PageVo { + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 组 + */ + @ApiModelProperty("组") + private String group; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @IsEnum(message = "状态格式错误!", enumClass = TriggerState.class) + private String state; + + /** + * 任务类 + */ + @ApiModelProperty(hidden = true) + private List jobClasses; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/UpdateQrtzVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/UpdateQrtzVo.java new file mode 100644 index 0000000..26846be --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/qrtz/UpdateQrtzVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.qrtz; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author zmj + * @since 2022/8/20 + */ +@Data +public class UpdateQrtzVo extends CreateQrtzVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 原始任务名称 + */ + @ApiModelProperty(value = "原始任务名称", required = true) + @NotBlank(message = "原始任务名称不能为空!") + private String oriName; + + /** + * 原始任务分组 + */ + @ApiModelProperty(value = "原始任务分组", required = true) + @NotBlank(message = "原始任务分组不能为空!") + private String oriGroup; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/config/UpdateSysConfigVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/config/UpdateSysConfigVo.java new file mode 100644 index 0000000..a66c087 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/config/UpdateSysConfigVo.java @@ -0,0 +1,96 @@ +package com.lframework.xingyun.template.inner.vo.system.config; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysConfigVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 是否允许注册 + */ + @ApiModelProperty(value = "是否允许注册", required = true) + @NotNull(message = "请选择是否允许注册!") + @TypeMismatch(message = "是否允许注册格式错误!") + private Boolean allowRegist; + + /** + * 是否允许手机号登录 + */ + @ApiModelProperty(value = "是否允许手机号登录", required = true) + @NotNull(message = "请选择是否允许手机号登录!") + @TypeMismatch(message = "是否允许手机号登录格式错误!") + private Boolean allowTelephoneLogin; + + /** + * 手机号登录时的signName + */ + private String telephoneLoginSignName; + + /** + * 手机号登录时的templateCode + */ + private String telephoneLoginTemplateCode; + + /** + * 是否允许锁定用户 + */ + @ApiModelProperty(value = "是否允许锁定用户", required = true) + @NotNull(message = "请选择是否允许锁定用户!") + @TypeMismatch(message = "是否允许锁定用户格式错误!") + private Boolean allowLock; + + /** + * 登录失败次数 + */ + @ApiModelProperty(value = "登录失败次数") + private Integer failNum; + + /** + * 是否允许验证码 + */ + @ApiModelProperty(value = "是否允许验证码", required = true) + @NotNull(message = "请选择是否允许验证码!") + @TypeMismatch(message = "是否允许验证码格式错误!") + private Boolean allowCaptcha; + + /** + * 是否开启忘记密码 + */ + @ApiModelProperty(value = "是否开启忘记密码", required = true) + @NotNull(message = "请选择是否开启忘记密码!") + @TypeMismatch(message = "是否开启忘记密码格式错误!") + private Boolean allowForgetPsw; + + /** + * 忘记密码是否使用邮箱 + */ + @ApiModelProperty(value = "忘记密码是否使用邮箱,allowForgetPsw == true时必填") + @TypeMismatch(message = "忘记密码是否使用邮箱格式错误!") + private Boolean forgetPswRequireMail; + + /** + * 忘记密码是否使用短信 + */ + @ApiModelProperty(value = "忘记密码是否使用短信,allowForgetPsw == true时必填") + @TypeMismatch(message = "忘记密码是否使用短信格式错误!") + private Boolean forgetPswRequireSms; + + /** + * signName + */ + @ApiModelProperty(value = "signName,forgetPswRequireSms == true时必填") + private String signName; + + /** + * templateCode + */ + @ApiModelProperty(value = "templateCode,forgetPswRequireSms == true时必填") + private String templateCode; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/CreateSysDeptVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/CreateSysDeptVo.java new file mode 100644 index 0000000..7b5b0ed --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/CreateSysDeptVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.template.inner.vo.system.dept; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysDeptVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 简称 + */ + @ApiModelProperty(value = "简称", required = true) + @NotBlank(message = "简称不能为空!") + private String shortName; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/SysUserDeptSettingVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/SysUserDeptSettingVo.java new file mode 100644 index 0000000..b210969 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/SysUserDeptSettingVo.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.vo.system.dept; + +import com.lframework.starter.web.vo.BaseVo; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class SysUserDeptSettingVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @NotBlank(message = "用户ID不能为空!") + private String userId; + + /** + * 部门ID + */ + private List deptIds; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/UpdateSysDeptVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/UpdateSysDeptVo.java new file mode 100644 index 0000000..23208a3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dept/UpdateSysDeptVo.java @@ -0,0 +1,63 @@ +package com.lframework.xingyun.template.inner.vo.system.dept; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysDeptVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "编号不能为空!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 简称 + */ + @ApiModelProperty(value = "简称", required = true) + @NotBlank(message = "简称不能为空!") + private String shortName; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/CreateSysDataDicVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/CreateSysDataDicVo.java new file mode 100644 index 0000000..fa7cad5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/CreateSysDataDicVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.inner.vo.system.dic; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysDataDicVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/QuerySysDataDicVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/QuerySysDataDicVo.java new file mode 100644 index 0000000..98bec53 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/QuerySysDataDicVo.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.template.inner.vo.system.dic; + +import com.lframework.starter.web.vo.PageVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class QuerySysDataDicVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/SysDataDicSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/SysDataDicSelectorVo.java new file mode 100644 index 0000000..b452075 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/SysDataDicSelectorVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.inner.vo.system.dic; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDataDicSelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/UpdateSysDataDicVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/UpdateSysDataDicVo.java new file mode 100644 index 0000000..a4148dc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/UpdateSysDataDicVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.vo.system.dic; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysDataDicVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 分类ID + */ + @ApiModelProperty("分类ID") + private String categoryId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java new file mode 100644 index 0000000..fad425d --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/CreateSysDataDicCategoryVo.java @@ -0,0 +1,29 @@ +package com.lframework.xingyun.template.inner.vo.system.dic.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysDataDicCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java new file mode 100644 index 0000000..badfdd7 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/SysDataDicCategorySelectorVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.inner.vo.system.dic.category; + +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class SysDataDicCategorySelectorVo extends PageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java new file mode 100644 index 0000000..48214f8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/category/UpdateSysDataDicCategoryVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.inner.vo.system.dic.category; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysDataDicCategoryVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/CreateSysDataDicItemVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/CreateSysDataDicItemVo.java new file mode 100644 index 0000000..df32917 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/CreateSysDataDicItemVo.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.inner.vo.system.dic.item; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSysDataDicItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 字典ID + */ + @ApiModelProperty("字典ID") + @NotBlank(message = "字典ID不能为空!") + private String dicId; + + /** + * 排序 + */ + @ApiModelProperty("排序") + @NotNull(message = "请输入排序!") + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/QuerySysDataDicItemVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/QuerySysDataDicItemVo.java new file mode 100644 index 0000000..d1e11f9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/QuerySysDataDicItemVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.dic.item; + +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class QuerySysDataDicItemVo extends SortPageVo { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 字典ID + */ + @ApiModelProperty("字典ID") + @NotBlank(message = "字典ID不能为空!") + private String dicId; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java new file mode 100644 index 0000000..04b2751 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/dic/item/UpdateSysDataDicItemVo.java @@ -0,0 +1,44 @@ +package com.lframework.xingyun.template.inner.vo.system.dic.item; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysDataDicItemVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @NotBlank(message = "请输入编号!") + @IsCode + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 排序 + */ + @ApiModelProperty("排序") + @NotNull(message = "请输入排序!") + private Integer orderNo; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/CreateSysMenuVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/CreateSysMenuVo.java new file mode 100644 index 0000000..0472795 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/CreateSysMenuVo.java @@ -0,0 +1,113 @@ +package com.lframework.xingyun.template.inner.vo.system.menu; + +import com.lframework.xingyun.template.inner.enums.system.SysMenuComponentType; +import com.lframework.xingyun.template.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 创建菜单Vo + */ +@Data +public class CreateSysMenuVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题", required = true) + @NotBlank(message = "请输入标题!") + private String title; + + /** + * 图标 + */ + @ApiModelProperty("图标") + private String icon; + + /** + * 类型 + */ + @ApiModelProperty(value = "类型", required = true) + @NotNull(message = "请选择类型!") + @IsEnum(message = "请选择类型!", enumClass = SysMenuDisplay.class) + private Integer display; + + /** + * 父级ID + */ + @ApiModelProperty("父级ID") + private String parentId; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + // 以下均为前端配置项 + + /** + * 路由名称 + */ + @ApiModelProperty("路由名称") + private String name; + + /** + * 组件类型 + */ + @ApiModelProperty("组件类型") + @IsEnum(message = "组件类型格式错误!", enumClass = SysMenuComponentType.class) + private Integer componentType; + + /** + * 组件 + */ + @ApiModelProperty("组件") + private String component; + + /** + * 自定义请求参数 + */ + @ApiModelProperty("自定义请求参数") + private String requestParam; + + /** + * 路径 + */ + @ApiModelProperty("路径") + private String path; + + /** + * 是否隐藏 + */ + @ApiModelProperty("是否隐藏") + private Boolean hidden; + + /** + * 是否不缓存 + */ + @ApiModelProperty("是否不缓存") + private Boolean noCache; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/SysMenuSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/SysMenuSelectorVo.java new file mode 100644 index 0000000..8f536f3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/SysMenuSelectorVo.java @@ -0,0 +1,21 @@ +package com.lframework.xingyun.template.inner.vo.system.menu; + +import com.lframework.xingyun.template.inner.enums.system.SysMenuDisplay; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysMenuSelectorVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("类型") + @IsEnum(message = "类型格式不正确!", enumClass = SysMenuDisplay.class) + private Integer display; + + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/UpdateSysMenuVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/UpdateSysMenuVo.java new file mode 100644 index 0000000..ce6fe31 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/menu/UpdateSysMenuVo.java @@ -0,0 +1,30 @@ +package com.lframework.xingyun.template.inner.vo.system.menu; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysMenuVo extends CreateSysMenuVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + @TypeMismatch(message = "状态格式有误!") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/module/SysModuleTenantVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/module/SysModuleTenantVo.java new file mode 100644 index 0000000..0ac2063 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/module/SysModuleTenantVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.inner.vo.system.module; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class SysModuleTenantVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + @Data + public static class SysModuleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 模块ID + */ + @ApiModelProperty(value = "模块ID", required = true) + @NotNull(message = "模块ID不能为空!") + private Integer moduleId; + + /** + * 过期时间 + */ + @ApiModelProperty(value = "过期时间", required = true) + @NotNull(message = "过期时间不能为空!") + private LocalDateTime expireTime; + } + + /** + * 租户ID + */ + @ApiModelProperty(value = "租户ID", required = true) + @NotNull(message = "租户ID不能为空!") + private Integer tenantId; + + /** + * 模块 + */ + @ApiModelProperty("模块") + @Valid + private List modules; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/CreateSysNoticeVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/CreateSysNoticeVo.java new file mode 100644 index 0000000..ee58cdc --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/CreateSysNoticeVo.java @@ -0,0 +1,38 @@ +package com.lframework.xingyun.template.inner.vo.system.notice; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSysNoticeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题", required = true) + @NotBlank(message = "请输入标题!") + private String title; + + /** + * 内容 + */ + @ApiModelProperty(value = "内容", required = true) + @NotBlank(message = "请输入内容!") + private String content; + + /** + * 是否发布 + */ + @ApiModelProperty(value = "是否发布", required = true) + @TypeMismatch(message = "是否发布格式有误!") + @NotNull(message = "请选择是否发布!") + private Boolean published; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeByUserVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeByUserVo.java new file mode 100644 index 0000000..f77bafd --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeByUserVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.template.inner.vo.system.notice; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySysNoticeByUserVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 用户ID + */ + @ApiModelProperty(hidden = true) + private String userId; + + /** + * 是否已读 + */ + @ApiModelProperty("是否已读") + private Boolean readed; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeVo.java new file mode 100644 index 0000000..c0c4922 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/QuerySysNoticeVo.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.template.inner.vo.system.notice; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySysNoticeVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标题 + */ + @ApiModelProperty("标题") + private String title; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/UpdateSysNoticeVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/UpdateSysNoticeVo.java new file mode 100644 index 0000000..aa6eca0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/notice/UpdateSysNoticeVo.java @@ -0,0 +1,52 @@ +package com.lframework.xingyun.template.inner.vo.system.notice; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysNoticeVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "id不能为空!") + private String id; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题", required = true) + @NotBlank(message = "请输入标题!") + private String title; + + /** + * 内容 + */ + @ApiModelProperty(value = "内容", required = true) + @NotBlank(message = "请输入内容!") + private String content; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @TypeMismatch(message = "状态格式有误!") + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 是否发布 + */ + @ApiModelProperty(value = "是否发布", required = true) + @TypeMismatch(message = "是否发布格式有误!") + @NotNull(message = "请选择是否发布!") + private Boolean published; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/CreateSysOpenDomainVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/CreateSysOpenDomainVo.java new file mode 100644 index 0000000..050083f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/CreateSysOpenDomainVo.java @@ -0,0 +1,39 @@ +package com.lframework.xingyun.template.inner.vo.system.open; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysOpenDomainVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * API密钥 + */ + @ApiModelProperty(value = "API密钥", required = true) + @NotBlank(message = "API密钥不能为空!") + private String apiSecret; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/QuerySysOpenDomainVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/QuerySysOpenDomainVo.java new file mode 100644 index 0000000..01b85ac --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/QuerySysOpenDomainVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.open; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySysOpenDomainVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/SysOpenDomainSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/SysOpenDomainSelectorVo.java new file mode 100644 index 0000000..6c01146 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/SysOpenDomainSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.open; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysOpenDomainSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + private String id; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java new file mode 100644 index 0000000..98383de --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainSecretVo.java @@ -0,0 +1,28 @@ +package com.lframework.xingyun.template.inner.vo.system.open; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysOpenDomainSecretVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private Long id; + + /** + * Api密钥 + */ + @ApiModelProperty(value = "Api密钥", required = true) + @NotBlank(message = "Api密钥不能为空!") + private String apiSecret; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainVo.java new file mode 100644 index 0000000..c3ed19f --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/open/UpdateSysOpenDomainVo.java @@ -0,0 +1,48 @@ +package com.lframework.xingyun.template.inner.vo.system.open; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysOpenDomainVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private Long id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "名称不能为空!") + private String name; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private Integer tenantId; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/CreateSysParameterVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/CreateSysParameterVo.java new file mode 100644 index 0000000..78dd0cb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/CreateSysParameterVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.inner.vo.system.parameter; + +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysParameterVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 键 + */ + @ApiModelProperty(value = "键", required = true) + @NotBlank(message = "请输入键!") + @Pattern(regexp = "^[A-Za-z0-9\\.\\-_]+$", message = "键只能由大写字母、小写字母、数字或._-组成") + private String pmKey; + + /** + * 值 + */ + @ApiModelProperty("值") + private String pmValue; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/QuerySysParameterVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/QuerySysParameterVo.java new file mode 100644 index 0000000..0924ee3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/QuerySysParameterVo.java @@ -0,0 +1,36 @@ +package com.lframework.xingyun.template.inner.vo.system.parameter; + +import com.lframework.starter.web.components.validation.TypeMismatch; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class QuerySysParameterVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 键 + */ + @ApiModelProperty("键") + private String pmKey; + + /** + * 创建时间 起始时间 + */ + @ApiModelProperty("创建时间 起始时间") + @TypeMismatch(message = "创建时间起始时间格式有误!") + private LocalDateTime createTimeStart; + + /** + * 创建时间 截止时间 + */ + @ApiModelProperty("创建时间 截止时间") + @TypeMismatch(message = "创建时间截止时间格式有误!") + private LocalDateTime createTimeEnd; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/UpdateSysParameterVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/UpdateSysParameterVo.java new file mode 100644 index 0000000..27d7e80 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/parameter/UpdateSysParameterVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.vo.system.parameter; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysParameterVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "id不能为空!") + private Long id; + + /** + * 值 + */ + @ApiModelProperty("值") + private String pmValue; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; + +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/CreateSysPositionVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/CreateSysPositionVo.java new file mode 100644 index 0000000..c7972ce --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/CreateSysPositionVo.java @@ -0,0 +1,35 @@ +package com.lframework.xingyun.template.inner.vo.system.position; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysPositionVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 岗位编号 + */ + @ApiModelProperty(value = "岗位编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty(value = "岗位名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/QuerySysPositionVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/QuerySysPositionVo.java new file mode 100644 index 0000000..733a0e2 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/QuerySysPositionVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.position; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySysPositionVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysPositionSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysPositionSelectorVo.java new file mode 100644 index 0000000..c783745 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysPositionSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.position; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysPositionSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysUserPositionSettingVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysUserPositionSettingVo.java new file mode 100644 index 0000000..49fc9c0 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/SysUserPositionSettingVo.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.vo.system.position; + +import com.lframework.starter.web.vo.BaseVo; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class SysUserPositionSettingVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @NotBlank(message = "用户ID不能为空!") + private String userId; + + /** + * 岗位ID + */ + private List positionIds; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/UpdateSysPositionVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/UpdateSysPositionVo.java new file mode 100644 index 0000000..b384619 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/position/UpdateSysPositionVo.java @@ -0,0 +1,50 @@ +package com.lframework.xingyun.template.inner.vo.system.position; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysPositionVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty("ID") + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 岗位编号 + */ + @ApiModelProperty("岗位编号") + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 岗位名称 + */ + @ApiModelProperty("岗位名称") + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/CreateSysRoleVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/CreateSysRoleVo.java new file mode 100644 index 0000000..3aa141e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/CreateSysRoleVo.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.inner.vo.system.role; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateSysRoleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/QuerySysRoleVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/QuerySysRoleVo.java new file mode 100644 index 0000000..86948ee --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/QuerySysRoleVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.role; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySysRoleVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleMenuSettingVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleMenuSettingVo.java new file mode 100644 index 0000000..8639e0e --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleMenuSettingVo.java @@ -0,0 +1,24 @@ +package com.lframework.xingyun.template.inner.vo.system.role; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class SysRoleMenuSettingVo implements BaseVo { + + /** + * 角色ID + */ + @ApiModelProperty(value = "角色ID", required = true) + @NotEmpty(message = "角色ID不能为空!") + private List roleIds; + + /** + * 菜单ID + */ + @ApiModelProperty("菜单ID") + private List menuIds; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleSelectorVo.java new file mode 100644 index 0000000..5b01fc3 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/SysRoleSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.role; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysRoleSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/UpdateSysRoleVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/UpdateSysRoleVo.java new file mode 100644 index 0000000..9d66124 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/role/UpdateSysRoleVo.java @@ -0,0 +1,56 @@ +package com.lframework.xingyun.template.inner.vo.system.role; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysRoleVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * 权限 + */ + @ApiModelProperty("权限") + private String permission; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/CreateTenantVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/CreateTenantVo.java new file mode 100644 index 0000000..c3cfbe1 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/CreateTenantVo.java @@ -0,0 +1,41 @@ +package com.lframework.xingyun.template.inner.vo.system.tenant; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class CreateTenantVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * JdbcUrl + */ + @ApiModelProperty(value = "JdbcUrl", required = true) + @NotBlank(message = "请输入JdbcUrl!") + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @ApiModelProperty(value = "Jdbc用户名", required = true) + @NotBlank(message = "请输入Jdbc用户名!") + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @ApiModelProperty(value = "Jdbc密码", required = true) + @NotBlank(message = "请输入Jdbc密码!") + private String jdbcPassword; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/QueryTenantVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/QueryTenantVo.java new file mode 100644 index 0000000..00f5f7a --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/QueryTenantVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.tenant; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QueryTenantVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private String tenantId; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/TenantSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/TenantSelectorVo.java new file mode 100644 index 0000000..78eb6fb --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/TenantSelectorVo.java @@ -0,0 +1,31 @@ +package com.lframework.xingyun.template.inner.vo.system.tenant; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class TenantSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @ApiModelProperty("租户ID") + private String tenantId; + + /** + * 名称 + */ + @ApiModelProperty("名称") + private String name; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/UpdateTenantVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/UpdateTenantVo.java new file mode 100644 index 0000000..6ffbf12 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/tenant/UpdateTenantVo.java @@ -0,0 +1,53 @@ +package com.lframework.xingyun.template.inner.vo.system.tenant; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateTenantVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotNull(message = "ID不能为空!") + private Integer id; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称", required = true) + @NotBlank(message = "请输入名称!") + private String name; + + /** + * JdbcUrl + */ + @ApiModelProperty("JdbcUrl") + private String jdbcUrl; + + /** + * Jdbc用户名 + */ + @ApiModelProperty("Jdbc用户名") + private String jdbcUsername; + + /** + * Jdbc密码 + */ + @ApiModelProperty("Jdbc密码") + private String jdbcPassword; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "请选择状态!") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/CreateSysUserVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/CreateSysUserVo.java new file mode 100644 index 0000000..d2d1934 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/CreateSysUserVo.java @@ -0,0 +1,96 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.template.core.enums.Gender; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class CreateSysUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @IsCode + @NotBlank(message = "请输入编号!") + @ApiModelProperty(value = "编号", required = true) + private String code; + + /** + * 姓名 + */ + @NotBlank(message = "请输入姓名!") + @ApiModelProperty(value = "姓名", required = true) + private String name; + + /** + * 用户名 + */ + @NotBlank(message = "请输入用户名!") + @ApiModelProperty(value = "用户名", required = true) + private String username; + + /** + * 密码 + */ + @Pattern(regexp = PatternPool.PATTERN_STR_PASSWORD, message = "密码长度必须为5-16位,只允许包含大写字母、小写字母、数字、下划线") + @NotBlank(message = "请输入密码!") + @ApiModelProperty(value = "密码", required = true) + private String password; + + /** + * 邮箱 + */ + @Pattern(regexp = PatternPool.PATTERN_STR_EMAIL, message = "邮箱地址格式不正确!") + @ApiModelProperty("邮箱") + private String email; + + /** + * 联系电话 + */ + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "联系电话格式不正确!") + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 性别 0-未知 1-男 2-女 + */ + @NotNull(message = "请选择性别!") + @IsEnum(message = "请选择性别!", enumClass = Gender.class) + @ApiModelProperty("性别") + private Integer gender; + + /** + * 部门ID + */ + @ApiModelProperty("部门ID") + private List deptIds; + + /** + * 角色ID + */ + @ApiModelProperty("角色ID") + private List roleIds; + + /** + * 岗位ID + */ + @ApiModelProperty("岗位ID") + private List positionIds; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java new file mode 100644 index 0000000..c93cfb6 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/GetTelephoneLoginCaptchaVo.java @@ -0,0 +1,23 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class GetTelephoneLoginCaptchaVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "手机号格式不正确!") + @NotBlank(message = "手机号不能为空!") + private String telephone; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/LoginVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/LoginVo.java new file mode 100644 index 0000000..f39fea8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/LoginVo.java @@ -0,0 +1,42 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 用户登录请求参数 + */ +@Data +public class LoginVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名", required = true) + @NotBlank(message = "用户名不能为空!") + private String username; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码", required = true) + @NotBlank(message = "密码不能为空!") + private String password; + + /** + * sn + */ + @ApiModelProperty(value = "sn,验证码流水号", required = true) + private String sn; + + /** + * 验证码 + */ + @ApiModelProperty(value = "验证码", required = true) + private String captcha; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/QuerySysUserVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/QuerySysUserVo.java new file mode 100644 index 0000000..d99ade9 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/QuerySysUserVo.java @@ -0,0 +1,56 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import com.lframework.starter.web.vo.SortPageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class QuerySysUserVo extends SortPageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 用户名 + */ + @ApiModelProperty("用户名") + private String username; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 岗位ID + */ + @ApiModelProperty("岗位ID") + private String positionId; + + /** + * 部门ID + */ + @ApiModelProperty("部门ID") + private String deptId; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; + + /** + * 是否锁定 + */ + @ApiModelProperty("是否锁定") + private Boolean lockStatus; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/RegistUserVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/RegistUserVo.java new file mode 100644 index 0000000..6b4f0f5 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/RegistUserVo.java @@ -0,0 +1,51 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class RegistUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名", required = true) + @NotBlank(message = "用户名不能为空!") + private String username; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码", required = true) + @Pattern(regexp = PatternPool.PATTERN_STR_PASSWORD, message = "密码长度必须为5-16位,只允许包含大写字母、小写字母、数字、下划线") + @NotBlank(message = "密码不能为空!") + private String password; + + /** + * 姓名 + */ + @ApiModelProperty(value = "姓名", required = true) + @NotBlank(message = "姓名不能为空!") + private String name; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱") + @Pattern(regexp = PatternPool.PATTERN_STR_EMAIL, message = "邮箱地址格式不正确!") + private String email; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "联系电话格式不正确!") + private String telephone; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserRoleSettingVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserRoleSettingVo.java new file mode 100644 index 0000000..64ecd58 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserRoleSettingVo.java @@ -0,0 +1,27 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class SysUserRoleSettingVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + @ApiModelProperty(value = "用户ID", required = true) + @NotEmpty(message = "用户ID不能为空!") + private List userIds; + + /** + * 角色ID + */ + @ApiModelProperty("角色ID") + private List roleIds; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserSelectorVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserSelectorVo.java new file mode 100644 index 0000000..76e910b --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/SysUserSelectorVo.java @@ -0,0 +1,37 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.starter.web.vo.PageVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +@Data +public class SysUserSelectorVo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @ApiModelProperty("编号") + private String code; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String name; + + /** + * 用户名 + */ + @ApiModelProperty("用户名") + private String username; + + /** + * 状态 + */ + @ApiModelProperty("状态") + private Boolean available; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneBindUserVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneBindUserVo.java new file mode 100644 index 0000000..9855646 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneBindUserVo.java @@ -0,0 +1,43 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 手机号绑定用户 + * + * @author zmj + * @since 2022/4/25 + */ +@Data +public class TelephoneBindUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "手机号格式不正确!") + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名", required = true) + @NotBlank(message = "用户名不能为空!") + private String username; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码", required = true) + @NotBlank(message = "密码不能为空!") + private String password; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneLoginVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneLoginVo.java new file mode 100644 index 0000000..4d0f4b8 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/TelephoneLoginVo.java @@ -0,0 +1,33 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.common.constants.PatternPool; +import com.lframework.starter.web.components.validation.Pattern; +import com.lframework.starter.web.vo.BaseVo; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 手机号登录请求参数 + */ +@Data +public class TelephoneLoginVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + @Pattern(regexp = PatternPool.PATTERN_STR_CN_TEL, message = "手机号格式不正确!") + @NotBlank(message = "手机号不能为空!") + private String telephone; + + /** + * 验证码 + */ + @ApiModelProperty(value = "验证码", required = true) + @NotBlank(message = "验证码不能为空!") + private String captcha; +} diff --git a/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/UpdateSysUserVo.java b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/UpdateSysUserVo.java new file mode 100644 index 0000000..7a56a47 --- /dev/null +++ b/xingyun-template/src/main/java/com/lframework/xingyun/template/inner/vo/system/user/UpdateSysUserVo.java @@ -0,0 +1,104 @@ +package com.lframework.xingyun.template.inner.vo.system.user; + +import com.lframework.starter.web.components.validation.IsCode; +import com.lframework.starter.web.components.validation.IsEnum; +import com.lframework.starter.web.vo.BaseVo; +import com.lframework.xingyun.template.core.enums.Gender; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdateSysUserVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID", required = true) + @NotBlank(message = "ID不能为空!") + private String id; + + /** + * 编号 + */ + @ApiModelProperty(value = "编号", required = true) + @IsCode + @NotBlank(message = "请输入编号!") + private String code; + + /** + * 姓名 + */ + @ApiModelProperty(value = "姓名", required = true) + @NotBlank(message = "请输入姓名!") + private String name; + + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名", required = true) + @NotBlank(message = "请输入用户名!") + private String username; + + /** + * 密码 如果不为空则为修改密码 + */ + @ApiModelProperty("密码 如果不为空则为修改密码") + private String password; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱") + private String email; + + /** + * 联系电话 + */ + @ApiModelProperty("联系电话") + private String telephone; + + /** + * 性别 + */ + @ApiModelProperty(value = "性别", required = true) + @NotNull(message = "请选择性别!") + @IsEnum(message = "请选择性别!", enumClass = Gender.class) + private Integer gender; + + /** + * 岗位ID + */ + @ApiModelProperty("岗位ID") + private List positionIds; + + /** + * 角色ID + */ + @ApiModelProperty("角色ID") + private List roleIds; + + /** + * 部门ID + */ + @ApiModelProperty("部门ID") + private List deptIds; + + /** + * 状态 + */ + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "请选择状态!") + private Boolean available; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String description; +} diff --git a/xingyun-template/src/main/java/lombok.config b/xingyun-template/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-template/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/QrtzMapper.xml b/xingyun-template/src/main/resources/mappers/QrtzMapper.xml new file mode 100644 index 0000000..916db3a --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/QrtzMapper.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + SELECT + job.JOB_NAME AS `name`, + job.JOB_GROUP AS `group`, + job.DESCRIPTION AS description, + cron.CRON_EXPRESSION AS cron, + tri.TRIGGER_STATE AS state + FROM qrtz_job_details AS job + LEFT JOIN qrtz_triggers AS tri ON job.JOB_NAME = tri.JOB_NAME AND job.JOB_GROUP = tri.JOB_GROUP + LEFT JOIN qrtz_cron_triggers AS cron ON cron.TRIGGER_NAME = tri.TRIGGER_NAME AND cron.TRIGGER_GROUP= tri.JOB_GROUP + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/SysParameterMapper.xml b/xingyun-template/src/main/resources/mappers/SysParameterMapper.xml new file mode 100644 index 0000000..9e0ec73 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/SysParameterMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.pm_key, + tb.pm_value, + tb.description, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_parameter AS tb + + diff --git a/xingyun-template/src/main/resources/mappers/TenantMapper.xml b/xingyun-template/src/main/resources/mappers/TenantMapper.xml new file mode 100644 index 0000000..49480c0 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/TenantMapper.xml @@ -0,0 +1,43 @@ + + + + + SELECT + tb.* + FROM tenant AS tb + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/UserDetailsMapper.xml b/xingyun-template/src/main/resources/mappers/UserDetailsMapper.xml new file mode 100644 index 0000000..afeb2f4 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/UserDetailsMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/DBMapper.xml b/xingyun-template/src/main/resources/mappers/gen/DBMapper.xml new file mode 100644 index 0000000..932e35e --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/DBMapper.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCreateColumnConfigMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCreateColumnConfigMapper.xml new file mode 100644 index 0000000..956ddbc --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCreateColumnConfigMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + SELECT + g.id, + g.required, + g.order_no + FROM gen_create_column_config AS g + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomListCategoryMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomListCategoryMapper.xml new file mode 100644 index 0000000..c5dda71 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomListCategoryMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM gen_custom_list_category AS tb + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomListHandleColumnMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomListHandleColumnMapper.xml new file mode 100644 index 0000000..11f584b --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomListHandleColumnMapper.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + SELECT o.id, + o.custom_list_id, + o.name, + o.view_type, + o.btn_type, + o.btn_config, + o.icon, + o.request_param, + o.width, + o.order_no + FROM gen_custom_list_handle_column AS o + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomListMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomListMapper.xml new file mode 100644 index 0000000..daa9567 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomListMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + SELECT o.id, + o.name, + o.category_id, + o.data_obj_id, + o.list_type, + o.available, + o.description, + o.create_by, + o.create_time, + o.update_by, + o.update_time + FROM gen_custom_list AS o + + + + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomListToolbarMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomListToolbarMapper.xml new file mode 100644 index 0000000..c941551 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomListToolbarMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + SELECT o.id, + o.custom_list_id, + o.name, + o.view_type, + o.btn_type, + o.btn_config, + o.icon, + o.request_param, + o.order_no + FROM gen_custom_list_toolbar AS o + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomPageCategoryMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomPageCategoryMapper.xml new file mode 100644 index 0000000..f670010 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomPageCategoryMapper.xml @@ -0,0 +1,15 @@ + + + + + + SELECT + tb.* + FROM gen_custom_page_category AS tb + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomPageMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomPageMapper.xml new file mode 100644 index 0000000..9f48ace --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomPageMapper.xml @@ -0,0 +1,46 @@ + + + + + + SELECT + o.* + FROM gen_custom_page AS o + + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorCategoryMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorCategoryMapper.xml new file mode 100644 index 0000000..debf121 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorCategoryMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM gen_custom_selector_category AS tb + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorMapper.xml new file mode 100644 index 0000000..51fb811 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenCustomSelectorMapper.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + SELECT o.id, + o.name, + o.category_id, + o.custom_list_id, + o.available, + o.description, + o.create_by, + o.create_time, + o.update_by, + o.update_time + FROM gen_custom_selector AS o + + + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenDataEntityCategoryMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenDataEntityCategoryMapper.xml new file mode 100644 index 0000000..cecb0df --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenDataEntityCategoryMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM gen_data_entity_category AS tb + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenDataEntityMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenDataEntityMapper.xml new file mode 100644 index 0000000..e3c5a9b --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenDataEntityMapper.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + SELECT o.id, + o.name, + o.category_id, + o.available, + o.description, + o.create_by, + o.create_time, + o.update_by, + o.update_time, + o.gen_status + FROM gen_data_entity AS o + + + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenDataObjDetailMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenDataObjDetailMapper.xml new file mode 100644 index 0000000..3cf68af --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenDataObjDetailMapper.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenDataObjMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenDataObjMapper.xml new file mode 100644 index 0000000..cebbbab --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenDataObjMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + SELECT o.id, + o.name, + o.category_id, + o.main_table_id, + o.main_table_alias, + o.available, + o.description, + o.create_by, + o.create_time, + o.update_by, + o.update_time + FROM gen_data_obj AS o + + + + + + + + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/mappers/gen/GenDetailColumnConfigMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenDetailColumnConfigMapper.xml new file mode 100644 index 0000000..d7ced56 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenDetailColumnConfigMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + SELECT + g.id, + g.span, + g.order_no + FROM gen_detail_column_config AS g + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenGenerateInfoMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenGenerateInfoMapper.xml new file mode 100644 index 0000000..ef611ed --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenGenerateInfoMapper.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + SELECT + i.id, + i.template_type, + i.package_name, + i.module_name, + i.biz_name, + i.class_name, + i.class_description, + i.parent_menu_id, + i.key_type, + i.author, + i.menu_code, + i.menu_name, + i.detail_span, + i.is_cache, + i.has_delete + FROM gen_generate_info AS i + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenMapper.xml new file mode 100644 index 0000000..8eb2a28 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenMapper.xml @@ -0,0 +1,33 @@ + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenQueryColumnConfigMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenQueryColumnConfigMapper.xml new file mode 100644 index 0000000..3f2cad7 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenQueryColumnConfigMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + SELECT + g.id, + g.width_type, + g.width, + g.sortable, + g.order_no + FROM gen_query_column_config AS g + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenQueryParamsColumnConfigMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenQueryParamsColumnConfigMapper.xml new file mode 100644 index 0000000..e724705 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenQueryParamsColumnConfigMapper.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + SELECT + g.id, + g.query_type, + g.order_no + FROM gen_query_params_column_config AS g + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenSimpleTableColumnMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenSimpleTableColumnMapper.xml new file mode 100644 index 0000000..879ab24 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenSimpleTableColumnMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenSimpleTableMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenSimpleTableMapper.xml new file mode 100644 index 0000000..9dcf3fc --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenSimpleTableMapper.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + SELECT + id, + table_name, + engine, + table_collation, + table_comment, + convert_type + FROM gen_simple_table + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigMapper.xml b/xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigMapper.xml new file mode 100644 index 0000000..fc2515d --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + SELECT + g.id, + g.required, + g.order_no + FROM gen_update_column_config AS g + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigService.xml b/xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigService.xml new file mode 100644 index 0000000..85db163 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/GenUpdateColumnConfigService.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM gen_data_obj_category AS tb + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/gen/SimpleDBMapper.xml b/xingyun-template/src/main/resources/mappers/gen/SimpleDBMapper.xml new file mode 100644 index 0000000..a87f8cf --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/gen/SimpleDBMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml new file mode 100644 index 0000000..f7f1813 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysDataDicCategoryMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_data_dic_category AS tb + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysDataDicItemMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysDataDicItemMapper.xml new file mode 100644 index 0000000..7682100 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysDataDicItemMapper.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.dic_id, + tb.order_no, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_data_dic_item AS tb + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysDataDicMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysDataDicMapper.xml new file mode 100644 index 0000000..556bc82 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysDataDicMapper.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.code, + tb.name, + tb.category_id, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time + FROM sys_data_dic AS tb + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysDeptMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysDeptMapper.xml new file mode 100644 index 0000000..308a9e3 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysDeptMapper.xml @@ -0,0 +1,19 @@ + + + + + + SELECT + * + FROM sys_dept + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysMenuMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysMenuMapper.xml new file mode 100644 index 0000000..8eec8a4 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysMenuMapper.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + SELECT id, + name, + path, + icon, + hidden, + display, + component_type, + component, + request_param, + parent_id, + title, + no_cache + FROM sys_menu + + + + SELECT + * + FROM sys_menu + + + + + + + + + + INSERT INTO sys_menu_collect (id, user_id, menu_id) VALUES (#{id}, #{userId}, #{menuId}) + + + DELETE FROM sys_menu_collect WHERE user_id = #{userId} AND menu_id = #{menuId} + + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysNoticeLogMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysNoticeLogMapper.xml new file mode 100644 index 0000000..67cd07a --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysNoticeLogMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + SELECT + tb.id, + tb.notice_id, + tb.user_id, + tb.readed, + tb.read_time + FROM sys_notice_log AS tb + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysNoticeMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysNoticeMapper.xml new file mode 100644 index 0000000..ba0a1b5 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysNoticeMapper.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT + tb.id, + tb.title, + tb.content, + tb.available, + tb.published, + tb.publish_time, + tb.create_by, + tb.create_time, + tb.update_by, + tb.update_time, + tb.readed_num, + tb.un_read_num + FROM sys_notice AS tb + + + + SELECT + tb.id, + tb.title, + tb.publish_time, + l.readed + FROM sys_notice_log AS l + INNER JOIN sys_notice AS tb ON tb.id = l.notice_id + + + + + UPDATE sys_notice SET readed_num = readed_num + 1, un_read_num = un_read_num - 1 WHERE id = #{id} + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysOpenDomainMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysOpenDomainMapper.xml new file mode 100644 index 0000000..9f670d5 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysOpenDomainMapper.xml @@ -0,0 +1,43 @@ + + + + + + SELECT + * + FROM sys_open_domain + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysPositionMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysPositionMapper.xml new file mode 100644 index 0000000..9b2ec66 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysPositionMapper.xml @@ -0,0 +1,48 @@ + + + + + + SELECT + * + FROM sys_position + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysRoleMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysRoleMapper.xml new file mode 100644 index 0000000..fde24b4 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysRoleMapper.xml @@ -0,0 +1,59 @@ + + + + + + SELECT + * + FROM sys_role + + + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysUserDeptMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysUserDeptMapper.xml new file mode 100644 index 0000000..7e6fd0e --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysUserDeptMapper.xml @@ -0,0 +1,22 @@ + + + + + + SELECT + ud.* + FROM sys_user_dept AS ud + INNER JOIN sys_dept AS d ON d.id = ud.dept_id + + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysUserMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysUserMapper.xml new file mode 100644 index 0000000..db63591 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysUserMapper.xml @@ -0,0 +1,99 @@ + + + + + + SELECT + u.* + FROM sys_user AS u + + + + + + + + UPDATE sys_user + SET password = #{password} + WHERE id = #{userId} + + + + UPDATE sys_user + SET email = #{email} + WHERE id = #{userId} + + + + UPDATE sys_user + SET telephone = #{telephone} + WHERE id = #{userId} + + + UPDATE sys_user + SET lock_status = TRUE + WHERE id = #{id} + + + UPDATE sys_user + SET lock_status = FALSE + WHERE id = #{id} + + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysUserPositionMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysUserPositionMapper.xml new file mode 100644 index 0000000..1d130fe --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysUserPositionMapper.xml @@ -0,0 +1,16 @@ + + + + + SELECT + up.* + FROM sys_user_position AS up + INNER JOIN sys_position AS p ON p.id = up.position_id + + + diff --git a/xingyun-template/src/main/resources/mappers/system/SysUserRoleMapper.xml b/xingyun-template/src/main/resources/mappers/system/SysUserRoleMapper.xml new file mode 100644 index 0000000..95b4ea7 --- /dev/null +++ b/xingyun-template/src/main/resources/mappers/system/SysUserRoleMapper.xml @@ -0,0 +1,15 @@ + + + + + SELECT + ur.* + FROM sys_user_role AS ur + INNER JOIN sys_role AS r ON r.id = ur.role_id + + + diff --git a/xingyun-template/src/main/resources/templates/add.vue.ftl b/xingyun-template/src/main/resources/templates/add.vue.ftl new file mode 100644 index 0000000..4fe8267 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/add.vue.ftl @@ -0,0 +1,111 @@ + + diff --git a/xingyun-template/src/main/resources/templates/api.ts.ftl b/xingyun-template/src/main/resources/templates/api.ts.ftl new file mode 100644 index 0000000..417c881 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/api.ts.ftl @@ -0,0 +1,113 @@ +import { defHttp } from '/@/utils/http/axios'; +import { PageResult } from '@/api/model/pageResult'; +import { ContentTypeEnum } from '@/enums/httpEnum'; +<#if query??>import { Query${className}Vo } from '@/api/${moduleName}/${bizName}/model/query${className}Vo'; +<#if query??>import { Query${className}Bo } from '@/api/${moduleName}/${bizName}/model/query${className}Bo'; +<#if detail??>import { ${r"Get"}${className}${r"Bo"} } from '@/api/${moduleName}/${bizName}/model/${r"get"}${className}${r"Bo"}'; +<#if create??>import { Create${className}Vo } from '@/api/${moduleName}/${bizName}/model/create${className}Vo'; +<#if update??>import { Update${className}Vo } from '@/api/${moduleName}/${bizName}/model/update${className}Vo'; + +const baseUrl = '/${moduleName}/${bizName}'; +const region = 'cloud-api'; + +<#if query??> +/** + * 查询列表 + * @param params + * @returns {Promise} + */ +export function query(params: Query${className}Vo): ${r"Promise>"} { + return defHttp.get<${r"PageResult<"}Query${className}${r"Bo>"}>( + { + url: baseUrl + '/query', + params: params, + }, + { + region, + }, + ); +} + + +<#if detail??> +/** + * 根据ID查询 + * @param ${keys[0].name} + * @returns {Promise} + */ +export function get(${keys[0].name}: ${keys[0].dataType}): ${r"Promise"} { + return defHttp.get<${r"Get"}${className}${r"Bo"}>( + { + url: baseUrl, + params: { + ${keys[0].name}, + } + }, + { + region, + }, + ); +} + + +<#if create??> +/** + * 新增 + * @param params + * @returns {Promise} + */ +export function create(params: Create${className}Vo): ${r"Promise"} { + return defHttp.post( + { + url: baseUrl, + data: params, + }, + { + contentType: ContentTypeEnum.FORM_URLENCODED, + region, + }, + ); +} + + +<#if update??> +/** + * 修改 + * @param params + * @returns {Promise} + */ +export function update(params: Update${className}Vo): ${r"Promise"} { + return defHttp.put( + { + url: baseUrl, + data: params, + }, + { + contentType: ContentTypeEnum.FORM_URLENCODED, + region, + }, + ); +} + + +<#if hasDelete> +/** + * 删除 + * @param params + * @returns {Promise} + */ +export function deleteById(${keys[0].name}: ${keys[0].dataType}): ${r"Promise"} { + return defHttp.delete( + { + url: baseUrl, + data: { + ${keys[0].name}, + }, + }, + { + region, + contentType: ContentTypeEnum.FORM_URLENCODED, + }, + ); +} + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/templates/controller.java.ftl b/xingyun-template/src/main/resources/templates/controller.java.ftl new file mode 100644 index 0000000..9be2e8c --- /dev/null +++ b/xingyun-template/src/main/resources/templates/controller.java.ftl @@ -0,0 +1,149 @@ +package ${packageName}.controller.${moduleName}; + +<#if detail??> +import ${packageName}.bo.${moduleName}.${bizName}.Get${className}Bo; + +<#if query??> +import ${packageName}.bo.${moduleName}.${bizName}.Query${className}Bo; + +<#if queryParams??> +import ${packageName}.vo.${moduleName}.${bizName}.Query${className}Vo; + +import ${packageName}.service.${moduleName}.${className}Service; +<#if create??> +import ${packageName}.vo.${moduleName}.${bizName}.Create${className}Vo; + +<#if update??> +import ${packageName}.vo.${moduleName}.${bizName}.Update${className}Vo; + +import ${packageName}.entity.${className}; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import com.lframework.starter.web.controller.DefaultBaseController; +import org.springframework.beans.factory.annotation.Autowired; +import com.lframework.starter.web.annotations.security.HasPermission; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; +import java.util.stream.Collectors; + +/** + * ${classDescription} Controller + * +<#if author??> + * @author ${author} + + */ +@Api(tags = "${classDescription}") +@Validated +@RestController +@RequestMapping("/${moduleName}/${bizName}") +public class ${className}Controller extends DefaultBaseController { + + @Autowired + private ${className}Service ${classNameProperty}Service; + <#if query?? && queryParams??> + + /** + * 查询列表 + */ + @ApiOperation("查询列表") + @HasPermission({"${moduleName}:${bizName}:query"}) + @GetMapping("/query") + public ${r"InvokeResult>"} query(@Valid Query${className}Vo vo) { + + PageResult${r"<"}${className}${r">"} pageResult = ${classNameProperty}Service.query(getPageIndex(vo), getPageSize(vo), vo); + + List${r"<"}${className}${r">"} datas = pageResult.getDatas(); + List${r"<"}Query${className}Bo${r">"} results = null; + + if (!CollectionUtil.isEmpty(datas)) { + results = datas.stream().map(Query${className}Bo::new).collect(Collectors.toList()); + } + + return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results)); + } + + <#if detail??> + + /** + * 根据ID查询 + */ + @ApiOperation("根据ID查询") + @ApiImplicitParam(value = "${keys[0].name}", name = "${keys[0].name}", paramType = "query", required = true) + @HasPermission({"${moduleName}:${bizName}:query"}) + @GetMapping + public ${r"InvokeResult"} get(<#if keys[0].dataType == 'String'>@NotBlank<#else>@NotNull(message = "${keys[0].name}不能为空!") ${keys[0].dataType} ${keys[0].name}) { + + ${className} data = ${classNameProperty}Service.findById(${keys[0].name}); + if (data == null) { + throw new DefaultClientException("${classDescription}不存在!"); + } + + Get${className}Bo result = new Get${className}Bo(data); + + return InvokeResultBuilder.success(result); + } + + <#if create??> + + /** + * 新增 + */ + @ApiOperation("新增") + @HasPermission({"${moduleName}:${bizName}:add"}) + @PostMapping + public ${r"InvokeResult"} create(@Valid Create${className}Vo vo) { + + ${classNameProperty}Service.create(vo); + + return InvokeResultBuilder.success(); + } + + <#if update??> + + /** + * 修改 + */ + @ApiOperation("修改") + @HasPermission({"${moduleName}:${bizName}:modify"}) + @PutMapping + public ${r"InvokeResult"} update(@Valid Update${className}Vo vo) { + + ${classNameProperty}Service.update(vo); + <#if isCache> + + ${classNameProperty}Service.cleanCacheByKey(vo.get${keys[0].nameProperty}()); + + + return InvokeResultBuilder.success(); + } + + <#if hasDelete> + + /** + * 根据ID删除 + */ + @ApiOperation("根据ID删除") + @ApiImplicitParam(value = "${keys[0].name}", name = "${keys[0].name}", paramType = "query", required = true) + @HasPermission({"${moduleName}:${bizName}:delete"}) + @DeleteMapping + public ${r"InvokeResult"} deleteById(<#if keys[0].dataType == 'String'>@NotBlank<#else>@NotNull(message = "${keys[0].name}不能为空!") ${keys[0].dataType} ${keys[0].name}) { + + ${classNameProperty}Service.deleteById(${keys[0].name}); + <#if isCache> + + ${classNameProperty}Service.cleanCacheByKey(${keys[0].name}); + + + return InvokeResultBuilder.success(); + } + +} diff --git a/xingyun-template/src/main/resources/templates/createvo.java.ftl b/xingyun-template/src/main/resources/templates/createvo.java.ftl new file mode 100644 index 0000000..bb4b6f8 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/createvo.java.ftl @@ -0,0 +1,51 @@ +package ${packageName}.vo.${moduleName}.${bizName}; + +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import java.io.Serializable; +import lombok.Data; + +@Data +public class Create${className}Vo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + <#list columns as column> + /** + * ${column.description} + */ + <#if column.required> + @ApiModelProperty(value = "${column.description}", required = true) + <#else> + @ApiModelProperty("${column.description}") + + <#if column.required> + @${column.validateAnno}(message = "${column.validateMsg}${column.description}!") + <#if column.fixEnum> + @IsEnum(message = "${column.validateMsg}${column.description}!", enumClass = ${column.dataType}.class) + + + <#if column.regularExpression??> + @Pattern(regexp = "${column.regularExpression?replace("\\", "\\\\")}", message = "${column.description}格式有误!") + + <#if column.dataType != 'String'> + @TypeMismatch(message = "${column.description}格式有误!") + + <#if column.isDecimalType> + <#if (column.decimals??) && column.decimals gt 0> + @IsNumberPrecision(message = "${column.description}最多允许${column.decimals}位小数!", value = ${column.decimals}) + + <#else> + <#if column.dataType == 'String' && (column.viewType == 0 || column.viewType == 1)> + <#if (column.len??) && column.len gt 0> + @Length(message = "${column.description}最多允许${column.len}个字符!") + + + + private <#if column.fixEnum>${column.enumCodeType}<#else>${column.dataType} ${column.name}; + + +} diff --git a/xingyun-template/src/main/resources/templates/createvo.ts.ftl b/xingyun-template/src/main/resources/templates/createvo.ts.ftl new file mode 100644 index 0000000..0ce281e --- /dev/null +++ b/xingyun-template/src/main/resources/templates/createvo.ts.ftl @@ -0,0 +1,10 @@ +export interface Create${className}Vo { + + <#list columns as column> + /** + * ${column.description} + */ + ${column.name}<#if !column.required>?: ${column.frontDataType}; + + +} diff --git a/xingyun-template/src/main/resources/templates/detail.vue.ftl b/xingyun-template/src/main/resources/templates/detail.vue.ftl new file mode 100644 index 0000000..2f6dead --- /dev/null +++ b/xingyun-template/src/main/resources/templates/detail.vue.ftl @@ -0,0 +1,91 @@ + + diff --git a/xingyun-template/src/main/resources/templates/entity.java.ftl b/xingyun-template/src/main/resources/templates/entity.java.ftl new file mode 100644 index 0000000..43deaad --- /dev/null +++ b/xingyun-template/src/main/resources/templates/entity.java.ftl @@ -0,0 +1,49 @@ +package ${packageName}.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import lombok.Data; + +/** + *

+ * ${classDescription} + *

+ * +<#if author??> + * @author ${author} + + */ +@Data +@TableName("${tableName}") +public class ${className} extends BaseEntity implements BaseDto { + + private static final long serialVersionUID = 1L; + + public static final String CACHE_NAME = "${className}"; + + <#list columns as column> + /** + * ${column.description} + */ + <#if !column.defaultConvertType> + <#if !column.isKey> + @TableField(value = "${column.columnName}"<#if column.fill?? && column.fill>, fill = FieldFill.${column.fillStrategy}) + <#else> + @TableId(value = "${column.columnName}"<#if column.autoIncrKey>, type = IdType.AUTO<#if column.fill?? && column.fill>, fill = FieldFill.${column.fillStrategy}<#if column.autoIncrKey>, type = IdType.AUTO) + + <#else> + <#if !column.isKey && column.fill?? && column.fill> + @TableField(fill = FieldFill.${column.fillStrategy}) + + + <#if column.defaultConvertType && column.isKey && column.autoIncrKey> + @TableId(value = "${column.columnName}", type = IdType.AUTO) + + private ${column.dataType} ${column.name}; + + +} diff --git a/xingyun-template/src/main/resources/templates/getbo.java.ftl b/xingyun-template/src/main/resources/templates/getbo.java.ftl new file mode 100644 index 0000000..8a01ec2 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/getbo.java.ftl @@ -0,0 +1,97 @@ +package ${packageName}.bo.${moduleName}.${bizName}; + +import com.fasterxml.jackson.annotation.JsonFormat; +import ${packageName}.entity.${className}; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + + +import lombok.Data; + +/** + *

+ * ${classDescription} GetBo + *

+ * +<#if author??> + * @author ${author} + + */ +@Data +public class Get${className}Bo extends BaseBo${r"<"}${className}${r">"} { + + /** + * ${keys[0].description} + */ + @ApiModelProperty("${keys[0].description}") + private ${keys[0].dataType} ${keys[0].name}; + + <#list columns as column> + /** + * ${column.description} + */ + @ApiModelProperty("${column.description}") + <#if column.dataType == 'LocalDateTime'> + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + + <#if column.dataType == 'LocalDate'> + @JsonFormat(pattern = StringPool.DATE_PATTERN) + + <#if column.dataType == 'LocalTime'> + @JsonFormat(pattern = StringPool.TIME_PATTERN) + + private <#if column.fixEnum>${column.enumCodeType}<#else>${column.dataType} ${column.name}; + + <#if column.dataDicCode??> + /** + * ${column.description}字典值 + */ + @ApiModelProperty("${column.description}字典值") + private String ${column.name}DicValue; + + + + public Get${className}Bo() { + + } + + public Get${className}Bo(${className} dto) { + + super(dto); + } + + @Override + public BaseBo${r"<"}${className}${r">"} convert(${className} dto) { + <#if hasFixEnum> + return super.convert(dto<#list columns as column><#if column.fixEnum>, Get${className}Bo::get${column.nameProperty}); + <#else> + return super.convert(dto); + + } + + @Override + protected void afterInit(${className} dto) { + + <#list columns as column> + <#if column.dataDicCode??> + ISysDataDicItemService sysDataDicItemService = ApplicationUtil.getBean(ISysDataDicItemService.class); + + <#break> + + + <#list columns as column> + <#if column.fixEnum> + this.${column.name} = dto.get${column.nameProperty}().getCode(); + + <#elseif column.dataDicCode??> + if (!StringUtil.isBlank(dto.get${column.nameProperty}())) { + String[] ${column.name}DicArr = dto.get${column.nameProperty}().split(StringPool.DATA_DIC_SPLIT); + this.${column.name}DicValue = sysDataDicItemService.findByCode(${column.name}DicArr[0], ${column.name}DicArr[1]).getName(); + } + + + + } +} diff --git a/xingyun-template/src/main/resources/templates/getbo.ts.ftl b/xingyun-template/src/main/resources/templates/getbo.ts.ftl new file mode 100644 index 0000000..d4908ca --- /dev/null +++ b/xingyun-template/src/main/resources/templates/getbo.ts.ftl @@ -0,0 +1,29 @@ +/** + * ${classDescription} GetBo + * +<#if author??> + * @author ${author} + + */ +export interface Get${className}Bo { + + /** + * ${keys[0].description} + */ + ${keys[0].name}: ${keys[0].frontDataType}; + + <#list columns as column> + /** + * ${column.description} + */ + ${column.name}: ${column.frontDataType}; + + <#if column.dataDicCode??> + /** + * ${column.description}字典值 + */ + ${column.name}DicValue: string; + + + +} diff --git a/xingyun-template/src/main/resources/templates/index.vue.ftl b/xingyun-template/src/main/resources/templates/index.vue.ftl new file mode 100644 index 0000000..d330763 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/index.vue.ftl @@ -0,0 +1,205 @@ + + + + diff --git a/xingyun-template/src/main/resources/templates/input-components.ftl b/xingyun-template/src/main/resources/templates/input-components.ftl new file mode 100644 index 0000000..f0f49c0 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/input-components.ftl @@ -0,0 +1,78 @@ +<#if column.viewType == 0> + max-length="${column.len}" allow-clear /> +<#elseif column.viewType == 1> + max-length="${column.len}" allow-clear /> +<#elseif column.viewType == 2> + +<#elseif column.viewType == 3> + +<#elseif column.viewType == 4> + + +<#elseif column.viewType == 5> +<#if column.fixEnum> + + {{ item.desc }} + +<#else> +<#if column.hasAvailableTag> + + {{ item.desc }} + +<#else> + + + + + + +<#elseif column.viewType == 6> +<#if column.dataType == 'LocalDateTime'> +
+ + + +
+<#else> +
+ + + +
+ +<#elseif column.viewType == 7> + +<#elseif column.viewType == 8> + + diff --git a/xingyun-template/src/main/resources/templates/mapper.java.ftl b/xingyun-template/src/main/resources/templates/mapper.java.ftl new file mode 100644 index 0000000..4a0f8d0 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/mapper.java.ftl @@ -0,0 +1,35 @@ +package ${packageName}.mappers; + +import ${packageName}.entity.${className}; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +<#if queryParams??> +import ${packageName}.vo.${moduleName}.${bizName}.Query${className}Vo; + +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * ${classDescription} Mapper 接口 + *

+ * +<#if author??> + * @author ${author} + + */ +public interface ${className}Mapper extends BaseMapper<${className}> { + + <#if queryParams??> + /** + * 查询列表 + * @param vo + * @return + */ + List${r"<"}${className}${r">"} query(@Param("vo") Query${className}Vo vo); + +} diff --git a/xingyun-template/src/main/resources/templates/mapper.list.xml.ftl b/xingyun-template/src/main/resources/templates/mapper.list.xml.ftl new file mode 100644 index 0000000..f77ad20 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/mapper.list.xml.ftl @@ -0,0 +1,49 @@ + + + + + + <#list entity.columns as column> + <#if column.isKey> + + <#else> + + + + + + + SELECT + <#list entity.columns as column> + tb.${column.columnName}<#if column_index != entity.columns?size - 1>, + + FROM ${entity.tableName} AS tb + + + <#if queryParams??> + + + diff --git a/xingyun-template/src/main/resources/templates/modify.vue.ftl b/xingyun-template/src/main/resources/templates/modify.vue.ftl new file mode 100644 index 0000000..3bf5a73 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/modify.vue.ftl @@ -0,0 +1,128 @@ + + diff --git a/xingyun-template/src/main/resources/templates/query-type-sql.ftl b/xingyun-template/src/main/resources/templates/query-type-sql.ftl new file mode 100644 index 0000000..855edb9 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/query-type-sql.ftl @@ -0,0 +1,27 @@ +<#if column.queryType == 0> +AND tb.${column.columnName} = ${r"#{vo."}${column.name}${r"}"} +<#elseif column.queryType == 1> +AND tb.${column.columnName} > ${r"#{vo."}${column.name}${r"}"} +<#elseif column.queryType == 2> +AND tb.${column.columnName} >= ${r"#{vo."}${column.name}${r"}"} +<#elseif column.queryType == 3> + +<#elseif column.queryType == 4> + +<#elseif column.queryType == 5> +AND tb.${column.columnName} != ${r"#{vo."}${column.name}${r"}"} +<#elseif column.queryType == 6> +AND tb.${column.columnName} IN (${r"#{vo."}${column.name}${r"}"}) +<#elseif column.queryType == 7> +AND tb.${column.columnName} NOT IN (${r"#{vo."}${column.name}${r"}"}) +<#elseif column.queryType == 8> +AND tb.${column.columnName} LIKE CONCAT('%', ${r"#{vo."}${column.name}${r"}"}) +<#elseif column.queryType == 9> +AND tb.${column.columnName} LIKE CONCAT(${r"#{vo."}${column.name}${r"}"}, '%') +<#elseif column.queryType == 10> +AND tb.${column.columnName} LIKE CONCAT('%', ${r"#{vo."}${column.name}${r"}"}, '%') + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/templates/querybo.java.ftl b/xingyun-template/src/main/resources/templates/querybo.java.ftl new file mode 100644 index 0000000..2284bf8 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/querybo.java.ftl @@ -0,0 +1,89 @@ +package ${packageName}.bo.${moduleName}.${bizName}; + +import com.fasterxml.jackson.annotation.JsonFormat; +import ${packageName}.entity.${className}; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + + +import lombok.Data; + +/** + *

+ * ${classDescription} QueryBo + *

+ * +<#if author??> + * @author ${author} + + */ +@Data +public class Query${className}Bo extends BaseBo${r"<"}${className}${r">"} { + + /** + * ${keys[0].description} + */ + @ApiModelProperty("${keys[0].description}") + private ${keys[0].dataType} ${keys[0].name}; + +<#list columns as column> + /** + * ${column.description} + */ + @ApiModelProperty("${column.description}") + <#if column.dataType == 'LocalDateTime'> + @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN) + + <#if column.dataType == 'LocalDate'> + @JsonFormat(pattern = StringPool.DATE_PATTERN) + + <#if column.dataType == 'LocalTime'> + @JsonFormat(pattern = StringPool.TIME_PATTERN) + + private <#if column.fixEnum>${column.enumCodeType}<#else>${column.dataType} ${column.name}; + + + public Query${className}Bo() { + + } + + public Query${className}Bo(${className} dto) { + + super(dto); + } + + @Override + public BaseBo${r"<"}${className}${r">"} convert(${className} dto) { + <#if hasFixEnum> + return super.convert(dto<#list columns as column><#if column.fixEnum>, Query${className}Bo::get${column.nameProperty}); + <#else> + return super.convert(dto); + + } + + @Override + protected void afterInit(${className} dto) { + + <#list columns as column> + <#if column.dataDicCode??> + ISysDataDicItemService sysDataDicItemService = ApplicationUtil.getBean(ISysDataDicItemService.class); + + <#break> + + + <#list columns as column> + <#if column.fixEnum> + this.${column.name} = dto.get${column.nameProperty}().getCode(); + + <#elseif column.dataDicCode??> + if (!StringUtil.isBlank(dto.get${column.nameProperty}())) { + String[] ${column.name}DicArr = dto.get${column.nameProperty}().split(StringPool.DATA_DIC_SPLIT); + this.${column.name} = sysDataDicItemService.findByCode(${column.name}DicArr[0], ${column.name}DicArr[1]).getName(); + } + + + + } +} diff --git a/xingyun-template/src/main/resources/templates/querybo.ts.ftl b/xingyun-template/src/main/resources/templates/querybo.ts.ftl new file mode 100644 index 0000000..6d2c4f6 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/querybo.ts.ftl @@ -0,0 +1,22 @@ +/** + * ${classDescription} QueryBo + * +<#if author??> + * @author ${author} + + */ +export interface Query${className}Bo { + + /** + * ${keys[0].description} + */ + ${keys[0].name}: ${keys[0].frontDataType}; + +<#list columns as column> + /** + * ${column.description} + */ + ${column.name}: ${column.frontDataType}; + + +} diff --git a/xingyun-template/src/main/resources/templates/queryvo.java.ftl b/xingyun-template/src/main/resources/templates/queryvo.java.ftl new file mode 100644 index 0000000..64374a5 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/queryvo.java.ftl @@ -0,0 +1,57 @@ +package ${packageName}.vo.${moduleName}.${bizName}; + +import lombok.Data; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import java.io.Serializable; + +@Data +public class Query${className}Vo extends PageVo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + <#list columns as column> + <#if column.viewType != 6> + /** + * ${column.description} + */ + @ApiModelProperty("${column.description}") + + <#if column.fixEnum> + <#if column.dataType != 'String'> + @TypeMismatch(message = "${column.description}格式有误!") + + @IsEnum(message = "${column.description}格式有误!", enumClass = ${column.dataType}.class) + private ${column.enumCodeType} ${column.name}; + <#else> + <#if column.viewType == 6> + /** + * ${column.description} 起始时间 + */ + @ApiModelProperty("${column.description} 起始时间") + <#if column.dataType != 'String'> + @TypeMismatch(message = "${column.description}起始时间格式有误!") + + private ${column.dataType} ${column.name}Start; + + /** + * ${column.description} 截止时间 + */ + @ApiModelProperty("${column.description} 截止时间") + <#if column.dataType != 'String'> + @TypeMismatch(message = "${column.description}截止时间格式有误!") + + private ${column.dataType} ${column.name}End; + <#else> + <#if column.dataType != 'String'> + @TypeMismatch(message = "${column.description}格式有误!") + + private ${column.dataType} ${column.name}; + + + + +} diff --git a/xingyun-template/src/main/resources/templates/queryvo.ts.ftl b/xingyun-template/src/main/resources/templates/queryvo.ts.ftl new file mode 100644 index 0000000..c229363 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/queryvo.ts.ftl @@ -0,0 +1,25 @@ +import { PageVo } from '@/api/model/pageVo'; + +export interface Query${className}Vo extends PageVo { + + <#list columns as column> + <#if column.viewType != 6> + /** + * ${column.description} + */ + ${column.name}: ${column.frontDataType}; + + <#if column.viewType == 6> + /** + * ${column.description} 起始时间 + */ + ${column.name}Start: ${column.frontDataType}; + + /** + * ${column.description} 截止时间 + */ + ${column.name}End: ${column.frontDataType}; + + + +} diff --git a/xingyun-template/src/main/resources/templates/service.java.ftl b/xingyun-template/src/main/resources/templates/service.java.ftl new file mode 100644 index 0000000..6262ed1 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/service.java.ftl @@ -0,0 +1,79 @@ +package ${packageName}.service.${moduleName}; + +<#if create??> +import ${packageName}.vo.${moduleName}.${bizName}.Create${className}Vo; + +<#if queryParams??> +import ${packageName}.vo.${moduleName}.${bizName}.Query${className}Vo; + +<#if update??> +import ${packageName}.vo.${moduleName}.${bizName}.Update${className}Vo; + +import ${packageName}.entity.${className}; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import java.util.Collection; +import java.util.List; + +/** + * ${classDescription} Service +<#if author??> + * + * @author ${author} + + */ +public interface ${className}Service extends BaseMpService${r"<"}${className}${r">"} { + + <#if queryParams??> + /** + * 查询列表 + * @return + */ + PageResult${r"<"}${className}${r">"} query(Integer pageIndex, Integer pageSize, Query${className}Vo vo); + + + <#if queryParams??> + /** + * 查询列表 + * @param vo + * @return + */ + ${r"List<"}${className}${r">"} query(Query${className}Vo vo); + + + /** + * 根据ID查询 + * @param ${keys[0].name} + * @return + */ + ${className} findById(<#list keys as key>${key.dataType} ${key.name}<#if key_index != keys?size - 1>, ); + + <#if create??> + /** + * 创建 + * @param vo + * @return + */ + ${create.keys[0].dataType} create(Create${className}Vo vo); + + + <#if update??> + /** + * 修改 + * @param vo + */ + void update(Update${className}Vo vo); + + + <#if hasDelete> + /** + * 根据ID删除 + * @param ${keys[0].name} + * @return + */ + void deleteById(<#list keys as key>${key.dataType} ${key.name}<#if key_index != keys?size - 1>, ); + +} diff --git a/xingyun-template/src/main/resources/templates/serviceimpl.java.ftl b/xingyun-template/src/main/resources/templates/serviceimpl.java.ftl new file mode 100644 index 0000000..bd9483c --- /dev/null +++ b/xingyun-template/src/main/resources/templates/serviceimpl.java.ftl @@ -0,0 +1,167 @@ +package ${packageName}.impl.${moduleName}; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.pagehelper.PageInfo; +import ${packageName}.entity.${className}; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import ${packageName}.mappers.${className}Mapper; +import ${packageName}.service.${moduleName}.${className}Service; +<#if create??> +import ${packageName}.vo.${moduleName}.${bizName}.Create${className}Vo; + +<#if queryParams??> +import ${packageName}.vo.${moduleName}.${bizName}.Query${className}Vo; + +<#if update??> +import ${packageName}.vo.${moduleName}.${bizName}.Update${className}Vo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.List; + +@Service +public class ${className}ServiceImpl extends BaseMpServiceImpl${r"<"}${className}Mapper, ${className}${r">"} implements ${className}Service { +<#if queryParams??> + + @Override + public PageResult${r"<"}${className}${r">"} query(Integer pageIndex, Integer pageSize, Query${className}Vo vo) { + + Assert.greaterThanZero(pageIndex); + Assert.greaterThanZero(pageSize); + + PageHelperUtil.startPage(pageIndex, pageSize); + List${r"<"}${className}${r">"} datas = this.query(vo); + + return PageResultUtil.convert(new PageInfo<>(datas)); + } + +<#if queryParams??> + + @Override + public List${r"<"}${className}${r">"} query(Query${className}Vo vo) { + + return getBaseMapper().query(vo); + } + + +<#if isCache> + @Cacheable(value = ${className}.CACHE_NAME, key = "@cacheVariables.tenantId() + #${keys[0].name}", unless = "#result == null") + + @Override + public ${className} findById(<#list keys as key>${key.dataType} ${key.name}<#if key_index != keys?size - 1>, ) { + + return getBaseMapper().selectById(${keys[0].name}); + } +<#if create??> + + @OpLog(type = 99, name = "新增${classDescription},ID:{}", params = ${r'{"#'}${create.keys[0].name}${r'"}'}) + @Transactional(rollbackFor = Exception.class) + @Override + public ${create.keys[0].dataType} create(Create${className}Vo vo) { + + ${className} data = new ${className}(); + <#if create.appointId> + data.set${create.keys[0].nameProperty}(${create.idCode}); + + <#list create.columns as column> + <#if column.required> + <#if column.fixEnum> + data.set${column.nameProperty}(EnumUtil.getByCode(${column.dataType}.class, vo.get${column.nameProperty}())); + <#else> + data.set${column.nameProperty}(vo.get${column.nameProperty}()); + + <#else> + <#if column.dataType == 'String'> + if (!StringUtil.isBlank(vo.get${column.nameProperty}())) { + data.set${column.nameProperty}(vo.get${column.nameProperty}()); + } + <#else> + if (vo.get${column.nameProperty}() != null) { + <#if column.fixEnum> + data.set${column.nameProperty}(EnumUtil.getByCode(${column.dataType}.class, vo.get${column.nameProperty}())); + <#else> + data.set${column.nameProperty}(vo.get${column.nameProperty}()); + + } + + + + + getBaseMapper().insert(data); + + OpLogUtil.setVariable("${create.keys[0].name}", <#if create.keys[0].dataType == 'String'>data.get${create.keys[0].nameProperty}()<#else>String.valueOf(data.get${create.keys[0].nameProperty}())); + OpLogUtil.setExtra(vo); + + return data.get${create.keys[0].nameProperty}(); + } + +<#if update??> + + @OpLog(type = 99, name = "修改${classDescription},ID:{}", params = ${r'{"#'}${update.keys[0].name}${r'"}'}) + @Transactional(rollbackFor = Exception.class) + @Override + public void update(Update${className}Vo vo) { + + ${className} data = getBaseMapper().selectById(vo.get${update.keys[0].nameProperty}()); + if (ObjectUtil.isNull(data)) { + throw new DefaultClientException("${classDescription}不存在!"); + } + + LambdaUpdateWrapper${r"<"}${className}${r">"} updateWrapper = Wrappers.lambdaUpdate(${className}.class) + <#list update.columns as column> + <#if column.required> + <#if column.fixEnum> + .set(${className}::get${column.nameProperty}, EnumUtil.getByCode(${column.dataType}.class, vo.get${column.nameProperty}())) + <#else> + .set(${className}::get${column.nameProperty}, vo.get${column.nameProperty}()) + + <#else> + <#if column.dataType == 'String'> + .set(${className}::get${column.nameProperty}, StringUtil.isBlank(vo.get${column.nameProperty}()) ? null : vo.get${column.nameProperty}()) + <#else> + <#if column.fixEnum> + .set(${className}::get${column.nameProperty}, vo.get${column.nameProperty}() == null ? null : EnumUtil.getByCode(${column.dataType}.class, vo.get${column.nameProperty}())) + <#else> + .set(${className}::get${column.nameProperty}, vo.get${column.nameProperty}() == null ? null : vo.get${column.nameProperty}()) + + + + + .eq(${className}::get${update.keys[0].nameProperty}, vo.get${update.keys[0].nameProperty}()); + + getBaseMapper().update(updateWrapper); + + OpLogUtil.setVariable("${update.keys[0].name}", <#if update.keys[0].dataType == 'String'>data.get${update.keys[0].nameProperty}()<#else>String.valueOf(data.get${update.keys[0].nameProperty}())); + OpLogUtil.setExtra(vo); + } + + <#if hasDelete> + + @OpLog(type = 99, name = "删除${classDescription},ID:{}", params = ${r'{"#'}${keys[0].name}${r'"}'}) + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteById(<#list keys as key>${key.dataType} ${key.name}<#if key_index != keys?size - 1>, ) { + + getBaseMapper().deleteById(<#list keys as key>${key.name}<#if key_index != keys?size - 1>, ); + } + + + <#if isCache> + @CacheEvict(value = ${className}.CACHE_NAME, key = "@cacheVariables.tenantId() + #key") + + @Override + public void cleanCacheByKey(Serializable key) { + + } +} diff --git a/xingyun-template/src/main/resources/templates/sql.ftl b/xingyun-template/src/main/resources/templates/sql.ftl new file mode 100644 index 0000000..789c320 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/sql.ftl @@ -0,0 +1,9 @@ +-- 功能菜单SQL +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `component`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('${menuId}', '${menuCode}', '${className}', '${menuName}', '/${moduleName}/${bizName}/index', <#if parentMenuId??>'${parentMenuId}'<#else>NULL, '/${moduleName}/${bizName}', 0, 1, 0, '${moduleName}:${bizName}:query', 0, 1, '', '1', NOW(), '1', NOW()); +-- 权限SQL +<#if create??> +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `component`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('${IdUtil.getId()}', '${menuCode}001', '', '新增${classDescription}', '', '${menuId}', '', 0, 2, 0, '${moduleName}:${bizName}:add', 0, 1, '', '1', NOW(), '1', NOW()); + +<#if update??> +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `component`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('${IdUtil.getId()}', '${menuCode}002', '', '修改${classDescription}', '', '${menuId}', '', 0, 2, 0, '${moduleName}:${bizName}:modify', 0, 1, '', '1', NOW(), '1', NOW()); + \ No newline at end of file diff --git a/xingyun-template/src/main/resources/templates/updatevo.java.ftl b/xingyun-template/src/main/resources/templates/updatevo.java.ftl new file mode 100644 index 0000000..7e63292 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/updatevo.java.ftl @@ -0,0 +1,62 @@ +package ${packageName}.vo.${moduleName}.${bizName}; + +import lombok.Data; +<#if importPackages??> + <#list importPackages as p> +import ${p}; + + +import java.io.Serializable; + +@Data +public class Update${className}Vo implements BaseVo, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ${keys[0].description} + */ + @ApiModelProperty(value = "${keys[0].description}", required = true) +<#if keys[0].dataType == 'String'> + @NotBlank(message = "${keys[0].name}不能为空!") +<#else> + @NotNull(message = "${keys[0].name}不能为空!") + + private ${keys[0].dataType} ${keys[0].name}; + +<#list columns as column> + /** + * ${column.description} + */ + <#if column.required> + @ApiModelProperty(value = "${column.description}", required = true) + <#else> + @ApiModelProperty("${column.description}") + + <#if column.dataType != 'String'> + @TypeMismatch(message = "${column.description}格式有误!") + + <#if column.required> + @${column.validateAnno}(message = "${column.validateMsg}${column.description}!") + <#if column.fixEnum> + @IsEnum(message = "${column.validateMsg}${column.description}!", enumClass = ${column.dataType}.class) + + + <#if column.regularExpression??> + @Pattern(regexp = "${column.regularExpression?replace("\\", "\\\\")}", message = "${column.description}格式有误!") + + <#if column.isDecimalType> + <#if (column.decimals??) && column.decimals gt 0> + @IsNumberPrecision(message = "${column.description}最多允许${column.decimals}位小数!", value = ${column.decimals}) + + <#else> + <#if column.dataType == 'String' && (column.viewType == 0 || column.viewType == 1)> + <#if (column.len??) && column.len gt 0> + @Length(message = "${column.description}最多允许${column.len}个字符!") + + + + private <#if column.fixEnum>${column.enumCodeType}<#else>${column.dataType} ${column.name}; + + +} diff --git a/xingyun-template/src/main/resources/templates/updatevo.ts.ftl b/xingyun-template/src/main/resources/templates/updatevo.ts.ftl new file mode 100644 index 0000000..747d111 --- /dev/null +++ b/xingyun-template/src/main/resources/templates/updatevo.ts.ftl @@ -0,0 +1,17 @@ + +export interface Update${className}Vo { + + /** + * ${keys[0].description} + */ + ${keys[0].name}: ${keys[0].frontDataType}; + +<#list columns as column> + /** + * ${column.description} + */ + + ${column.name}<#if !column.required>?: ${column.frontDataType}; + + +}

p1gtN*D6_yz-$f$E~9ouP~TIHm-z`{s%A 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 E0o??6YybcN literal 0 HcmV?d00001 diff --git a/screenshots/7.jpg b/screenshots/7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ab1db12cb2bf18c420bd0e782bd661fc3be205f7 GIT binary patch literal 151753 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 q49=^lFF=HpwFp2y|N(zJ|0Y;&0#rRXwV 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≻}L@4!!EH<9A;qCbU@QQpqHD|J?LLs6Qfl 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 + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-api + 【${project.artifactId}】Api接口层 + + + + com.lframework + xingyun-common + + + com.lframework + xingyun-basedata + + + + com.lframework + xingyun-sc + + + + com.lframework + xingyun-settle + + + + com.lframework + xingyun-chart + + + + com.lframework + xingyun-template + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + + copy-resources-to-target + package + + copy-resources + + + ${project.build.directory} + + + ${project.basedir} + true + + Dockerfile + + + + ${project.basedir}/src/main/resources + true + + scripts/* + + + + + + + + + + + src/main/resources + true + + application.yml + + + + src/main/resources + false + + ** + + + db/** + scripts/* + + + + + diff --git a/xingyun-api/src/main/java/com/lframework/xingyun/api/XingYunApiApplication.java b/xingyun-api/src/main/java/com/lframework/xingyun/api/XingYunApiApplication.java new file mode 100644 index 0000000..b59dd6c --- /dev/null +++ b/xingyun-api/src/main/java/com/lframework/xingyun/api/XingYunApiApplication.java @@ -0,0 +1,61 @@ +package com.lframework.xingyun.api; + +import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver; +import com.lframework.starter.web.annotations.locker.EnableLock; +import com.lframework.starter.web.annotations.locker.LockType; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +@EnableLock(type = LockType.REDIS) +@ServletComponentScan(basePackages = {"com.lframework.xingyun"}) +@SpringBootApplication(scanBasePackages = {"com.lframework.xingyun"}) +@MapperScan({"com.lframework.xingyun.**.mappers"}) +public class XingYunApiApplication { + + public static void main(String[] args) { + + SpringApplication.run(XingYunApiApplication.class, args); + } + + /** + * Swagger 自定义配置信息 请自行修改 + */ + @Configuration + public static class SwaggerApiConfiguration { + + @Bean(value = "defaultApi") + public Docket defaultApi(OpenApiExtensionResolver openApiExtensionResolver) { + + Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName("星云ERP") + .select() + .apis(RequestHandlerSelectors.basePackage("com.lframework.xingyun.api") + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.basedata")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.chart")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.core")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.sc")) + .or(RequestHandlerSelectors.basePackage("com.lframework.xingyun.settle"))) + .paths(PathSelectors.any()) + .build().extensions(openApiExtensionResolver.buildSettingExtensions()); + return docket; + } + + // 可以修改内容 但是不要删除这个Bean + @Bean + public ApiInfo apiInfo() { + + return new ApiInfoBuilder().title("星云ERP接口文档").description("# 星云ERP接口文档") + .contact("lframework@163.com") + .build(); + } + } +} diff --git a/xingyun-api/src/main/java/lombok.config b/xingyun-api/src/main/java/lombok.config new file mode 100644 index 0000000..8e37527 --- /dev/null +++ b/xingyun-api/src/main/java/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling=true +lombok.equalsAndHashCode.callSuper=call \ No newline at end of file diff --git a/xingyun-api/src/main/resources/application-dev.yml b/xingyun-api/src/main/resources/application-dev.yml new file mode 100644 index 0000000..cf606a9 --- /dev/null +++ b/xingyun-api/src/main/resources/application-dev.yml @@ -0,0 +1,83 @@ +logging: + pattern: + console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint}|%clr(%5p)|%clr(${PID:- }){magenta}|%clr(%15.15t){faint}|%clr(${spring.application.name}){cyan}|%clr(%X{X-B3-TraceId:-N/A}){blue}|%X{X-B3-SpanId:-N/A}|%clr(%-40.40logger{39}){cyan}|%m%n%wEx" + file: ${logging.pattern.console} + level: + com.lframework: DEBUG + +spring: + servlet: + multipart: + #临时文件路径 + location: D:\tmp\tmp-datas + datasource: + dynamic: + # 设置默认数据源 + primary: master + # 是否严格匹配数据源 未匹配到指定数据源时true抛异常,false使用默认数据源 + strict: true + datasource: + master: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:1234/platform?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 + username: platform + password: wnaHZEmN6BPTTR2M + druid: + initial-size: 10 + min-idle: 10 + max-active: 200 + max-wait: 60000 + time-between-eviction-runs-millis: 300000 + validation-query: SELECT 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + filters: stat + #redis配置,这个redis用来缓存业务数据 + redis: + #地址 + host: 127.0.0.1 + #端口,默认为6379 + port: 6379 + #数据库 + database: 0 + #密码 + password: + #连接超时时间 + timeout: 10s + lettuce: + pool: + #连接池中的最小空闲连接 + min-idle: 0 + #连接池中的最大空闲连接 + max-idle: 8 + #连接池的最大数据库连接数 + max-active: 8 + #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + +sa-token: + # 配置 Sa-Token 单独使用的 Redis 连接,将业务和鉴权独立 + alone-redis: + # Redis数据库索引(默认为0),最好与业务数据的redis隔离 + database: 1 + # Redis服务器地址 + host: ${spring.redis.host} + # Redis服务器连接端口 + port: ${spring.redis.port} + # Redis服务器连接密码(默认为空) + password: ${spring.redis.password} + # 连接超时时间 + timeout: ${spring.redis.timeout} + +jugg: + upload: + #下载时的baseUrl,与domain的区别:会在url后面拼接/**作为静态资源的url,而domain是后端系统的具体域名,下载时的完整url例如:upload.domain + upload.url/xxx.jpg + url: /oss + #下载时的域名 + domain: http://localhost:8080 + #上传文件的路径 + location: D:\upload\upload-data diff --git a/xingyun-api/src/main/resources/application-prod.yml b/xingyun-api/src/main/resources/application-prod.yml new file mode 100644 index 0000000..ab4431b --- /dev/null +++ b/xingyun-api/src/main/resources/application-prod.yml @@ -0,0 +1,87 @@ +server: + #端口 + port: 10062 +logging: + pattern: + console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint}|%clr(%5p)|%clr(${PID:- }){magenta}|%clr(%15.15t){faint}|%clr(${spring.application.name}){cyan}|%clr(%X{X-B3-TraceId:-N/A}){blue}|%X{X-B3-SpanId:-N/A}|%clr(%-40.40logger{39}){cyan}|%m%n%wEx" + file: ${logging.pattern.console} + file: + name: logs/${spring.application.name}.log + max-history: 14 + +spring: + servlet: + multipart: + #临时文件路径 + location: /mnt/erp.fpvone.cn/tmp-datas + datasource: + dynamic: + # 设置默认数据源 + primary: master + # 是否严格匹配数据源 未匹配到指定数据源时true抛异常,false使用默认数据源 + strict: true + datasource: + master: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/platform?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 + username: platform + password: wnaHZEmN6BPTTR2M + druid: + initial-size: 10 + min-idle: 10 + max-active: 200 + max-wait: 60000 + time-between-eviction-runs-millis: 300000 + validation-query: SELECT 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + filters: stat + #redis配置,这个redis用来缓存业务数据 + redis: + #地址 + host: 127.0.0.1 + #端口,默认为6379 + port: 6379 + #数据库 + database: 0 + #密码 + password: + #连接超时时间 + timeout: 10s + lettuce: + pool: + #连接池中的最小空闲连接 + min-idle: 0 + #连接池中的最大空闲连接 + max-idle: 8 + #连接池的最大数据库连接数 + max-active: 8 + #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + +sa-token: + # 配置 Sa-Token 单独使用的 Redis 连接,将业务和鉴权独立 + alone-redis: + # Redis数据库索引(默认为0),最好与业务数据的redis隔离 + database: 1 + # Redis服务器地址 + host: ${spring.redis.host} + # Redis服务器连接端口 + port: ${spring.redis.port} + # Redis服务器连接密码(默认为空) + password: ${spring.redis.password} + # 连接超时时间 + timeout: ${spring.redis.timeout} + +jugg: + upload: + #下载时的baseUrl,与domain的区别:会在url后面拼接/**作为静态资源的url,而domain是后端系统的具体域名,下载时的完整url例如:upload.domain + upload.url/xxx.jpg + url: /oss + #下载时的域名 + domain: http://localhost:10662 + #上传文件的路径 + location: /mnt/erp.fpvone.cn/upload \ No newline at end of file diff --git a/xingyun-api/src/main/resources/application-test.yml b/xingyun-api/src/main/resources/application-test.yml new file mode 100644 index 0000000..8733a14 --- /dev/null +++ b/xingyun-api/src/main/resources/application-test.yml @@ -0,0 +1,84 @@ +logging: + pattern: + console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint}|%clr(%5p)|%clr(${PID:- }){magenta}|%clr(%15.15t){faint}|%clr(${spring.application.name}){cyan}|%clr(%X{X-B3-TraceId:-N/A}){blue}|%X{X-B3-SpanId:-N/A}|%clr(%-40.40logger{39}){cyan}|%m%n%wEx" + file: ${logging.pattern.console} + file: + name: logs/${spring.application.name}.log + max-history: 14 + +spring: + servlet: + multipart: + #临时文件路径 + location: D:\tmp\tmp-datas + datasource: + dynamic: + # 设置默认数据源 + primary: master + # 是否严格匹配数据源 未匹配到指定数据源时true抛异常,false使用默认数据源 + strict: true + datasource: + master: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/platform?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8 + username: root + password: password + druid: + initial-size: 10 + min-idle: 10 + max-active: 200 + max-wait: 60000 + time-between-eviction-runs-millis: 300000 + validation-query: SELECT 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + filters: stat + #redis配置,这个redis用来缓存业务数据 + redis: + #地址 + host: 127.0.0.1 + #端口,默认为6379 + port: 6379 + #数据库 + database: 0 + #密码 + password: password + #连接超时时间 + timeout: 10s + lettuce: + pool: + #连接池中的最小空闲连接 + min-idle: 0 + #连接池中的最大空闲连接 + max-idle: 8 + #连接池的最大数据库连接数 + max-active: 8 + #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + +sa-token: + # 配置 Sa-Token 单独使用的 Redis 连接,将业务和鉴权独立 + alone-redis: + # Redis数据库索引(默认为0),最好与业务数据的redis隔离 + database: 1 + # Redis服务器地址 + host: ${spring.redis.host} + # Redis服务器连接端口 + port: ${spring.redis.port} + # Redis服务器连接密码(默认为空) + password: ${spring.redis.password} + # 连接超时时间 + timeout: ${spring.redis.timeout} + +jugg: + upload: + #下载时的baseUrl,与domain的区别:会在url后面拼接/**作为静态资源的url,而domain是后端系统的具体域名,下载时的完整url例如:upload.domain + upload.url/xxx.jpg + url: /oss + #下载时的域名 + domain: http://localhost:8080 + #上传文件的路径 + location: D:\upload\upload-data diff --git a/xingyun-api/src/main/resources/application.yml b/xingyun-api/src/main/resources/application.yml new file mode 100644 index 0000000..fb72edb --- /dev/null +++ b/xingyun-api/src/main/resources/application.yml @@ -0,0 +1,207 @@ +server: + #端口 + port: 8080 +spring: + application: + name: @project.artifactId@ + profiles: + active: dev + servlet: + multipart: + #是否开启文件上传 + enabled: true + #单个文件最大值 + max-file-size: 10MB + #请求中所有文件的最大值 + max-request-size: 100MB + #将文件写入磁盘的阈值 + #file-size-threshold: 0 + #是否要延迟解析文件 + #resolve-lazily: false + quartz: + jdbc: + initialize-schema: never + job-store-type: jdbc + wait-for-jobs-to-complete-on-shutdown: true + #时间格式 + jackson: + date-format: yyyy-MM-dd HH:mm:ss + default-property-inclusion: non_null + #使用redis存储SESSION + session: + store-type: redis + +knife4j: + enable: true + setting: + language: zh-CN + # 是否显示界面中SwaggerModel功能 + enableSwaggerModels: false + # 是否显示界面中"文档管理"功能 + enableDocumentManage: true + # 是否默认显示底部Footer + enableFooter: false + # 是否自定义Footer + enableFooterCustom: true + # 自定义Footer内容(支持Markdown语法) + footerCustomContent: Apache License 2.0 | Copyright 2019-[星云ERP](https://gitee.com/lframework/xingyun) + # 是否开启调试 + enableDebug: true + # 是否显示OpenAPI原始结构的Tab框,默认显示 + enableOpenApi: false + # 是否生产环境 + production: false + +# Sa-Token配置 +sa-token: + # token名称 (同时也是cookie名称),此值不要修改 + token-name: X-Auth-Token + # token有效期,单位s 默认30天, -1代表永不过期 + timeout: 25920000 + # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 + activity-timeout: 7200 + # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) + is-share: false + # token风格 + token-style: uuid + # 是否输出操作日志 + is-log: false + +jugg: + secret: + # 秘钥,用于敏感信息加密,生产环境一定要更改此项,并且产生数据后不要更改秘钥 + # 提供了EncryptUtil工具类,包含:生成秘钥、加密、解密方法。 + key: eRE2drUFINojkG9ivqtfOA== + #默认配置 + default-setting: + #默认单号生成类型 FLOW:流水号 SNOW_FLAKE:雪花算法,如果不配置,默认是SNOW_FLAKE + generator-type: SNOW_FLAKE + #默认的用户ID,用于写入数据库时的createById和updateById的自动赋值,如果有登录人则取登录人ID,如果没有则取默认用户ID,如果不配置,默认是1 + default-user-id: 1 + #默认的用户姓名,用于写入数据库时的createBy和updateBy的自动赋值,如果有登录人则取登录人姓名,如果没有则取默认用户姓名,如果不配置,默认是系统管理员 + default-user-name: 系统管理员 + web: + #不需要认证的Url + filter-url: ${magic-api.push_path} + #终端ID + worker-id: 1 + #数据中心ID + center-id: 1 + #重复提交拦截暂时不实现 + #repeat-request: + #重复提交拦截间隔(单位:秒) + #filter-interval: 1 + #缓存TTL配置 单位:秒 + cache: + #公共缓存过期时间 + ttl: 1800 + #特殊指定缓存过期时间,以下示例为cacheName的过期时间是3600秒、cacheName2的过期是7200秒。cacheName、cacheName2对应的是@Cacheable的Value属性 + #regions: + # cacheName: 3600 + # cacheName2: 7200 + #开启多租户 + tenant: + enabled: false + #开启websocket + ws: + enabled: true + #通信topic + #topic: xingyun:ws:topic + #是否支持跨域 + #support-cross-domain: false + #验证码配置 + kaptcha: + #过期时间(单位:分钟) + expire-time: 5 + session-config-key: KAPTCHA_SESSION_KEY + session-config-date: KAPTCHA_SESSION_DATE + border: true + border-color: black + border-thickness: 1 + noise-color: black + noise-impl: com.google.code.kaptcha.impl.DefaultNoise + obscurificator-impl: com.google.code.kaptcha.impl.WaterRipple + producer-impl: com.google.code.kaptcha.impl.DefaultKaptcha + text-producer-impl: com.google.code.kaptcha.text.impl.DefaultTextCreator + text-producer-char-string: abcde2345678gfynmnpwx + text-producer-char-length: 4 + text-producer-font-names: Arial,Courier + text-producer-font-color: black + text-producer-font-size: 28 + text-producer-char-space: 2 + word-render-impl: com.google.code.kaptcha.text.impl.DefaultWordRenderer + back-ground-impl: com.google.code.kaptcha.impl.DefaultBackground + back-ground-clr-from: lightGray + back-ground-clr-to: white + image-width: 120 + image-height: 40 + + +#PageHelper分页器 +pagehelper: + offset-as-page-num: true + row-bounds-with-count: true + page-size-zero: true + reasonable: false + params: pageNum=pageIndex;pageSize=pageSize; + support-methods-arguments: false +mybatis-plus: + mapper-locations: classpath*:/mappers/**/*.xml + typeEnumsPackage: com.lframework.starter.**.enums,com.lframework.xingyun.**.enums + +op-logs: + #是否开启 + enabled: true + #操作日志保留天数 + retain-days: 7 + +# 是否移除内置权限,针对admin等内置权限,因为内置权限等同于通配符权限,设置为true时会用具体的权限将内置权限替换掉,生产环境建议设置为true +remove-fixed-permissions: false + +magic-api: + # 编辑器配置项 + editor-config: classpath:magic-editor-config.js + # 这里改为项目运行时的域名,菜单中嵌入的页面为base-url + web,这里示例即为http://localhost:8080/dynamic/web + base-url: http://localhost:8080 + # 编辑器页面的访问路径url + web: /dynamic/web + resource: + type: database + tableName: magic_api_file + prefix: /magic-api + readonly: false + # 接口前缀 + prefix: /dynamic-api + # 禁止覆盖应用接口 + allow-override: true + # 是否支持跨域 + support-cross-domain: false + # 推送路径 + push_path: /_magic-api-sync + # 推送秘钥,自行修改 + secret-key: 123456789 + throw-exception: true + response: |- #配置JSON格式,格式为magic-script中的表达式 + { + code: code, + msg: message, + data, + timestamp, + requestTime, + executeTime, + } + response-code: + success: 200 + invalid: 400 + exception: 500 + page: + size: pageSize # 页大小的参数名称 + page: pageIndex # 页码的参数名称 + default-page: 1 # 未传页码时的默认首页 + default-size: 20 # 未传页大小时的默认页大小 + backup: + enable: true + max-history: 14 #备份保留天数,-1为永久保留 + table-name: magic_api_file_backup \ No newline at end of file diff --git a/xingyun-api/src/main/resources/banner.txt b/xingyun-api/src/main/resources/banner.txt new file mode 100644 index 0000000..15182bc --- /dev/null +++ b/xingyun-api/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + ▄ ▄ ▀ + █ █ ▄▄▄ ▄ ▄▄ ▄▄▄▄ ▄ ▄ ▄ ▄ ▄ ▄▄ + ██ █ █▀ █ █▀ ▀█ ▀▄ ▄▀ █ █ █▀ █ + ▄▀▀▄ █ █ █ █ █ █▄█ █ █ █ █ + ▄▀ ▀▄ ▄▄█▄▄ █ █ ▀█▄▀█ ▀█ ▀▄▄▀█ █ █ + ▄ █ ▄▀ + ▀▀ ▀▀ \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/SQL文件说明,重要!!!!!!.txt b/xingyun-api/src/main/resources/db/SQL文件说明,重要!!!!!!.txt new file mode 100644 index 0000000..7d9df38 --- /dev/null +++ b/xingyun-api/src/main/resources/db/SQL文件说明,重要!!!!!!.txt @@ -0,0 +1,5 @@ +all目录中的是全量SQL,其中platform.sql是平台库SQL;tenant.sql是租户库SQL。 +migration目录中的是增量SQL,其中platform目录中是平台库的增量SQL;tenant目录中是租户库的增量SQL。 +如果不使用多租户,那么平台库和租户库的SQL就在同一个库中执行。 +使用多租户时,租户库是从平台库的tenant表中获取的,不要忘记修改这个表里面的数据 +tenant表中存储的密码不是明文密码,需要将明文密码加密后存储,参见EncryptUtil中的main方法进行转换。 \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/all/platform.sql b/xingyun-api/src/main/resources/db/all/platform.sql new file mode 100644 index 0000000..6d28672 --- /dev/null +++ b/xingyun-api/src/main/resources/db/all/platform.sql @@ -0,0 +1,388 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for magic_api_file +-- ---------------------------- +DROP TABLE IF EXISTS `magic_api_file`; +CREATE TABLE `magic_api_file` ( + `file_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `file_content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + PRIMARY KEY (`file_path`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of magic_api_file +-- ---------------------------- + +-- ---------------------------- +-- Table structure for magic_api_file_backup +-- ---------------------------- +DROP TABLE IF EXISTS `magic_api_file_backup`; +CREATE TABLE `magic_api_file_backup` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原对象ID', + `create_date` bigint(13) NOT NULL COMMENT '备份时间', + `tag` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签', + `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '原名称', + `content` blob NULL COMMENT '备份内容', + `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作人', + PRIMARY KEY (`id`, `create_date`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of magic_api_file_backup +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_blob_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_blob_triggers`; +CREATE TABLE `qrtz_blob_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `BLOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `SCHED_NAME`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_blob_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_calendars +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_calendars`; +CREATE TABLE `qrtz_calendars` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CALENDAR_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CALENDAR` blob NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_calendars +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_cron_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_cron_triggers`; +CREATE TABLE `qrtz_cron_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CRON_EXPRESSION` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TIME_ZONE_ID` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_cron_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_fired_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_fired_triggers`; +CREATE TABLE `qrtz_fired_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ENTRY_ID` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `INSTANCE_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `FIRED_TIME` bigint(13) NOT NULL, + `SCHED_TIME` bigint(13) NOT NULL, + `PRIORITY` int(11) NOT NULL, + `STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `JOB_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE, + INDEX `IDX_QRTZ_FT_TRIG_INST_NAME`(`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE, + INDEX `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY`(`SCHED_NAME`, `INSTANCE_NAME`, `REQUESTS_RECOVERY`) USING BTREE, + INDEX `IDX_QRTZ_FT_J_G`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_FT_JG`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_FT_T_G`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_FT_TG`(`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_fired_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_job_details +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_job_details`; +CREATE TABLE `qrtz_job_details` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_DURABLE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_J_REQ_RECOVERY`(`SCHED_NAME`, `REQUESTS_RECOVERY`) USING BTREE, + INDEX `IDX_QRTZ_J_GRP`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_job_details +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_locks +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_locks`; +CREATE TABLE `qrtz_locks` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `LOCK_NAME` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_locks +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_paused_trigger_grps +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; +CREATE TABLE `qrtz_paused_trigger_grps` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_paused_trigger_grps +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_scheduler_state +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_scheduler_state`; +CREATE TABLE `qrtz_scheduler_state` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `INSTANCE_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `LAST_CHECKIN_TIME` bigint(13) NOT NULL, + `CHECKIN_INTERVAL` bigint(13) NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_scheduler_state +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_simple_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simple_triggers`; +CREATE TABLE `qrtz_simple_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `REPEAT_COUNT` bigint(7) NOT NULL, + `REPEAT_INTERVAL` bigint(12) NOT NULL, + `TIMES_TRIGGERED` bigint(10) NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_simple_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_simprop_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simprop_triggers`; +CREATE TABLE `qrtz_simprop_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `STR_PROP_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `STR_PROP_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `STR_PROP_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `INT_PROP_1` int(11) NULL DEFAULT NULL, + `INT_PROP_2` int(11) NULL DEFAULT NULL, + `LONG_PROP_1` bigint(20) NULL DEFAULT NULL, + `LONG_PROP_2` bigint(20) NULL DEFAULT NULL, + `DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL, + `DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL, + `BOOL_PROP_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `BOOL_PROP_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_simprop_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_triggers`; +CREATE TABLE `qrtz_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `NEXT_FIRE_TIME` bigint(13) NULL DEFAULT NULL, + `PREV_FIRE_TIME` bigint(13) NULL DEFAULT NULL, + `PRIORITY` int(11) NULL DEFAULT NULL, + `TRIGGER_STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_TYPE` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `START_TIME` bigint(13) NOT NULL, + `END_TIME` bigint(13) NULL DEFAULT NULL, + `CALENDAR_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `MISFIRE_INSTR` smallint(2) NULL DEFAULT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_J`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_JG`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_C`(`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE, + INDEX `IDX_QRTZ_T_G`(`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_STATE`(`SCHED_NAME`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_N_STATE`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_N_G_STATE`(`SCHED_NAME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_NEXT_FIRE_TIME`(`SCHED_NAME`, `NEXT_FIRE_TIME`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_ST`(`SCHED_NAME`, `TRIGGER_STATE`, `NEXT_FIRE_TIME`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_MISFIRE`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, + CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_module +-- ---------------------------- +DROP TABLE IF EXISTS `sys_module`; +CREATE TABLE `sys_module` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统模块' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_module +-- ---------------------------- +INSERT INTO `sys_module` VALUES (1, '平台管理', '系统平台的核心模块。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (2, '系统管理', '维护企业、系统基础数据,包括部门、岗位、角色、系统菜单和参数等。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (3, '基础信息管理', '维护基础业务数据,包括仓库、客户、供应商、会员等。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (4, '商品中心', '管理商品核心数据。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (5, '采购业务', '管理供应商与企业的采购业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (6, '销售业务', '管理企业与TOB端大客户的销售业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (7, '零售业务', '管理企业与TOC端会员的零售业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (8, '库存管理及调拨', '查询商品库存和进行商品调拨。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (9, '库存盘点', '库存商品盘点。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (10, '库存调整', '商品库存数量和成本调整。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (11, '结算管理', '企业与供应商、客户进行结算。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (12, '开发管理', '系统快捷开发,如管理定时器、数据实体、数据对象、表单生成等。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (13, '便捷办公', '支持文件收纳和在线Excel。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (14, '开放平台', '系统开放平台管理。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (15, '物流发货', '管理企业物流业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); + +-- ---------------------------- +-- Table structure for sys_module_tenant +-- ---------------------------- +DROP TABLE IF EXISTS `sys_module_tenant`; +CREATE TABLE `sys_module_tenant` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `module_id` int(11) NOT NULL COMMENT '模块ID', + `tenant_id` int(11) NOT NULL COMMENT '租户ID', + `expire_time` datetime NOT NULL COMMENT '过期时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `name`(`tenant_id`, `module_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '租户和系统模块关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_module_tenant +-- ---------------------------- +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875135', 1, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875136', 2, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875137', 3, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875138', 4, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875139', 5, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875140', 6, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875141', 7, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875142', 8, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875143', 9, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875144', 10, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875145', 11, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875146', 12, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875147', 13, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875148', 14, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875149', 15, 1000, '2099-01-01 00:00:00'); + +-- ---------------------------- +-- Table structure for sys_open_domain +-- ---------------------------- +DROP TABLE IF EXISTS `sys_open_domain`; +CREATE TABLE `sys_open_domain` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `api_secret` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'API秘钥', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `tenant_id` int(11) NULL DEFAULT NULL COMMENT '租户ID', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '开放域' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_open_domain +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tenant +-- ---------------------------- +DROP TABLE IF EXISTS `tenant`; +CREATE TABLE `tenant` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `jdbc_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'JDBC连接地址', + `jdbc_username` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'JDBC用户名', + `jdbc_password` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'JDBC密码', + `available` tinyint(1) NOT NULL COMMENT '状态', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1001 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '租户' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tenant +-- ---------------------------- +INSERT INTO `tenant` VALUES (1000, '测试租户', 'jdbc:mysql://127.0.0.1:3306/xingyun', 'root', '24590d72bfb4d71ccbc533570aa9627b', 1, '2022-12-31 22:59:21', '2023-03-13 22:14:07'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/xingyun-api/src/main/resources/db/all/tenant.sql b/xingyun-api/src/main/resources/db/all/tenant.sql new file mode 100644 index 0000000..a559de5 --- /dev/null +++ b/xingyun-api/src/main/resources/db/all/tenant.sql @@ -0,0 +1,7141 @@ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for base_data_address +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_address`; +CREATE TABLE `base_data_address` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `entity_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '实体ID', + `entity_type` tinyint(3) NOT NULL COMMENT '实体类型', + `address_type` tinyint(3) NOT NULL COMMENT '地址类型', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号', + `province_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '省', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '市', + `district_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '区', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '详细地址', + `is_default` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否默认地址', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `entity_id`(`entity_id`, `entity_type`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '地址库' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_address +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_customer +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_customer`; +CREATE TABLE `base_data_customer` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `mnemonic_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '助记码', + `contact` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '电子邮箱', + `zip_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮编', + `fax` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '传真', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', + `settle_type` tinyint(3) NOT NULL DEFAULT 1 COMMENT '结算方式', + `credit_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '统一社会信用代码', + `tax_identify_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '纳税人识别号', + `bank_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '开户银行', + `account_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '户名', + `account_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '银行账号', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_customer +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_logistics_company +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_logistics_company`; +CREATE TABLE `base_data_logistics_company` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `contact` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '物流公司' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of base_data_logistics_company +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_member +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_member`; +CREATE TABLE `base_data_member` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `gender` tinyint(3) NOT NULL DEFAULT 0 COMMENT '性别', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '电子邮箱', + `birthday` date NULL DEFAULT NULL COMMENT '出生日期', + `join_day` date NOT NULL COMMENT '入会日期', + `shop_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属门店', + `guider_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属导购', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `telephone`(`telephone`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_member +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_pay_type +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_pay_type`; +CREATE TABLE `base_data_pay_type` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `rec_text` tinyint(1) NOT NULL COMMENT '是否记录内容', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支付方式' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_pay_type +-- ---------------------------- +INSERT INTO `base_data_pay_type` VALUES ('1', '001', '现金', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('2', '002', '微信支付', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('3', '003', '支付宝支付', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('4', '004', '移动支付', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('5', '005', '优惠券', 1, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('6', '006', '积分', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); + +-- ---------------------------- +-- Table structure for base_data_product +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product`; +CREATE TABLE `base_data_product` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `short_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '简称', + `sku_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'SKU', + `external_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '外部编号', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '类目ID', + `brand_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '品牌ID', + `product_type` tinyint(3) NOT NULL DEFAULT 1 COMMENT '商品类型', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '进项税率(%)', + `sale_tax_rate` decimal(16, 2) NOT NULL COMMENT '销项税率', + `spec` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格', + `unit` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '单位', + `weight` decimal(16, 2) NULL DEFAULT NULL COMMENT '重量(kg)', + `volume` decimal(16, 2) NULL DEFAULT NULL COMMENT '体积(cm3)', + `available` tinyint(1) NOT NULL COMMENT '状态', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `sku_code`(`sku_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_brand +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_brand`; +CREATE TABLE `base_data_product_brand` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `short_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '简称', + `logo` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'logo', + `introduction` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '简介', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品品牌' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_brand +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_bundle +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_bundle`; +CREATE TABLE `base_data_product_bundle` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `main_product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主商品ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品ID', + `bundle_num` int(11) NOT NULL COMMENT '包含数量', + `sale_price` decimal(24, 2) NOT NULL COMMENT '销售价', + `retail_price` decimal(24, 2) NOT NULL COMMENT '零售价', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `main_product_id`(`main_product_id`, `product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '组合商品' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_bundle +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_category +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_category`; +CREATE TABLE `base_data_product_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `parent_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品类目' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_category_property +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_category_property`; +CREATE TABLE `base_data_product_category_property` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `property_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品属性ID', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品类目ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `property_id`(`property_id`, `category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品类目和商品属性关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_category_property +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_property +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_property`; +CREATE TABLE `base_data_product_property` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `is_required` tinyint(1) NOT NULL COMMENT '是否必填', + `column_type` tinyint(3) NOT NULL COMMENT '录入类型', + `column_data_type` tinyint(3) NULL DEFAULT NULL COMMENT '数据类型', + `property_type` tinyint(3) NOT NULL COMMENT '属性类别', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品属性' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_property +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_property_item +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_property_item`; +CREATE TABLE `base_data_product_property_item` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `property_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '属性ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `property_id`(`property_id`, `code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品属性值' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_property_item +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_property_relation +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_property_relation`; +CREATE TABLE `base_data_product_property_relation` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `property_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品属性ID', + `property_item_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '属性值ID', + `property_text` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品属性值', + PRIMARY KEY (`id`) USING BTREE, + INDEX `product_id`(`product_id`, `property_id`, `property_item_id`) USING BTREE, + INDEX `property_id`(`property_id`, `property_item_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品和商品属性关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_property_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_purchase +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_purchase`; +CREATE TABLE `base_data_product_purchase` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `price` decimal(24, 2) NOT NULL COMMENT '采购价', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品采购价' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_purchase +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_retail +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_retail`; +CREATE TABLE `base_data_product_retail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `price` decimal(24, 2) NOT NULL COMMENT '零售价', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品零售价' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_retail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_product_sale +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_sale`; +CREATE TABLE `base_data_product_sale` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `price` decimal(24, 2) NOT NULL COMMENT '销售价', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品销售价' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_product_sale +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_store_center +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_store_center`; +CREATE TABLE `base_data_store_center` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `contact` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人手机号码', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', + `people_num` int(11) NULL DEFAULT NULL COMMENT '仓库人数', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_store_center +-- ---------------------------- + +-- ---------------------------- +-- Table structure for base_data_supplier +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_supplier`; +CREATE TABLE `base_data_supplier` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `mnemonic_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '助记码', + `contact` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '电子邮箱', + `zip_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮编', + `fax` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '传真', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', + `delivery_cycle` int(11) NULL DEFAULT NULL COMMENT '发货周期(天)', + `manage_type` tinyint(3) NOT NULL DEFAULT 1 COMMENT '经营方式', + `settle_type` tinyint(3) NOT NULL DEFAULT 1 COMMENT '结算方式', + `credit_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '统一社会信用代码', + `tax_identify_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '纳税人识别号', + `bank_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '开户银行', + `account_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '户名', + `account_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '银行账号', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of base_data_supplier +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_check_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_check_sheet`; +CREATE TABLE `customer_settle_check_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `total_pay_amount` decimal(24, 2) NOT NULL COMMENT '应付金额', + `total_payed_amount` decimal(24, 2) NOT NULL COMMENT '已付金额', + `total_discount_amount` decimal(24, 2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户对账单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_check_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_check_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_check_sheet_detail`; +CREATE TABLE `customer_settle_check_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '对账单ID', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `calc_type` tinyint(3) NOT NULL COMMENT '计算类型', + `pay_amount` decimal(24, 2) NOT NULL COMMENT '应付金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `biz_id`) USING BTREE, + INDEX `biz_id`(`biz_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户对账单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_check_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_fee_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_fee_sheet`; +CREATE TABLE `customer_settle_fee_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `sheet_type` tinyint(3) NOT NULL COMMENT '单据类型', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户费用单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_fee_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_fee_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_fee_sheet_detail`; +CREATE TABLE `customer_settle_fee_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '费用单ID', + `item_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '项目ID', + `amount` decimal(24, 2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `item_id`) USING BTREE, + INDEX `item_id`(`item_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户费用单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_fee_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_pre_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_pre_sheet`; +CREATE TABLE `customer_settle_pre_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户预付款单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_pre_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_pre_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_pre_sheet_detail`; +CREATE TABLE `customer_settle_pre_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '预付款单ID', + `item_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '项目ID', + `amount` decimal(24, 2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `item_id`) USING BTREE, + INDEX `item_id`(`item_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户预付款单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_pre_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_sheet`; +CREATE TABLE `customer_settle_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `total_discount_amount` decimal(24, 2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户结算单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for customer_settle_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_sheet_detail`; +CREATE TABLE `customer_settle_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '结算单ID', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `pay_amount` decimal(24, 2) NOT NULL COMMENT '实付金额', + `discount_amount` decimal(24, 2) NOT NULL COMMENT '优惠金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `biz_id`) USING BTREE, + INDEX `biz_id`(`biz_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客户结算单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of customer_settle_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for dic_city +-- ---------------------------- +DROP TABLE IF EXISTS `dic_city`; +CREATE TABLE `dic_city` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `parent_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID', + `level` int(11) NOT NULL COMMENT '层级', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `parent_id`(`parent_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '地区字典表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of dic_city +-- ---------------------------- +INSERT INTO `dic_city` VALUES ('11', '11', '北京市', NULL, 1); +INSERT INTO `dic_city` VALUES ('1101', '1101', '市辖区', '11', 2); +INSERT INTO `dic_city` VALUES ('110101', '110101', '东城区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110102', '110102', '西城区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110105', '110105', '朝阳区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110106', '110106', '丰台区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110107', '110107', '石景山区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110108', '110108', '海淀区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110109', '110109', '门头沟区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110111', '110111', '房山区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110112', '110112', '通州区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110113', '110113', '顺义区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110114', '110114', '昌平区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110115', '110115', '大兴区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110116', '110116', '怀柔区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110117', '110117', '平谷区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110118', '110118', '密云区', '1101', 3); +INSERT INTO `dic_city` VALUES ('110119', '110119', '延庆区', '1101', 3); +INSERT INTO `dic_city` VALUES ('12', '12', '天津市', NULL, 1); +INSERT INTO `dic_city` VALUES ('1201', '1201', '市辖区', '12', 2); +INSERT INTO `dic_city` VALUES ('120101', '120101', '和平区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120102', '120102', '河东区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120103', '120103', '河西区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120104', '120104', '南开区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120105', '120105', '河北区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120106', '120106', '红桥区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120110', '120110', '东丽区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120111', '120111', '西青区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120112', '120112', '津南区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120113', '120113', '北辰区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120114', '120114', '武清区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120115', '120115', '宝坻区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120116', '120116', '滨海新区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120117', '120117', '宁河区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120118', '120118', '静海区', '1201', 3); +INSERT INTO `dic_city` VALUES ('120119', '120119', '蓟州区', '1201', 3); +INSERT INTO `dic_city` VALUES ('13', '13', '河北省', NULL, 1); +INSERT INTO `dic_city` VALUES ('1301', '1301', '石家庄市', '13', 2); +INSERT INTO `dic_city` VALUES ('130102', '130102', '长安区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130104', '130104', '桥西区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130105', '130105', '新华区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130107', '130107', '井陉矿区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130108', '130108', '裕华区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130109', '130109', '藁城区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130110', '130110', '鹿泉区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130111', '130111', '栾城区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130121', '130121', '井陉县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130123', '130123', '正定县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130125', '130125', '行唐县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130126', '130126', '灵寿县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130127', '130127', '高邑县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130128', '130128', '深泽县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130129', '130129', '赞皇县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130130', '130130', '无极县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130131', '130131', '平山县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130132', '130132', '元氏县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130133', '130133', '赵县', '1301', 3); +INSERT INTO `dic_city` VALUES ('130171', '130171', '石家庄高新技术产业开发区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130172', '130172', '石家庄循环化工园区', '1301', 3); +INSERT INTO `dic_city` VALUES ('130181', '130181', '辛集市', '1301', 3); +INSERT INTO `dic_city` VALUES ('130183', '130183', '晋州市', '1301', 3); +INSERT INTO `dic_city` VALUES ('130184', '130184', '新乐市', '1301', 3); +INSERT INTO `dic_city` VALUES ('1302', '1302', '唐山市', '13', 2); +INSERT INTO `dic_city` VALUES ('130202', '130202', '路南区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130203', '130203', '路北区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130204', '130204', '古冶区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130205', '130205', '开平区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130207', '130207', '丰南区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130208', '130208', '丰润区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130209', '130209', '曹妃甸区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130224', '130224', '滦南县', '1302', 3); +INSERT INTO `dic_city` VALUES ('130225', '130225', '乐亭县', '1302', 3); +INSERT INTO `dic_city` VALUES ('130227', '130227', '迁西县', '1302', 3); +INSERT INTO `dic_city` VALUES ('130229', '130229', '玉田县', '1302', 3); +INSERT INTO `dic_city` VALUES ('130271', '130271', '河北唐山芦台经济开发区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130272', '130272', '唐山市汉沽管理区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130273', '130273', '唐山高新技术产业开发区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130274', '130274', '河北唐山海港经济开发区', '1302', 3); +INSERT INTO `dic_city` VALUES ('130281', '130281', '遵化市', '1302', 3); +INSERT INTO `dic_city` VALUES ('130283', '130283', '迁安市', '1302', 3); +INSERT INTO `dic_city` VALUES ('130284', '130284', '滦州市', '1302', 3); +INSERT INTO `dic_city` VALUES ('1303', '1303', '秦皇岛市', '13', 2); +INSERT INTO `dic_city` VALUES ('130302', '130302', '海港区', '1303', 3); +INSERT INTO `dic_city` VALUES ('130303', '130303', '山海关区', '1303', 3); +INSERT INTO `dic_city` VALUES ('130304', '130304', '北戴河区', '1303', 3); +INSERT INTO `dic_city` VALUES ('130306', '130306', '抚宁区', '1303', 3); +INSERT INTO `dic_city` VALUES ('130321', '130321', '青龙满族自治县', '1303', 3); +INSERT INTO `dic_city` VALUES ('130322', '130322', '昌黎县', '1303', 3); +INSERT INTO `dic_city` VALUES ('130324', '130324', '卢龙县', '1303', 3); +INSERT INTO `dic_city` VALUES ('130371', '130371', '秦皇岛市经济技术开发区', '1303', 3); +INSERT INTO `dic_city` VALUES ('130372', '130372', '北戴河新区', '1303', 3); +INSERT INTO `dic_city` VALUES ('1304', '1304', '邯郸市', '13', 2); +INSERT INTO `dic_city` VALUES ('130402', '130402', '邯山区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130403', '130403', '丛台区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130404', '130404', '复兴区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130406', '130406', '峰峰矿区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130407', '130407', '肥乡区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130408', '130408', '永年区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130423', '130423', '临漳县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130424', '130424', '成安县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130425', '130425', '大名县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130426', '130426', '涉县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130427', '130427', '磁县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130430', '130430', '邱县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130431', '130431', '鸡泽县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130432', '130432', '广平县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130433', '130433', '馆陶县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130434', '130434', '魏县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130435', '130435', '曲周县', '1304', 3); +INSERT INTO `dic_city` VALUES ('130471', '130471', '邯郸经济技术开发区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130473', '130473', '邯郸冀南新区', '1304', 3); +INSERT INTO `dic_city` VALUES ('130481', '130481', '武安市', '1304', 3); +INSERT INTO `dic_city` VALUES ('1305', '1305', '邢台市', '13', 2); +INSERT INTO `dic_city` VALUES ('130502', '130502', '襄都区', '1305', 3); +INSERT INTO `dic_city` VALUES ('130503', '130503', '信都区', '1305', 3); +INSERT INTO `dic_city` VALUES ('130505', '130505', '任泽区', '1305', 3); +INSERT INTO `dic_city` VALUES ('130506', '130506', '南和区', '1305', 3); +INSERT INTO `dic_city` VALUES ('130522', '130522', '临城县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130523', '130523', '内丘县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130524', '130524', '柏乡县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130525', '130525', '隆尧县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130528', '130528', '宁晋县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130529', '130529', '巨鹿县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130530', '130530', '新河县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130531', '130531', '广宗县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130532', '130532', '平乡县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130533', '130533', '威县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130534', '130534', '清河县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130535', '130535', '临西县', '1305', 3); +INSERT INTO `dic_city` VALUES ('130571', '130571', '河北邢台经济开发区', '1305', 3); +INSERT INTO `dic_city` VALUES ('130581', '130581', '南宫市', '1305', 3); +INSERT INTO `dic_city` VALUES ('130582', '130582', '沙河市', '1305', 3); +INSERT INTO `dic_city` VALUES ('1306', '1306', '保定市', '13', 2); +INSERT INTO `dic_city` VALUES ('130602', '130602', '竞秀区', '1306', 3); +INSERT INTO `dic_city` VALUES ('130606', '130606', '莲池区', '1306', 3); +INSERT INTO `dic_city` VALUES ('130607', '130607', '满城区', '1306', 3); +INSERT INTO `dic_city` VALUES ('130608', '130608', '清苑区', '1306', 3); +INSERT INTO `dic_city` VALUES ('130609', '130609', '徐水区', '1306', 3); +INSERT INTO `dic_city` VALUES ('130623', '130623', '涞水县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130624', '130624', '阜平县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130626', '130626', '定兴县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130627', '130627', '唐县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130628', '130628', '高阳县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130629', '130629', '容城县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130630', '130630', '涞源县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130631', '130631', '望都县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130632', '130632', '安新县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130633', '130633', '易县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130634', '130634', '曲阳县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130635', '130635', '蠡县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130636', '130636', '顺平县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130637', '130637', '博野县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130638', '130638', '雄县', '1306', 3); +INSERT INTO `dic_city` VALUES ('130671', '130671', '保定高新技术产业开发区', '1306', 3); +INSERT INTO `dic_city` VALUES ('130672', '130672', '保定白沟新城', '1306', 3); +INSERT INTO `dic_city` VALUES ('130681', '130681', '涿州市', '1306', 3); +INSERT INTO `dic_city` VALUES ('130682', '130682', '定州市', '1306', 3); +INSERT INTO `dic_city` VALUES ('130683', '130683', '安国市', '1306', 3); +INSERT INTO `dic_city` VALUES ('130684', '130684', '高碑店市', '1306', 3); +INSERT INTO `dic_city` VALUES ('1307', '1307', '张家口市', '13', 2); +INSERT INTO `dic_city` VALUES ('130702', '130702', '桥东区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130703', '130703', '桥西区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130705', '130705', '宣化区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130706', '130706', '下花园区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130708', '130708', '万全区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130709', '130709', '崇礼区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130722', '130722', '张北县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130723', '130723', '康保县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130724', '130724', '沽源县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130725', '130725', '尚义县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130726', '130726', '蔚县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130727', '130727', '阳原县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130728', '130728', '怀安县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130730', '130730', '怀来县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130731', '130731', '涿鹿县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130732', '130732', '赤城县', '1307', 3); +INSERT INTO `dic_city` VALUES ('130771', '130771', '张家口经济开发区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130772', '130772', '张家口市察北管理区', '1307', 3); +INSERT INTO `dic_city` VALUES ('130773', '130773', '张家口市塞北管理区', '1307', 3); +INSERT INTO `dic_city` VALUES ('1308', '1308', '承德市', '13', 2); +INSERT INTO `dic_city` VALUES ('130802', '130802', '双桥区', '1308', 3); +INSERT INTO `dic_city` VALUES ('130803', '130803', '双滦区', '1308', 3); +INSERT INTO `dic_city` VALUES ('130804', '130804', '鹰手营子矿区', '1308', 3); +INSERT INTO `dic_city` VALUES ('130821', '130821', '承德县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130822', '130822', '兴隆县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130824', '130824', '滦平县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130825', '130825', '隆化县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130826', '130826', '丰宁满族自治县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130827', '130827', '宽城满族自治县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130828', '130828', '围场满族蒙古族自治县', '1308', 3); +INSERT INTO `dic_city` VALUES ('130871', '130871', '承德高新技术产业开发区', '1308', 3); +INSERT INTO `dic_city` VALUES ('130881', '130881', '平泉市', '1308', 3); +INSERT INTO `dic_city` VALUES ('1309', '1309', '沧州市', '13', 2); +INSERT INTO `dic_city` VALUES ('130902', '130902', '新华区', '1309', 3); +INSERT INTO `dic_city` VALUES ('130903', '130903', '运河区', '1309', 3); +INSERT INTO `dic_city` VALUES ('130921', '130921', '沧县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130922', '130922', '青县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130923', '130923', '东光县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130924', '130924', '海兴县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130925', '130925', '盐山县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130926', '130926', '肃宁县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130927', '130927', '南皮县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130928', '130928', '吴桥县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130929', '130929', '献县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130930', '130930', '孟村回族自治县', '1309', 3); +INSERT INTO `dic_city` VALUES ('130971', '130971', '河北沧州经济开发区', '1309', 3); +INSERT INTO `dic_city` VALUES ('130972', '130972', '沧州高新技术产业开发区', '1309', 3); +INSERT INTO `dic_city` VALUES ('130973', '130973', '沧州渤海新区', '1309', 3); +INSERT INTO `dic_city` VALUES ('130981', '130981', '泊头市', '1309', 3); +INSERT INTO `dic_city` VALUES ('130982', '130982', '任丘市', '1309', 3); +INSERT INTO `dic_city` VALUES ('130983', '130983', '黄骅市', '1309', 3); +INSERT INTO `dic_city` VALUES ('130984', '130984', '河间市', '1309', 3); +INSERT INTO `dic_city` VALUES ('1310', '1310', '廊坊市', '13', 2); +INSERT INTO `dic_city` VALUES ('131002', '131002', '安次区', '1310', 3); +INSERT INTO `dic_city` VALUES ('131003', '131003', '广阳区', '1310', 3); +INSERT INTO `dic_city` VALUES ('131022', '131022', '固安县', '1310', 3); +INSERT INTO `dic_city` VALUES ('131023', '131023', '永清县', '1310', 3); +INSERT INTO `dic_city` VALUES ('131024', '131024', '香河县', '1310', 3); +INSERT INTO `dic_city` VALUES ('131025', '131025', '大城县', '1310', 3); +INSERT INTO `dic_city` VALUES ('131026', '131026', '文安县', '1310', 3); +INSERT INTO `dic_city` VALUES ('131028', '131028', '大厂回族自治县', '1310', 3); +INSERT INTO `dic_city` VALUES ('131071', '131071', '廊坊经济技术开发区', '1310', 3); +INSERT INTO `dic_city` VALUES ('131081', '131081', '霸州市', '1310', 3); +INSERT INTO `dic_city` VALUES ('131082', '131082', '三河市', '1310', 3); +INSERT INTO `dic_city` VALUES ('1311', '1311', '衡水市', '13', 2); +INSERT INTO `dic_city` VALUES ('131102', '131102', '桃城区', '1311', 3); +INSERT INTO `dic_city` VALUES ('131103', '131103', '冀州区', '1311', 3); +INSERT INTO `dic_city` VALUES ('131121', '131121', '枣强县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131122', '131122', '武邑县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131123', '131123', '武强县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131124', '131124', '饶阳县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131125', '131125', '安平县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131126', '131126', '故城县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131127', '131127', '景县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131128', '131128', '阜城县', '1311', 3); +INSERT INTO `dic_city` VALUES ('131171', '131171', '河北衡水高新技术产业开发区', '1311', 3); +INSERT INTO `dic_city` VALUES ('131172', '131172', '衡水滨湖新区', '1311', 3); +INSERT INTO `dic_city` VALUES ('131182', '131182', '深州市', '1311', 3); +INSERT INTO `dic_city` VALUES ('14', '14', '山西省', NULL, 1); +INSERT INTO `dic_city` VALUES ('1401', '1401', '太原市', '14', 2); +INSERT INTO `dic_city` VALUES ('140105', '140105', '小店区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140106', '140106', '迎泽区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140107', '140107', '杏花岭区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140108', '140108', '尖草坪区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140109', '140109', '万柏林区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140110', '140110', '晋源区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140121', '140121', '清徐县', '1401', 3); +INSERT INTO `dic_city` VALUES ('140122', '140122', '阳曲县', '1401', 3); +INSERT INTO `dic_city` VALUES ('140123', '140123', '娄烦县', '1401', 3); +INSERT INTO `dic_city` VALUES ('140171', '140171', '山西转型综合改革示范区', '1401', 3); +INSERT INTO `dic_city` VALUES ('140181', '140181', '古交市', '1401', 3); +INSERT INTO `dic_city` VALUES ('1402', '1402', '大同市', '14', 2); +INSERT INTO `dic_city` VALUES ('140212', '140212', '新荣区', '1402', 3); +INSERT INTO `dic_city` VALUES ('140213', '140213', '平城区', '1402', 3); +INSERT INTO `dic_city` VALUES ('140214', '140214', '云冈区', '1402', 3); +INSERT INTO `dic_city` VALUES ('140215', '140215', '云州区', '1402', 3); +INSERT INTO `dic_city` VALUES ('140221', '140221', '阳高县', '1402', 3); +INSERT INTO `dic_city` VALUES ('140222', '140222', '天镇县', '1402', 3); +INSERT INTO `dic_city` VALUES ('140223', '140223', '广灵县', '1402', 3); +INSERT INTO `dic_city` VALUES ('140224', '140224', '灵丘县', '1402', 3); +INSERT INTO `dic_city` VALUES ('140225', '140225', '浑源县', '1402', 3); +INSERT INTO `dic_city` VALUES ('140226', '140226', '左云县', '1402', 3); +INSERT INTO `dic_city` VALUES ('140271', '140271', '山西大同经济开发区', '1402', 3); +INSERT INTO `dic_city` VALUES ('1403', '1403', '阳泉市', '14', 2); +INSERT INTO `dic_city` VALUES ('140302', '140302', '城区', '1403', 3); +INSERT INTO `dic_city` VALUES ('140303', '140303', '矿区', '1403', 3); +INSERT INTO `dic_city` VALUES ('140311', '140311', '郊区', '1403', 3); +INSERT INTO `dic_city` VALUES ('140321', '140321', '平定县', '1403', 3); +INSERT INTO `dic_city` VALUES ('140322', '140322', '盂县', '1403', 3); +INSERT INTO `dic_city` VALUES ('1404', '1404', '长治市', '14', 2); +INSERT INTO `dic_city` VALUES ('140403', '140403', '潞州区', '1404', 3); +INSERT INTO `dic_city` VALUES ('140404', '140404', '上党区', '1404', 3); +INSERT INTO `dic_city` VALUES ('140405', '140405', '屯留区', '1404', 3); +INSERT INTO `dic_city` VALUES ('140406', '140406', '潞城区', '1404', 3); +INSERT INTO `dic_city` VALUES ('140423', '140423', '襄垣县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140425', '140425', '平顺县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140426', '140426', '黎城县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140427', '140427', '壶关县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140428', '140428', '长子县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140429', '140429', '武乡县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140430', '140430', '沁县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140431', '140431', '沁源县', '1404', 3); +INSERT INTO `dic_city` VALUES ('140471', '140471', '山西长治高新技术产业园区', '1404', 3); +INSERT INTO `dic_city` VALUES ('1405', '1405', '晋城市', '14', 2); +INSERT INTO `dic_city` VALUES ('140502', '140502', '城区', '1405', 3); +INSERT INTO `dic_city` VALUES ('140521', '140521', '沁水县', '1405', 3); +INSERT INTO `dic_city` VALUES ('140522', '140522', '阳城县', '1405', 3); +INSERT INTO `dic_city` VALUES ('140524', '140524', '陵川县', '1405', 3); +INSERT INTO `dic_city` VALUES ('140525', '140525', '泽州县', '1405', 3); +INSERT INTO `dic_city` VALUES ('140581', '140581', '高平市', '1405', 3); +INSERT INTO `dic_city` VALUES ('1406', '1406', '朔州市', '14', 2); +INSERT INTO `dic_city` VALUES ('140602', '140602', '朔城区', '1406', 3); +INSERT INTO `dic_city` VALUES ('140603', '140603', '平鲁区', '1406', 3); +INSERT INTO `dic_city` VALUES ('140621', '140621', '山阴县', '1406', 3); +INSERT INTO `dic_city` VALUES ('140622', '140622', '应县', '1406', 3); +INSERT INTO `dic_city` VALUES ('140623', '140623', '右玉县', '1406', 3); +INSERT INTO `dic_city` VALUES ('140671', '140671', '山西朔州经济开发区', '1406', 3); +INSERT INTO `dic_city` VALUES ('140681', '140681', '怀仁市', '1406', 3); +INSERT INTO `dic_city` VALUES ('1407', '1407', '晋中市', '14', 2); +INSERT INTO `dic_city` VALUES ('140702', '140702', '榆次区', '1407', 3); +INSERT INTO `dic_city` VALUES ('140703', '140703', '太谷区', '1407', 3); +INSERT INTO `dic_city` VALUES ('140721', '140721', '榆社县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140722', '140722', '左权县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140723', '140723', '和顺县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140724', '140724', '昔阳县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140725', '140725', '寿阳县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140727', '140727', '祁县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140728', '140728', '平遥县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140729', '140729', '灵石县', '1407', 3); +INSERT INTO `dic_city` VALUES ('140781', '140781', '介休市', '1407', 3); +INSERT INTO `dic_city` VALUES ('1408', '1408', '运城市', '14', 2); +INSERT INTO `dic_city` VALUES ('140802', '140802', '盐湖区', '1408', 3); +INSERT INTO `dic_city` VALUES ('140821', '140821', '临猗县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140822', '140822', '万荣县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140823', '140823', '闻喜县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140824', '140824', '稷山县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140825', '140825', '新绛县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140826', '140826', '绛县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140827', '140827', '垣曲县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140828', '140828', '夏县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140829', '140829', '平陆县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140830', '140830', '芮城县', '1408', 3); +INSERT INTO `dic_city` VALUES ('140881', '140881', '永济市', '1408', 3); +INSERT INTO `dic_city` VALUES ('140882', '140882', '河津市', '1408', 3); +INSERT INTO `dic_city` VALUES ('1409', '1409', '忻州市', '14', 2); +INSERT INTO `dic_city` VALUES ('140902', '140902', '忻府区', '1409', 3); +INSERT INTO `dic_city` VALUES ('140921', '140921', '定襄县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140922', '140922', '五台县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140923', '140923', '代县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140924', '140924', '繁峙县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140925', '140925', '宁武县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140926', '140926', '静乐县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140927', '140927', '神池县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140928', '140928', '五寨县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140929', '140929', '岢岚县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140930', '140930', '河曲县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140931', '140931', '保德县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140932', '140932', '偏关县', '1409', 3); +INSERT INTO `dic_city` VALUES ('140971', '140971', '五台山风景名胜区', '1409', 3); +INSERT INTO `dic_city` VALUES ('140981', '140981', '原平市', '1409', 3); +INSERT INTO `dic_city` VALUES ('1410', '1410', '临汾市', '14', 2); +INSERT INTO `dic_city` VALUES ('141002', '141002', '尧都区', '1410', 3); +INSERT INTO `dic_city` VALUES ('141021', '141021', '曲沃县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141022', '141022', '翼城县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141023', '141023', '襄汾县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141024', '141024', '洪洞县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141025', '141025', '古县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141026', '141026', '安泽县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141027', '141027', '浮山县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141028', '141028', '吉县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141029', '141029', '乡宁县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141030', '141030', '大宁县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141031', '141031', '隰县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141032', '141032', '永和县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141033', '141033', '蒲县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141034', '141034', '汾西县', '1410', 3); +INSERT INTO `dic_city` VALUES ('141081', '141081', '侯马市', '1410', 3); +INSERT INTO `dic_city` VALUES ('141082', '141082', '霍州市', '1410', 3); +INSERT INTO `dic_city` VALUES ('1411', '1411', '吕梁市', '14', 2); +INSERT INTO `dic_city` VALUES ('141102', '141102', '离石区', '1411', 3); +INSERT INTO `dic_city` VALUES ('141121', '141121', '文水县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141122', '141122', '交城县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141123', '141123', '兴县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141124', '141124', '临县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141125', '141125', '柳林县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141126', '141126', '石楼县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141127', '141127', '岚县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141128', '141128', '方山县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141129', '141129', '中阳县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141130', '141130', '交口县', '1411', 3); +INSERT INTO `dic_city` VALUES ('141181', '141181', '孝义市', '1411', 3); +INSERT INTO `dic_city` VALUES ('141182', '141182', '汾阳市', '1411', 3); +INSERT INTO `dic_city` VALUES ('15', '15', '内蒙古自治区', NULL, 1); +INSERT INTO `dic_city` VALUES ('1501', '1501', '呼和浩特市', '15', 2); +INSERT INTO `dic_city` VALUES ('150102', '150102', '新城区', '1501', 3); +INSERT INTO `dic_city` VALUES ('150103', '150103', '回民区', '1501', 3); +INSERT INTO `dic_city` VALUES ('150104', '150104', '玉泉区', '1501', 3); +INSERT INTO `dic_city` VALUES ('150105', '150105', '赛罕区', '1501', 3); +INSERT INTO `dic_city` VALUES ('150121', '150121', '土默特左旗', '1501', 3); +INSERT INTO `dic_city` VALUES ('150122', '150122', '托克托县', '1501', 3); +INSERT INTO `dic_city` VALUES ('150123', '150123', '和林格尔县', '1501', 3); +INSERT INTO `dic_city` VALUES ('150124', '150124', '清水河县', '1501', 3); +INSERT INTO `dic_city` VALUES ('150125', '150125', '武川县', '1501', 3); +INSERT INTO `dic_city` VALUES ('150172', '150172', '呼和浩特经济技术开发区', '1501', 3); +INSERT INTO `dic_city` VALUES ('1502', '1502', '包头市', '15', 2); +INSERT INTO `dic_city` VALUES ('150202', '150202', '东河区', '1502', 3); +INSERT INTO `dic_city` VALUES ('150203', '150203', '昆都仑区', '1502', 3); +INSERT INTO `dic_city` VALUES ('150204', '150204', '青山区', '1502', 3); +INSERT INTO `dic_city` VALUES ('150205', '150205', '石拐区', '1502', 3); +INSERT INTO `dic_city` VALUES ('150206', '150206', '白云鄂博矿区', '1502', 3); +INSERT INTO `dic_city` VALUES ('150207', '150207', '九原区', '1502', 3); +INSERT INTO `dic_city` VALUES ('150221', '150221', '土默特右旗', '1502', 3); +INSERT INTO `dic_city` VALUES ('150222', '150222', '固阳县', '1502', 3); +INSERT INTO `dic_city` VALUES ('150223', '150223', '达尔罕茂明安联合旗', '1502', 3); +INSERT INTO `dic_city` VALUES ('150271', '150271', '包头稀土高新技术产业开发区', '1502', 3); +INSERT INTO `dic_city` VALUES ('1503', '1503', '乌海市', '15', 2); +INSERT INTO `dic_city` VALUES ('150302', '150302', '海勃湾区', '1503', 3); +INSERT INTO `dic_city` VALUES ('150303', '150303', '海南区', '1503', 3); +INSERT INTO `dic_city` VALUES ('150304', '150304', '乌达区', '1503', 3); +INSERT INTO `dic_city` VALUES ('1504', '1504', '赤峰市', '15', 2); +INSERT INTO `dic_city` VALUES ('150402', '150402', '红山区', '1504', 3); +INSERT INTO `dic_city` VALUES ('150403', '150403', '元宝山区', '1504', 3); +INSERT INTO `dic_city` VALUES ('150404', '150404', '松山区', '1504', 3); +INSERT INTO `dic_city` VALUES ('150421', '150421', '阿鲁科尔沁旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('150422', '150422', '巴林左旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('150423', '150423', '巴林右旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('150424', '150424', '林西县', '1504', 3); +INSERT INTO `dic_city` VALUES ('150425', '150425', '克什克腾旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('150426', '150426', '翁牛特旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('150428', '150428', '喀喇沁旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('150429', '150429', '宁城县', '1504', 3); +INSERT INTO `dic_city` VALUES ('150430', '150430', '敖汉旗', '1504', 3); +INSERT INTO `dic_city` VALUES ('1505', '1505', '通辽市', '15', 2); +INSERT INTO `dic_city` VALUES ('150502', '150502', '科尔沁区', '1505', 3); +INSERT INTO `dic_city` VALUES ('150521', '150521', '科尔沁左翼中旗', '1505', 3); +INSERT INTO `dic_city` VALUES ('150522', '150522', '科尔沁左翼后旗', '1505', 3); +INSERT INTO `dic_city` VALUES ('150523', '150523', '开鲁县', '1505', 3); +INSERT INTO `dic_city` VALUES ('150524', '150524', '库伦旗', '1505', 3); +INSERT INTO `dic_city` VALUES ('150525', '150525', '奈曼旗', '1505', 3); +INSERT INTO `dic_city` VALUES ('150526', '150526', '扎鲁特旗', '1505', 3); +INSERT INTO `dic_city` VALUES ('150571', '150571', '通辽经济技术开发区', '1505', 3); +INSERT INTO `dic_city` VALUES ('150581', '150581', '霍林郭勒市', '1505', 3); +INSERT INTO `dic_city` VALUES ('1506', '1506', '鄂尔多斯市', '15', 2); +INSERT INTO `dic_city` VALUES ('150602', '150602', '东胜区', '1506', 3); +INSERT INTO `dic_city` VALUES ('150603', '150603', '康巴什区', '1506', 3); +INSERT INTO `dic_city` VALUES ('150621', '150621', '达拉特旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('150622', '150622', '准格尔旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('150623', '150623', '鄂托克前旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('150624', '150624', '鄂托克旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('150625', '150625', '杭锦旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('150626', '150626', '乌审旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('150627', '150627', '伊金霍洛旗', '1506', 3); +INSERT INTO `dic_city` VALUES ('1507', '1507', '呼伦贝尔市', '15', 2); +INSERT INTO `dic_city` VALUES ('150702', '150702', '海拉尔区', '1507', 3); +INSERT INTO `dic_city` VALUES ('150703', '150703', '扎赉诺尔区', '1507', 3); +INSERT INTO `dic_city` VALUES ('150721', '150721', '阿荣旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150722', '150722', '莫力达瓦达斡尔族自治旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150723', '150723', '鄂伦春自治旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150724', '150724', '鄂温克族自治旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150725', '150725', '陈巴尔虎旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150726', '150726', '新巴尔虎左旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150727', '150727', '新巴尔虎右旗', '1507', 3); +INSERT INTO `dic_city` VALUES ('150781', '150781', '满洲里市', '1507', 3); +INSERT INTO `dic_city` VALUES ('150782', '150782', '牙克石市', '1507', 3); +INSERT INTO `dic_city` VALUES ('150783', '150783', '扎兰屯市', '1507', 3); +INSERT INTO `dic_city` VALUES ('150784', '150784', '额尔古纳市', '1507', 3); +INSERT INTO `dic_city` VALUES ('150785', '150785', '根河市', '1507', 3); +INSERT INTO `dic_city` VALUES ('1508', '1508', '巴彦淖尔市', '15', 2); +INSERT INTO `dic_city` VALUES ('150802', '150802', '临河区', '1508', 3); +INSERT INTO `dic_city` VALUES ('150821', '150821', '五原县', '1508', 3); +INSERT INTO `dic_city` VALUES ('150822', '150822', '磴口县', '1508', 3); +INSERT INTO `dic_city` VALUES ('150823', '150823', '乌拉特前旗', '1508', 3); +INSERT INTO `dic_city` VALUES ('150824', '150824', '乌拉特中旗', '1508', 3); +INSERT INTO `dic_city` VALUES ('150825', '150825', '乌拉特后旗', '1508', 3); +INSERT INTO `dic_city` VALUES ('150826', '150826', '杭锦后旗', '1508', 3); +INSERT INTO `dic_city` VALUES ('1509', '1509', '乌兰察布市', '15', 2); +INSERT INTO `dic_city` VALUES ('150902', '150902', '集宁区', '1509', 3); +INSERT INTO `dic_city` VALUES ('150921', '150921', '卓资县', '1509', 3); +INSERT INTO `dic_city` VALUES ('150922', '150922', '化德县', '1509', 3); +INSERT INTO `dic_city` VALUES ('150923', '150923', '商都县', '1509', 3); +INSERT INTO `dic_city` VALUES ('150924', '150924', '兴和县', '1509', 3); +INSERT INTO `dic_city` VALUES ('150925', '150925', '凉城县', '1509', 3); +INSERT INTO `dic_city` VALUES ('150926', '150926', '察哈尔右翼前旗', '1509', 3); +INSERT INTO `dic_city` VALUES ('150927', '150927', '察哈尔右翼中旗', '1509', 3); +INSERT INTO `dic_city` VALUES ('150928', '150928', '察哈尔右翼后旗', '1509', 3); +INSERT INTO `dic_city` VALUES ('150929', '150929', '四子王旗', '1509', 3); +INSERT INTO `dic_city` VALUES ('150981', '150981', '丰镇市', '1509', 3); +INSERT INTO `dic_city` VALUES ('1522', '1522', '兴安盟', '15', 2); +INSERT INTO `dic_city` VALUES ('152201', '152201', '乌兰浩特市', '1522', 3); +INSERT INTO `dic_city` VALUES ('152202', '152202', '阿尔山市', '1522', 3); +INSERT INTO `dic_city` VALUES ('152221', '152221', '科尔沁右翼前旗', '1522', 3); +INSERT INTO `dic_city` VALUES ('152222', '152222', '科尔沁右翼中旗', '1522', 3); +INSERT INTO `dic_city` VALUES ('152223', '152223', '扎赉特旗', '1522', 3); +INSERT INTO `dic_city` VALUES ('152224', '152224', '突泉县', '1522', 3); +INSERT INTO `dic_city` VALUES ('1525', '1525', '锡林郭勒盟', '15', 2); +INSERT INTO `dic_city` VALUES ('152501', '152501', '二连浩特市', '1525', 3); +INSERT INTO `dic_city` VALUES ('152502', '152502', '锡林浩特市', '1525', 3); +INSERT INTO `dic_city` VALUES ('152522', '152522', '阿巴嘎旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152523', '152523', '苏尼特左旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152524', '152524', '苏尼特右旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152525', '152525', '东乌珠穆沁旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152526', '152526', '西乌珠穆沁旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152527', '152527', '太仆寺旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152528', '152528', '镶黄旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152529', '152529', '正镶白旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152530', '152530', '正蓝旗', '1525', 3); +INSERT INTO `dic_city` VALUES ('152531', '152531', '多伦县', '1525', 3); +INSERT INTO `dic_city` VALUES ('152571', '152571', '乌拉盖管委会', '1525', 3); +INSERT INTO `dic_city` VALUES ('1529', '1529', '阿拉善盟', '15', 2); +INSERT INTO `dic_city` VALUES ('152921', '152921', '阿拉善左旗', '1529', 3); +INSERT INTO `dic_city` VALUES ('152922', '152922', '阿拉善右旗', '1529', 3); +INSERT INTO `dic_city` VALUES ('152923', '152923', '额济纳旗', '1529', 3); +INSERT INTO `dic_city` VALUES ('152971', '152971', '内蒙古阿拉善经济开发区', '1529', 3); +INSERT INTO `dic_city` VALUES ('21', '21', '辽宁省', NULL, 1); +INSERT INTO `dic_city` VALUES ('2101', '2101', '沈阳市', '21', 2); +INSERT INTO `dic_city` VALUES ('210102', '210102', '和平区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210103', '210103', '沈河区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210104', '210104', '大东区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210105', '210105', '皇姑区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210106', '210106', '铁西区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210111', '210111', '苏家屯区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210112', '210112', '浑南区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210113', '210113', '沈北新区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210114', '210114', '于洪区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210115', '210115', '辽中区', '2101', 3); +INSERT INTO `dic_city` VALUES ('210123', '210123', '康平县', '2101', 3); +INSERT INTO `dic_city` VALUES ('210124', '210124', '法库县', '2101', 3); +INSERT INTO `dic_city` VALUES ('210181', '210181', '新民市', '2101', 3); +INSERT INTO `dic_city` VALUES ('2102', '2102', '大连市', '21', 2); +INSERT INTO `dic_city` VALUES ('210202', '210202', '中山区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210203', '210203', '西岗区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210204', '210204', '沙河口区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210211', '210211', '甘井子区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210212', '210212', '旅顺口区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210213', '210213', '金州区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210214', '210214', '普兰店区', '2102', 3); +INSERT INTO `dic_city` VALUES ('210224', '210224', '长海县', '2102', 3); +INSERT INTO `dic_city` VALUES ('210281', '210281', '瓦房店市', '2102', 3); +INSERT INTO `dic_city` VALUES ('210283', '210283', '庄河市', '2102', 3); +INSERT INTO `dic_city` VALUES ('2103', '2103', '鞍山市', '21', 2); +INSERT INTO `dic_city` VALUES ('210302', '210302', '铁东区', '2103', 3); +INSERT INTO `dic_city` VALUES ('210303', '210303', '铁西区', '2103', 3); +INSERT INTO `dic_city` VALUES ('210304', '210304', '立山区', '2103', 3); +INSERT INTO `dic_city` VALUES ('210311', '210311', '千山区', '2103', 3); +INSERT INTO `dic_city` VALUES ('210321', '210321', '台安县', '2103', 3); +INSERT INTO `dic_city` VALUES ('210323', '210323', '岫岩满族自治县', '2103', 3); +INSERT INTO `dic_city` VALUES ('210381', '210381', '海城市', '2103', 3); +INSERT INTO `dic_city` VALUES ('2104', '2104', '抚顺市', '21', 2); +INSERT INTO `dic_city` VALUES ('210402', '210402', '新抚区', '2104', 3); +INSERT INTO `dic_city` VALUES ('210403', '210403', '东洲区', '2104', 3); +INSERT INTO `dic_city` VALUES ('210404', '210404', '望花区', '2104', 3); +INSERT INTO `dic_city` VALUES ('210411', '210411', '顺城区', '2104', 3); +INSERT INTO `dic_city` VALUES ('210421', '210421', '抚顺县', '2104', 3); +INSERT INTO `dic_city` VALUES ('210422', '210422', '新宾满族自治县', '2104', 3); +INSERT INTO `dic_city` VALUES ('210423', '210423', '清原满族自治县', '2104', 3); +INSERT INTO `dic_city` VALUES ('2105', '2105', '本溪市', '21', 2); +INSERT INTO `dic_city` VALUES ('210502', '210502', '平山区', '2105', 3); +INSERT INTO `dic_city` VALUES ('210503', '210503', '溪湖区', '2105', 3); +INSERT INTO `dic_city` VALUES ('210504', '210504', '明山区', '2105', 3); +INSERT INTO `dic_city` VALUES ('210505', '210505', '南芬区', '2105', 3); +INSERT INTO `dic_city` VALUES ('210521', '210521', '本溪满族自治县', '2105', 3); +INSERT INTO `dic_city` VALUES ('210522', '210522', '桓仁满族自治县', '2105', 3); +INSERT INTO `dic_city` VALUES ('2106', '2106', '丹东市', '21', 2); +INSERT INTO `dic_city` VALUES ('210602', '210602', '元宝区', '2106', 3); +INSERT INTO `dic_city` VALUES ('210603', '210603', '振兴区', '2106', 3); +INSERT INTO `dic_city` VALUES ('210604', '210604', '振安区', '2106', 3); +INSERT INTO `dic_city` VALUES ('210624', '210624', '宽甸满族自治县', '2106', 3); +INSERT INTO `dic_city` VALUES ('210681', '210681', '东港市', '2106', 3); +INSERT INTO `dic_city` VALUES ('210682', '210682', '凤城市', '2106', 3); +INSERT INTO `dic_city` VALUES ('2107', '2107', '锦州市', '21', 2); +INSERT INTO `dic_city` VALUES ('210702', '210702', '古塔区', '2107', 3); +INSERT INTO `dic_city` VALUES ('210703', '210703', '凌河区', '2107', 3); +INSERT INTO `dic_city` VALUES ('210711', '210711', '太和区', '2107', 3); +INSERT INTO `dic_city` VALUES ('210726', '210726', '黑山县', '2107', 3); +INSERT INTO `dic_city` VALUES ('210727', '210727', '义县', '2107', 3); +INSERT INTO `dic_city` VALUES ('210781', '210781', '凌海市', '2107', 3); +INSERT INTO `dic_city` VALUES ('210782', '210782', '北镇市', '2107', 3); +INSERT INTO `dic_city` VALUES ('2108', '2108', '营口市', '21', 2); +INSERT INTO `dic_city` VALUES ('210802', '210802', '站前区', '2108', 3); +INSERT INTO `dic_city` VALUES ('210803', '210803', '西市区', '2108', 3); +INSERT INTO `dic_city` VALUES ('210804', '210804', '鲅鱼圈区', '2108', 3); +INSERT INTO `dic_city` VALUES ('210811', '210811', '老边区', '2108', 3); +INSERT INTO `dic_city` VALUES ('210881', '210881', '盖州市', '2108', 3); +INSERT INTO `dic_city` VALUES ('210882', '210882', '大石桥市', '2108', 3); +INSERT INTO `dic_city` VALUES ('2109', '2109', '阜新市', '21', 2); +INSERT INTO `dic_city` VALUES ('210902', '210902', '海州区', '2109', 3); +INSERT INTO `dic_city` VALUES ('210903', '210903', '新邱区', '2109', 3); +INSERT INTO `dic_city` VALUES ('210904', '210904', '太平区', '2109', 3); +INSERT INTO `dic_city` VALUES ('210905', '210905', '清河门区', '2109', 3); +INSERT INTO `dic_city` VALUES ('210911', '210911', '细河区', '2109', 3); +INSERT INTO `dic_city` VALUES ('210921', '210921', '阜新蒙古族自治县', '2109', 3); +INSERT INTO `dic_city` VALUES ('210922', '210922', '彰武县', '2109', 3); +INSERT INTO `dic_city` VALUES ('2110', '2110', '辽阳市', '21', 2); +INSERT INTO `dic_city` VALUES ('211002', '211002', '白塔区', '2110', 3); +INSERT INTO `dic_city` VALUES ('211003', '211003', '文圣区', '2110', 3); +INSERT INTO `dic_city` VALUES ('211004', '211004', '宏伟区', '2110', 3); +INSERT INTO `dic_city` VALUES ('211005', '211005', '弓长岭区', '2110', 3); +INSERT INTO `dic_city` VALUES ('211011', '211011', '太子河区', '2110', 3); +INSERT INTO `dic_city` VALUES ('211021', '211021', '辽阳县', '2110', 3); +INSERT INTO `dic_city` VALUES ('211081', '211081', '灯塔市', '2110', 3); +INSERT INTO `dic_city` VALUES ('2111', '2111', '盘锦市', '21', 2); +INSERT INTO `dic_city` VALUES ('211102', '211102', '双台子区', '2111', 3); +INSERT INTO `dic_city` VALUES ('211103', '211103', '兴隆台区', '2111', 3); +INSERT INTO `dic_city` VALUES ('211104', '211104', '大洼区', '2111', 3); +INSERT INTO `dic_city` VALUES ('211122', '211122', '盘山县', '2111', 3); +INSERT INTO `dic_city` VALUES ('2112', '2112', '铁岭市', '21', 2); +INSERT INTO `dic_city` VALUES ('211202', '211202', '银州区', '2112', 3); +INSERT INTO `dic_city` VALUES ('211204', '211204', '清河区', '2112', 3); +INSERT INTO `dic_city` VALUES ('211221', '211221', '铁岭县', '2112', 3); +INSERT INTO `dic_city` VALUES ('211223', '211223', '西丰县', '2112', 3); +INSERT INTO `dic_city` VALUES ('211224', '211224', '昌图县', '2112', 3); +INSERT INTO `dic_city` VALUES ('211281', '211281', '调兵山市', '2112', 3); +INSERT INTO `dic_city` VALUES ('211282', '211282', '开原市', '2112', 3); +INSERT INTO `dic_city` VALUES ('2113', '2113', '朝阳市', '21', 2); +INSERT INTO `dic_city` VALUES ('211302', '211302', '双塔区', '2113', 3); +INSERT INTO `dic_city` VALUES ('211303', '211303', '龙城区', '2113', 3); +INSERT INTO `dic_city` VALUES ('211321', '211321', '朝阳县', '2113', 3); +INSERT INTO `dic_city` VALUES ('211322', '211322', '建平县', '2113', 3); +INSERT INTO `dic_city` VALUES ('211324', '211324', '喀喇沁左翼蒙古族自治县', '2113', 3); +INSERT INTO `dic_city` VALUES ('211381', '211381', '北票市', '2113', 3); +INSERT INTO `dic_city` VALUES ('211382', '211382', '凌源市', '2113', 3); +INSERT INTO `dic_city` VALUES ('2114', '2114', '葫芦岛市', '21', 2); +INSERT INTO `dic_city` VALUES ('211402', '211402', '连山区', '2114', 3); +INSERT INTO `dic_city` VALUES ('211403', '211403', '龙港区', '2114', 3); +INSERT INTO `dic_city` VALUES ('211404', '211404', '南票区', '2114', 3); +INSERT INTO `dic_city` VALUES ('211421', '211421', '绥中县', '2114', 3); +INSERT INTO `dic_city` VALUES ('211422', '211422', '建昌县', '2114', 3); +INSERT INTO `dic_city` VALUES ('211481', '211481', '兴城市', '2114', 3); +INSERT INTO `dic_city` VALUES ('22', '22', '吉林省', NULL, 1); +INSERT INTO `dic_city` VALUES ('2201', '2201', '长春市', '22', 2); +INSERT INTO `dic_city` VALUES ('220102', '220102', '南关区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220103', '220103', '宽城区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220104', '220104', '朝阳区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220105', '220105', '二道区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220106', '220106', '绿园区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220112', '220112', '双阳区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220113', '220113', '九台区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220122', '220122', '农安县', '2201', 3); +INSERT INTO `dic_city` VALUES ('220171', '220171', '长春经济技术开发区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220172', '220172', '长春净月高新技术产业开发区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220173', '220173', '长春高新技术产业开发区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220174', '220174', '长春汽车经济技术开发区', '2201', 3); +INSERT INTO `dic_city` VALUES ('220182', '220182', '榆树市', '2201', 3); +INSERT INTO `dic_city` VALUES ('220183', '220183', '德惠市', '2201', 3); +INSERT INTO `dic_city` VALUES ('220184', '220184', '公主岭市', '2201', 3); +INSERT INTO `dic_city` VALUES ('2202', '2202', '吉林市', '22', 2); +INSERT INTO `dic_city` VALUES ('220202', '220202', '昌邑区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220203', '220203', '龙潭区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220204', '220204', '船营区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220211', '220211', '丰满区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220221', '220221', '永吉县', '2202', 3); +INSERT INTO `dic_city` VALUES ('220271', '220271', '吉林经济开发区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220272', '220272', '吉林高新技术产业开发区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220273', '220273', '吉林中国新加坡食品区', '2202', 3); +INSERT INTO `dic_city` VALUES ('220281', '220281', '蛟河市', '2202', 3); +INSERT INTO `dic_city` VALUES ('220282', '220282', '桦甸市', '2202', 3); +INSERT INTO `dic_city` VALUES ('220283', '220283', '舒兰市', '2202', 3); +INSERT INTO `dic_city` VALUES ('220284', '220284', '磐石市', '2202', 3); +INSERT INTO `dic_city` VALUES ('2203', '2203', '四平市', '22', 2); +INSERT INTO `dic_city` VALUES ('220302', '220302', '铁西区', '2203', 3); +INSERT INTO `dic_city` VALUES ('220303', '220303', '铁东区', '2203', 3); +INSERT INTO `dic_city` VALUES ('220322', '220322', '梨树县', '2203', 3); +INSERT INTO `dic_city` VALUES ('220323', '220323', '伊通满族自治县', '2203', 3); +INSERT INTO `dic_city` VALUES ('220382', '220382', '双辽市', '2203', 3); +INSERT INTO `dic_city` VALUES ('2204', '2204', '辽源市', '22', 2); +INSERT INTO `dic_city` VALUES ('220402', '220402', '龙山区', '2204', 3); +INSERT INTO `dic_city` VALUES ('220403', '220403', '西安区', '2204', 3); +INSERT INTO `dic_city` VALUES ('220421', '220421', '东丰县', '2204', 3); +INSERT INTO `dic_city` VALUES ('220422', '220422', '东辽县', '2204', 3); +INSERT INTO `dic_city` VALUES ('2205', '2205', '通化市', '22', 2); +INSERT INTO `dic_city` VALUES ('220502', '220502', '东昌区', '2205', 3); +INSERT INTO `dic_city` VALUES ('220503', '220503', '二道江区', '2205', 3); +INSERT INTO `dic_city` VALUES ('220521', '220521', '通化县', '2205', 3); +INSERT INTO `dic_city` VALUES ('220523', '220523', '辉南县', '2205', 3); +INSERT INTO `dic_city` VALUES ('220524', '220524', '柳河县', '2205', 3); +INSERT INTO `dic_city` VALUES ('220581', '220581', '梅河口市', '2205', 3); +INSERT INTO `dic_city` VALUES ('220582', '220582', '集安市', '2205', 3); +INSERT INTO `dic_city` VALUES ('2206', '2206', '白山市', '22', 2); +INSERT INTO `dic_city` VALUES ('220602', '220602', '浑江区', '2206', 3); +INSERT INTO `dic_city` VALUES ('220605', '220605', '江源区', '2206', 3); +INSERT INTO `dic_city` VALUES ('220621', '220621', '抚松县', '2206', 3); +INSERT INTO `dic_city` VALUES ('220622', '220622', '靖宇县', '2206', 3); +INSERT INTO `dic_city` VALUES ('220623', '220623', '长白朝鲜族自治县', '2206', 3); +INSERT INTO `dic_city` VALUES ('220681', '220681', '临江市', '2206', 3); +INSERT INTO `dic_city` VALUES ('2207', '2207', '松原市', '22', 2); +INSERT INTO `dic_city` VALUES ('220702', '220702', '宁江区', '2207', 3); +INSERT INTO `dic_city` VALUES ('220721', '220721', '前郭尔罗斯蒙古族自治县', '2207', 3); +INSERT INTO `dic_city` VALUES ('220722', '220722', '长岭县', '2207', 3); +INSERT INTO `dic_city` VALUES ('220723', '220723', '乾安县', '2207', 3); +INSERT INTO `dic_city` VALUES ('220771', '220771', '吉林松原经济开发区', '2207', 3); +INSERT INTO `dic_city` VALUES ('220781', '220781', '扶余市', '2207', 3); +INSERT INTO `dic_city` VALUES ('2208', '2208', '白城市', '22', 2); +INSERT INTO `dic_city` VALUES ('220802', '220802', '洮北区', '2208', 3); +INSERT INTO `dic_city` VALUES ('220821', '220821', '镇赉县', '2208', 3); +INSERT INTO `dic_city` VALUES ('220822', '220822', '通榆县', '2208', 3); +INSERT INTO `dic_city` VALUES ('220871', '220871', '吉林白城经济开发区', '2208', 3); +INSERT INTO `dic_city` VALUES ('220881', '220881', '洮南市', '2208', 3); +INSERT INTO `dic_city` VALUES ('220882', '220882', '大安市', '2208', 3); +INSERT INTO `dic_city` VALUES ('2224', '2224', '延边朝鲜族自治州', '22', 2); +INSERT INTO `dic_city` VALUES ('222401', '222401', '延吉市', '2224', 3); +INSERT INTO `dic_city` VALUES ('222402', '222402', '图们市', '2224', 3); +INSERT INTO `dic_city` VALUES ('222403', '222403', '敦化市', '2224', 3); +INSERT INTO `dic_city` VALUES ('222404', '222404', '珲春市', '2224', 3); +INSERT INTO `dic_city` VALUES ('222405', '222405', '龙井市', '2224', 3); +INSERT INTO `dic_city` VALUES ('222406', '222406', '和龙市', '2224', 3); +INSERT INTO `dic_city` VALUES ('222424', '222424', '汪清县', '2224', 3); +INSERT INTO `dic_city` VALUES ('222426', '222426', '安图县', '2224', 3); +INSERT INTO `dic_city` VALUES ('23', '23', '黑龙江省', NULL, 1); +INSERT INTO `dic_city` VALUES ('2301', '2301', '哈尔滨市', '23', 2); +INSERT INTO `dic_city` VALUES ('230102', '230102', '道里区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230103', '230103', '南岗区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230104', '230104', '道外区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230108', '230108', '平房区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230109', '230109', '松北区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230110', '230110', '香坊区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230111', '230111', '呼兰区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230112', '230112', '阿城区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230113', '230113', '双城区', '2301', 3); +INSERT INTO `dic_city` VALUES ('230123', '230123', '依兰县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230124', '230124', '方正县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230125', '230125', '宾县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230126', '230126', '巴彦县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230127', '230127', '木兰县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230128', '230128', '通河县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230129', '230129', '延寿县', '2301', 3); +INSERT INTO `dic_city` VALUES ('230183', '230183', '尚志市', '2301', 3); +INSERT INTO `dic_city` VALUES ('230184', '230184', '五常市', '2301', 3); +INSERT INTO `dic_city` VALUES ('2302', '2302', '齐齐哈尔市', '23', 2); +INSERT INTO `dic_city` VALUES ('230202', '230202', '龙沙区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230203', '230203', '建华区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230204', '230204', '铁锋区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230205', '230205', '昂昂溪区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230206', '230206', '富拉尔基区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230207', '230207', '碾子山区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230208', '230208', '梅里斯达斡尔族区', '2302', 3); +INSERT INTO `dic_city` VALUES ('230221', '230221', '龙江县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230223', '230223', '依安县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230224', '230224', '泰来县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230225', '230225', '甘南县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230227', '230227', '富裕县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230229', '230229', '克山县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230230', '230230', '克东县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230231', '230231', '拜泉县', '2302', 3); +INSERT INTO `dic_city` VALUES ('230281', '230281', '讷河市', '2302', 3); +INSERT INTO `dic_city` VALUES ('2303', '2303', '鸡西市', '23', 2); +INSERT INTO `dic_city` VALUES ('230302', '230302', '鸡冠区', '2303', 3); +INSERT INTO `dic_city` VALUES ('230303', '230303', '恒山区', '2303', 3); +INSERT INTO `dic_city` VALUES ('230304', '230304', '滴道区', '2303', 3); +INSERT INTO `dic_city` VALUES ('230305', '230305', '梨树区', '2303', 3); +INSERT INTO `dic_city` VALUES ('230306', '230306', '城子河区', '2303', 3); +INSERT INTO `dic_city` VALUES ('230307', '230307', '麻山区', '2303', 3); +INSERT INTO `dic_city` VALUES ('230321', '230321', '鸡东县', '2303', 3); +INSERT INTO `dic_city` VALUES ('230381', '230381', '虎林市', '2303', 3); +INSERT INTO `dic_city` VALUES ('230382', '230382', '密山市', '2303', 3); +INSERT INTO `dic_city` VALUES ('2304', '2304', '鹤岗市', '23', 2); +INSERT INTO `dic_city` VALUES ('230402', '230402', '向阳区', '2304', 3); +INSERT INTO `dic_city` VALUES ('230403', '230403', '工农区', '2304', 3); +INSERT INTO `dic_city` VALUES ('230404', '230404', '南山区', '2304', 3); +INSERT INTO `dic_city` VALUES ('230405', '230405', '兴安区', '2304', 3); +INSERT INTO `dic_city` VALUES ('230406', '230406', '东山区', '2304', 3); +INSERT INTO `dic_city` VALUES ('230407', '230407', '兴山区', '2304', 3); +INSERT INTO `dic_city` VALUES ('230421', '230421', '萝北县', '2304', 3); +INSERT INTO `dic_city` VALUES ('230422', '230422', '绥滨县', '2304', 3); +INSERT INTO `dic_city` VALUES ('2305', '2305', '双鸭山市', '23', 2); +INSERT INTO `dic_city` VALUES ('230502', '230502', '尖山区', '2305', 3); +INSERT INTO `dic_city` VALUES ('230503', '230503', '岭东区', '2305', 3); +INSERT INTO `dic_city` VALUES ('230505', '230505', '四方台区', '2305', 3); +INSERT INTO `dic_city` VALUES ('230506', '230506', '宝山区', '2305', 3); +INSERT INTO `dic_city` VALUES ('230521', '230521', '集贤县', '2305', 3); +INSERT INTO `dic_city` VALUES ('230522', '230522', '友谊县', '2305', 3); +INSERT INTO `dic_city` VALUES ('230523', '230523', '宝清县', '2305', 3); +INSERT INTO `dic_city` VALUES ('230524', '230524', '饶河县', '2305', 3); +INSERT INTO `dic_city` VALUES ('2306', '2306', '大庆市', '23', 2); +INSERT INTO `dic_city` VALUES ('230602', '230602', '萨尔图区', '2306', 3); +INSERT INTO `dic_city` VALUES ('230603', '230603', '龙凤区', '2306', 3); +INSERT INTO `dic_city` VALUES ('230604', '230604', '让胡路区', '2306', 3); +INSERT INTO `dic_city` VALUES ('230605', '230605', '红岗区', '2306', 3); +INSERT INTO `dic_city` VALUES ('230606', '230606', '大同区', '2306', 3); +INSERT INTO `dic_city` VALUES ('230621', '230621', '肇州县', '2306', 3); +INSERT INTO `dic_city` VALUES ('230622', '230622', '肇源县', '2306', 3); +INSERT INTO `dic_city` VALUES ('230623', '230623', '林甸县', '2306', 3); +INSERT INTO `dic_city` VALUES ('230624', '230624', '杜尔伯特蒙古族自治县', '2306', 3); +INSERT INTO `dic_city` VALUES ('230671', '230671', '大庆高新技术产业开发区', '2306', 3); +INSERT INTO `dic_city` VALUES ('2307', '2307', '伊春市', '23', 2); +INSERT INTO `dic_city` VALUES ('230717', '230717', '伊美区', '2307', 3); +INSERT INTO `dic_city` VALUES ('230718', '230718', '乌翠区', '2307', 3); +INSERT INTO `dic_city` VALUES ('230719', '230719', '友好区', '2307', 3); +INSERT INTO `dic_city` VALUES ('230722', '230722', '嘉荫县', '2307', 3); +INSERT INTO `dic_city` VALUES ('230723', '230723', '汤旺县', '2307', 3); +INSERT INTO `dic_city` VALUES ('230724', '230724', '丰林县', '2307', 3); +INSERT INTO `dic_city` VALUES ('230725', '230725', '大箐山县', '2307', 3); +INSERT INTO `dic_city` VALUES ('230726', '230726', '南岔县', '2307', 3); +INSERT INTO `dic_city` VALUES ('230751', '230751', '金林区', '2307', 3); +INSERT INTO `dic_city` VALUES ('230781', '230781', '铁力市', '2307', 3); +INSERT INTO `dic_city` VALUES ('2308', '2308', '佳木斯市', '23', 2); +INSERT INTO `dic_city` VALUES ('230803', '230803', '向阳区', '2308', 3); +INSERT INTO `dic_city` VALUES ('230804', '230804', '前进区', '2308', 3); +INSERT INTO `dic_city` VALUES ('230805', '230805', '东风区', '2308', 3); +INSERT INTO `dic_city` VALUES ('230811', '230811', '郊区', '2308', 3); +INSERT INTO `dic_city` VALUES ('230822', '230822', '桦南县', '2308', 3); +INSERT INTO `dic_city` VALUES ('230826', '230826', '桦川县', '2308', 3); +INSERT INTO `dic_city` VALUES ('230828', '230828', '汤原县', '2308', 3); +INSERT INTO `dic_city` VALUES ('230881', '230881', '同江市', '2308', 3); +INSERT INTO `dic_city` VALUES ('230882', '230882', '富锦市', '2308', 3); +INSERT INTO `dic_city` VALUES ('230883', '230883', '抚远市', '2308', 3); +INSERT INTO `dic_city` VALUES ('2309', '2309', '七台河市', '23', 2); +INSERT INTO `dic_city` VALUES ('230902', '230902', '新兴区', '2309', 3); +INSERT INTO `dic_city` VALUES ('230903', '230903', '桃山区', '2309', 3); +INSERT INTO `dic_city` VALUES ('230904', '230904', '茄子河区', '2309', 3); +INSERT INTO `dic_city` VALUES ('230921', '230921', '勃利县', '2309', 3); +INSERT INTO `dic_city` VALUES ('2310', '2310', '牡丹江市', '23', 2); +INSERT INTO `dic_city` VALUES ('231002', '231002', '东安区', '2310', 3); +INSERT INTO `dic_city` VALUES ('231003', '231003', '阳明区', '2310', 3); +INSERT INTO `dic_city` VALUES ('231004', '231004', '爱民区', '2310', 3); +INSERT INTO `dic_city` VALUES ('231005', '231005', '西安区', '2310', 3); +INSERT INTO `dic_city` VALUES ('231025', '231025', '林口县', '2310', 3); +INSERT INTO `dic_city` VALUES ('231071', '231071', '牡丹江经济技术开发区', '2310', 3); +INSERT INTO `dic_city` VALUES ('231081', '231081', '绥芬河市', '2310', 3); +INSERT INTO `dic_city` VALUES ('231083', '231083', '海林市', '2310', 3); +INSERT INTO `dic_city` VALUES ('231084', '231084', '宁安市', '2310', 3); +INSERT INTO `dic_city` VALUES ('231085', '231085', '穆棱市', '2310', 3); +INSERT INTO `dic_city` VALUES ('231086', '231086', '东宁市', '2310', 3); +INSERT INTO `dic_city` VALUES ('2311', '2311', '黑河市', '23', 2); +INSERT INTO `dic_city` VALUES ('231102', '231102', '爱辉区', '2311', 3); +INSERT INTO `dic_city` VALUES ('231123', '231123', '逊克县', '2311', 3); +INSERT INTO `dic_city` VALUES ('231124', '231124', '孙吴县', '2311', 3); +INSERT INTO `dic_city` VALUES ('231181', '231181', '北安市', '2311', 3); +INSERT INTO `dic_city` VALUES ('231182', '231182', '五大连池市', '2311', 3); +INSERT INTO `dic_city` VALUES ('231183', '231183', '嫩江市', '2311', 3); +INSERT INTO `dic_city` VALUES ('2312', '2312', '绥化市', '23', 2); +INSERT INTO `dic_city` VALUES ('231202', '231202', '北林区', '2312', 3); +INSERT INTO `dic_city` VALUES ('231221', '231221', '望奎县', '2312', 3); +INSERT INTO `dic_city` VALUES ('231222', '231222', '兰西县', '2312', 3); +INSERT INTO `dic_city` VALUES ('231223', '231223', '青冈县', '2312', 3); +INSERT INTO `dic_city` VALUES ('231224', '231224', '庆安县', '2312', 3); +INSERT INTO `dic_city` VALUES ('231225', '231225', '明水县', '2312', 3); +INSERT INTO `dic_city` VALUES ('231226', '231226', '绥棱县', '2312', 3); +INSERT INTO `dic_city` VALUES ('231281', '231281', '安达市', '2312', 3); +INSERT INTO `dic_city` VALUES ('231282', '231282', '肇东市', '2312', 3); +INSERT INTO `dic_city` VALUES ('231283', '231283', '海伦市', '2312', 3); +INSERT INTO `dic_city` VALUES ('2327', '2327', '大兴安岭地区', '23', 2); +INSERT INTO `dic_city` VALUES ('232701', '232701', '漠河市', '2327', 3); +INSERT INTO `dic_city` VALUES ('232721', '232721', '呼玛县', '2327', 3); +INSERT INTO `dic_city` VALUES ('232722', '232722', '塔河县', '2327', 3); +INSERT INTO `dic_city` VALUES ('232761', '232761', '加格达奇区', '2327', 3); +INSERT INTO `dic_city` VALUES ('232762', '232762', '松岭区', '2327', 3); +INSERT INTO `dic_city` VALUES ('232763', '232763', '新林区', '2327', 3); +INSERT INTO `dic_city` VALUES ('232764', '232764', '呼中区', '2327', 3); +INSERT INTO `dic_city` VALUES ('31', '31', '上海市', NULL, 1); +INSERT INTO `dic_city` VALUES ('3101', '3101', '市辖区', '31', 2); +INSERT INTO `dic_city` VALUES ('310101', '310101', '黄浦区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310104', '310104', '徐汇区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310105', '310105', '长宁区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310106', '310106', '静安区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310107', '310107', '普陀区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310109', '310109', '虹口区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310110', '310110', '杨浦区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310112', '310112', '闵行区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310113', '310113', '宝山区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310114', '310114', '嘉定区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310115', '310115', '浦东新区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310116', '310116', '金山区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310117', '310117', '松江区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310118', '310118', '青浦区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310120', '310120', '奉贤区', '3101', 3); +INSERT INTO `dic_city` VALUES ('310151', '310151', '崇明区', '3101', 3); +INSERT INTO `dic_city` VALUES ('32', '32', '江苏省', NULL, 1); +INSERT INTO `dic_city` VALUES ('3201', '3201', '南京市', '32', 2); +INSERT INTO `dic_city` VALUES ('320102', '320102', '玄武区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320104', '320104', '秦淮区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320105', '320105', '建邺区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320106', '320106', '鼓楼区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320111', '320111', '浦口区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320113', '320113', '栖霞区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320114', '320114', '雨花台区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320115', '320115', '江宁区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320116', '320116', '六合区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320117', '320117', '溧水区', '3201', 3); +INSERT INTO `dic_city` VALUES ('320118', '320118', '高淳区', '3201', 3); +INSERT INTO `dic_city` VALUES ('3202', '3202', '无锡市', '32', 2); +INSERT INTO `dic_city` VALUES ('320205', '320205', '锡山区', '3202', 3); +INSERT INTO `dic_city` VALUES ('320206', '320206', '惠山区', '3202', 3); +INSERT INTO `dic_city` VALUES ('320211', '320211', '滨湖区', '3202', 3); +INSERT INTO `dic_city` VALUES ('320213', '320213', '梁溪区', '3202', 3); +INSERT INTO `dic_city` VALUES ('320214', '320214', '新吴区', '3202', 3); +INSERT INTO `dic_city` VALUES ('320281', '320281', '江阴市', '3202', 3); +INSERT INTO `dic_city` VALUES ('320282', '320282', '宜兴市', '3202', 3); +INSERT INTO `dic_city` VALUES ('3203', '3203', '徐州市', '32', 2); +INSERT INTO `dic_city` VALUES ('320302', '320302', '鼓楼区', '3203', 3); +INSERT INTO `dic_city` VALUES ('320303', '320303', '云龙区', '3203', 3); +INSERT INTO `dic_city` VALUES ('320305', '320305', '贾汪区', '3203', 3); +INSERT INTO `dic_city` VALUES ('320311', '320311', '泉山区', '3203', 3); +INSERT INTO `dic_city` VALUES ('320312', '320312', '铜山区', '3203', 3); +INSERT INTO `dic_city` VALUES ('320321', '320321', '丰县', '3203', 3); +INSERT INTO `dic_city` VALUES ('320322', '320322', '沛县', '3203', 3); +INSERT INTO `dic_city` VALUES ('320324', '320324', '睢宁县', '3203', 3); +INSERT INTO `dic_city` VALUES ('320371', '320371', '徐州经济技术开发区', '3203', 3); +INSERT INTO `dic_city` VALUES ('320381', '320381', '新沂市', '3203', 3); +INSERT INTO `dic_city` VALUES ('320382', '320382', '邳州市', '3203', 3); +INSERT INTO `dic_city` VALUES ('3204', '3204', '常州市', '32', 2); +INSERT INTO `dic_city` VALUES ('320402', '320402', '天宁区', '3204', 3); +INSERT INTO `dic_city` VALUES ('320404', '320404', '钟楼区', '3204', 3); +INSERT INTO `dic_city` VALUES ('320411', '320411', '新北区', '3204', 3); +INSERT INTO `dic_city` VALUES ('320412', '320412', '武进区', '3204', 3); +INSERT INTO `dic_city` VALUES ('320413', '320413', '金坛区', '3204', 3); +INSERT INTO `dic_city` VALUES ('320481', '320481', '溧阳市', '3204', 3); +INSERT INTO `dic_city` VALUES ('3205', '3205', '苏州市', '32', 2); +INSERT INTO `dic_city` VALUES ('320505', '320505', '虎丘区', '3205', 3); +INSERT INTO `dic_city` VALUES ('320506', '320506', '吴中区', '3205', 3); +INSERT INTO `dic_city` VALUES ('320507', '320507', '相城区', '3205', 3); +INSERT INTO `dic_city` VALUES ('320508', '320508', '姑苏区', '3205', 3); +INSERT INTO `dic_city` VALUES ('320509', '320509', '吴江区', '3205', 3); +INSERT INTO `dic_city` VALUES ('320571', '320571', '苏州工业园区', '3205', 3); +INSERT INTO `dic_city` VALUES ('320581', '320581', '常熟市', '3205', 3); +INSERT INTO `dic_city` VALUES ('320582', '320582', '张家港市', '3205', 3); +INSERT INTO `dic_city` VALUES ('320583', '320583', '昆山市', '3205', 3); +INSERT INTO `dic_city` VALUES ('320585', '320585', '太仓市', '3205', 3); +INSERT INTO `dic_city` VALUES ('3206', '3206', '南通市', '32', 2); +INSERT INTO `dic_city` VALUES ('320602', '320602', '崇川区', '3206', 3); +INSERT INTO `dic_city` VALUES ('320611', '320611', '港闸区', '3206', 3); +INSERT INTO `dic_city` VALUES ('320612', '320612', '通州区', '3206', 3); +INSERT INTO `dic_city` VALUES ('320623', '320623', '如东县', '3206', 3); +INSERT INTO `dic_city` VALUES ('320671', '320671', '南通经济技术开发区', '3206', 3); +INSERT INTO `dic_city` VALUES ('320681', '320681', '启东市', '3206', 3); +INSERT INTO `dic_city` VALUES ('320682', '320682', '如皋市', '3206', 3); +INSERT INTO `dic_city` VALUES ('320684', '320684', '海门市', '3206', 3); +INSERT INTO `dic_city` VALUES ('320685', '320685', '海安市', '3206', 3); +INSERT INTO `dic_city` VALUES ('3207', '3207', '连云港市', '32', 2); +INSERT INTO `dic_city` VALUES ('320703', '320703', '连云区', '3207', 3); +INSERT INTO `dic_city` VALUES ('320706', '320706', '海州区', '3207', 3); +INSERT INTO `dic_city` VALUES ('320707', '320707', '赣榆区', '3207', 3); +INSERT INTO `dic_city` VALUES ('320722', '320722', '东海县', '3207', 3); +INSERT INTO `dic_city` VALUES ('320723', '320723', '灌云县', '3207', 3); +INSERT INTO `dic_city` VALUES ('320724', '320724', '灌南县', '3207', 3); +INSERT INTO `dic_city` VALUES ('320771', '320771', '连云港经济技术开发区', '3207', 3); +INSERT INTO `dic_city` VALUES ('320772', '320772', '连云港高新技术产业开发区', '3207', 3); +INSERT INTO `dic_city` VALUES ('3208', '3208', '淮安市', '32', 2); +INSERT INTO `dic_city` VALUES ('320803', '320803', '淮安区', '3208', 3); +INSERT INTO `dic_city` VALUES ('320804', '320804', '淮阴区', '3208', 3); +INSERT INTO `dic_city` VALUES ('320812', '320812', '清江浦区', '3208', 3); +INSERT INTO `dic_city` VALUES ('320813', '320813', '洪泽区', '3208', 3); +INSERT INTO `dic_city` VALUES ('320826', '320826', '涟水县', '3208', 3); +INSERT INTO `dic_city` VALUES ('320830', '320830', '盱眙县', '3208', 3); +INSERT INTO `dic_city` VALUES ('320831', '320831', '金湖县', '3208', 3); +INSERT INTO `dic_city` VALUES ('320871', '320871', '淮安经济技术开发区', '3208', 3); +INSERT INTO `dic_city` VALUES ('3209', '3209', '盐城市', '32', 2); +INSERT INTO `dic_city` VALUES ('320902', '320902', '亭湖区', '3209', 3); +INSERT INTO `dic_city` VALUES ('320903', '320903', '盐都区', '3209', 3); +INSERT INTO `dic_city` VALUES ('320904', '320904', '大丰区', '3209', 3); +INSERT INTO `dic_city` VALUES ('320921', '320921', '响水县', '3209', 3); +INSERT INTO `dic_city` VALUES ('320922', '320922', '滨海县', '3209', 3); +INSERT INTO `dic_city` VALUES ('320923', '320923', '阜宁县', '3209', 3); +INSERT INTO `dic_city` VALUES ('320924', '320924', '射阳县', '3209', 3); +INSERT INTO `dic_city` VALUES ('320925', '320925', '建湖县', '3209', 3); +INSERT INTO `dic_city` VALUES ('320971', '320971', '盐城经济技术开发区', '3209', 3); +INSERT INTO `dic_city` VALUES ('320981', '320981', '东台市', '3209', 3); +INSERT INTO `dic_city` VALUES ('3210', '3210', '扬州市', '32', 2); +INSERT INTO `dic_city` VALUES ('321002', '321002', '广陵区', '3210', 3); +INSERT INTO `dic_city` VALUES ('321003', '321003', '邗江区', '3210', 3); +INSERT INTO `dic_city` VALUES ('321012', '321012', '江都区', '3210', 3); +INSERT INTO `dic_city` VALUES ('321023', '321023', '宝应县', '3210', 3); +INSERT INTO `dic_city` VALUES ('321071', '321071', '扬州经济技术开发区', '3210', 3); +INSERT INTO `dic_city` VALUES ('321081', '321081', '仪征市', '3210', 3); +INSERT INTO `dic_city` VALUES ('321084', '321084', '高邮市', '3210', 3); +INSERT INTO `dic_city` VALUES ('3211', '3211', '镇江市', '32', 2); +INSERT INTO `dic_city` VALUES ('321102', '321102', '京口区', '3211', 3); +INSERT INTO `dic_city` VALUES ('321111', '321111', '润州区', '3211', 3); +INSERT INTO `dic_city` VALUES ('321112', '321112', '丹徒区', '3211', 3); +INSERT INTO `dic_city` VALUES ('321171', '321171', '镇江新区', '3211', 3); +INSERT INTO `dic_city` VALUES ('321181', '321181', '丹阳市', '3211', 3); +INSERT INTO `dic_city` VALUES ('321182', '321182', '扬中市', '3211', 3); +INSERT INTO `dic_city` VALUES ('321183', '321183', '句容市', '3211', 3); +INSERT INTO `dic_city` VALUES ('3212', '3212', '泰州市', '32', 2); +INSERT INTO `dic_city` VALUES ('321202', '321202', '海陵区', '3212', 3); +INSERT INTO `dic_city` VALUES ('321203', '321203', '高港区', '3212', 3); +INSERT INTO `dic_city` VALUES ('321204', '321204', '姜堰区', '3212', 3); +INSERT INTO `dic_city` VALUES ('321271', '321271', '泰州医药高新技术产业开发区', '3212', 3); +INSERT INTO `dic_city` VALUES ('321281', '321281', '兴化市', '3212', 3); +INSERT INTO `dic_city` VALUES ('321282', '321282', '靖江市', '3212', 3); +INSERT INTO `dic_city` VALUES ('321283', '321283', '泰兴市', '3212', 3); +INSERT INTO `dic_city` VALUES ('3213', '3213', '宿迁市', '32', 2); +INSERT INTO `dic_city` VALUES ('321302', '321302', '宿城区', '3213', 3); +INSERT INTO `dic_city` VALUES ('321311', '321311', '宿豫区', '3213', 3); +INSERT INTO `dic_city` VALUES ('321322', '321322', '沭阳县', '3213', 3); +INSERT INTO `dic_city` VALUES ('321323', '321323', '泗阳县', '3213', 3); +INSERT INTO `dic_city` VALUES ('321324', '321324', '泗洪县', '3213', 3); +INSERT INTO `dic_city` VALUES ('321371', '321371', '宿迁经济技术开发区', '3213', 3); +INSERT INTO `dic_city` VALUES ('33', '33', '浙江省', NULL, 1); +INSERT INTO `dic_city` VALUES ('3301', '3301', '杭州市', '33', 2); +INSERT INTO `dic_city` VALUES ('330102', '330102', '上城区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330103', '330103', '下城区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330104', '330104', '江干区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330105', '330105', '拱墅区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330106', '330106', '西湖区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330108', '330108', '滨江区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330109', '330109', '萧山区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330110', '330110', '余杭区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330111', '330111', '富阳区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330112', '330112', '临安区', '3301', 3); +INSERT INTO `dic_city` VALUES ('330122', '330122', '桐庐县', '3301', 3); +INSERT INTO `dic_city` VALUES ('330127', '330127', '淳安县', '3301', 3); +INSERT INTO `dic_city` VALUES ('330182', '330182', '建德市', '3301', 3); +INSERT INTO `dic_city` VALUES ('3302', '3302', '宁波市', '33', 2); +INSERT INTO `dic_city` VALUES ('330203', '330203', '海曙区', '3302', 3); +INSERT INTO `dic_city` VALUES ('330205', '330205', '江北区', '3302', 3); +INSERT INTO `dic_city` VALUES ('330206', '330206', '北仑区', '3302', 3); +INSERT INTO `dic_city` VALUES ('330211', '330211', '镇海区', '3302', 3); +INSERT INTO `dic_city` VALUES ('330212', '330212', '鄞州区', '3302', 3); +INSERT INTO `dic_city` VALUES ('330213', '330213', '奉化区', '3302', 3); +INSERT INTO `dic_city` VALUES ('330225', '330225', '象山县', '3302', 3); +INSERT INTO `dic_city` VALUES ('330226', '330226', '宁海县', '3302', 3); +INSERT INTO `dic_city` VALUES ('330281', '330281', '余姚市', '3302', 3); +INSERT INTO `dic_city` VALUES ('330282', '330282', '慈溪市', '3302', 3); +INSERT INTO `dic_city` VALUES ('3303', '3303', '温州市', '33', 2); +INSERT INTO `dic_city` VALUES ('330302', '330302', '鹿城区', '3303', 3); +INSERT INTO `dic_city` VALUES ('330303', '330303', '龙湾区', '3303', 3); +INSERT INTO `dic_city` VALUES ('330304', '330304', '瓯海区', '3303', 3); +INSERT INTO `dic_city` VALUES ('330305', '330305', '洞头区', '3303', 3); +INSERT INTO `dic_city` VALUES ('330324', '330324', '永嘉县', '3303', 3); +INSERT INTO `dic_city` VALUES ('330326', '330326', '平阳县', '3303', 3); +INSERT INTO `dic_city` VALUES ('330327', '330327', '苍南县', '3303', 3); +INSERT INTO `dic_city` VALUES ('330328', '330328', '文成县', '3303', 3); +INSERT INTO `dic_city` VALUES ('330329', '330329', '泰顺县', '3303', 3); +INSERT INTO `dic_city` VALUES ('330371', '330371', '温州经济技术开发区', '3303', 3); +INSERT INTO `dic_city` VALUES ('330381', '330381', '瑞安市', '3303', 3); +INSERT INTO `dic_city` VALUES ('330382', '330382', '乐清市', '3303', 3); +INSERT INTO `dic_city` VALUES ('330383', '330383', '龙港市', '3303', 3); +INSERT INTO `dic_city` VALUES ('3304', '3304', '嘉兴市', '33', 2); +INSERT INTO `dic_city` VALUES ('330402', '330402', '南湖区', '3304', 3); +INSERT INTO `dic_city` VALUES ('330411', '330411', '秀洲区', '3304', 3); +INSERT INTO `dic_city` VALUES ('330421', '330421', '嘉善县', '3304', 3); +INSERT INTO `dic_city` VALUES ('330424', '330424', '海盐县', '3304', 3); +INSERT INTO `dic_city` VALUES ('330481', '330481', '海宁市', '3304', 3); +INSERT INTO `dic_city` VALUES ('330482', '330482', '平湖市', '3304', 3); +INSERT INTO `dic_city` VALUES ('330483', '330483', '桐乡市', '3304', 3); +INSERT INTO `dic_city` VALUES ('3305', '3305', '湖州市', '33', 2); +INSERT INTO `dic_city` VALUES ('330502', '330502', '吴兴区', '3305', 3); +INSERT INTO `dic_city` VALUES ('330503', '330503', '南浔区', '3305', 3); +INSERT INTO `dic_city` VALUES ('330521', '330521', '德清县', '3305', 3); +INSERT INTO `dic_city` VALUES ('330522', '330522', '长兴县', '3305', 3); +INSERT INTO `dic_city` VALUES ('330523', '330523', '安吉县', '3305', 3); +INSERT INTO `dic_city` VALUES ('3306', '3306', '绍兴市', '33', 2); +INSERT INTO `dic_city` VALUES ('330602', '330602', '越城区', '3306', 3); +INSERT INTO `dic_city` VALUES ('330603', '330603', '柯桥区', '3306', 3); +INSERT INTO `dic_city` VALUES ('330604', '330604', '上虞区', '3306', 3); +INSERT INTO `dic_city` VALUES ('330624', '330624', '新昌县', '3306', 3); +INSERT INTO `dic_city` VALUES ('330681', '330681', '诸暨市', '3306', 3); +INSERT INTO `dic_city` VALUES ('330683', '330683', '嵊州市', '3306', 3); +INSERT INTO `dic_city` VALUES ('3307', '3307', '金华市', '33', 2); +INSERT INTO `dic_city` VALUES ('330702', '330702', '婺城区', '3307', 3); +INSERT INTO `dic_city` VALUES ('330703', '330703', '金东区', '3307', 3); +INSERT INTO `dic_city` VALUES ('330723', '330723', '武义县', '3307', 3); +INSERT INTO `dic_city` VALUES ('330726', '330726', '浦江县', '3307', 3); +INSERT INTO `dic_city` VALUES ('330727', '330727', '磐安县', '3307', 3); +INSERT INTO `dic_city` VALUES ('330781', '330781', '兰溪市', '3307', 3); +INSERT INTO `dic_city` VALUES ('330782', '330782', '义乌市', '3307', 3); +INSERT INTO `dic_city` VALUES ('330783', '330783', '东阳市', '3307', 3); +INSERT INTO `dic_city` VALUES ('330784', '330784', '永康市', '3307', 3); +INSERT INTO `dic_city` VALUES ('3308', '3308', '衢州市', '33', 2); +INSERT INTO `dic_city` VALUES ('330802', '330802', '柯城区', '3308', 3); +INSERT INTO `dic_city` VALUES ('330803', '330803', '衢江区', '3308', 3); +INSERT INTO `dic_city` VALUES ('330822', '330822', '常山县', '3308', 3); +INSERT INTO `dic_city` VALUES ('330824', '330824', '开化县', '3308', 3); +INSERT INTO `dic_city` VALUES ('330825', '330825', '龙游县', '3308', 3); +INSERT INTO `dic_city` VALUES ('330881', '330881', '江山市', '3308', 3); +INSERT INTO `dic_city` VALUES ('3309', '3309', '舟山市', '33', 2); +INSERT INTO `dic_city` VALUES ('330902', '330902', '定海区', '3309', 3); +INSERT INTO `dic_city` VALUES ('330903', '330903', '普陀区', '3309', 3); +INSERT INTO `dic_city` VALUES ('330921', '330921', '岱山县', '3309', 3); +INSERT INTO `dic_city` VALUES ('330922', '330922', '嵊泗县', '3309', 3); +INSERT INTO `dic_city` VALUES ('3310', '3310', '台州市', '33', 2); +INSERT INTO `dic_city` VALUES ('331002', '331002', '椒江区', '3310', 3); +INSERT INTO `dic_city` VALUES ('331003', '331003', '黄岩区', '3310', 3); +INSERT INTO `dic_city` VALUES ('331004', '331004', '路桥区', '3310', 3); +INSERT INTO `dic_city` VALUES ('331022', '331022', '三门县', '3310', 3); +INSERT INTO `dic_city` VALUES ('331023', '331023', '天台县', '3310', 3); +INSERT INTO `dic_city` VALUES ('331024', '331024', '仙居县', '3310', 3); +INSERT INTO `dic_city` VALUES ('331081', '331081', '温岭市', '3310', 3); +INSERT INTO `dic_city` VALUES ('331082', '331082', '临海市', '3310', 3); +INSERT INTO `dic_city` VALUES ('331083', '331083', '玉环市', '3310', 3); +INSERT INTO `dic_city` VALUES ('3311', '3311', '丽水市', '33', 2); +INSERT INTO `dic_city` VALUES ('331102', '331102', '莲都区', '3311', 3); +INSERT INTO `dic_city` VALUES ('331121', '331121', '青田县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331122', '331122', '缙云县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331123', '331123', '遂昌县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331124', '331124', '松阳县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331125', '331125', '云和县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331126', '331126', '庆元县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331127', '331127', '景宁畲族自治县', '3311', 3); +INSERT INTO `dic_city` VALUES ('331181', '331181', '龙泉市', '3311', 3); +INSERT INTO `dic_city` VALUES ('34', '34', '安徽省', NULL, 1); +INSERT INTO `dic_city` VALUES ('3401', '3401', '合肥市', '34', 2); +INSERT INTO `dic_city` VALUES ('340102', '340102', '瑶海区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340103', '340103', '庐阳区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340104', '340104', '蜀山区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340111', '340111', '包河区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340121', '340121', '长丰县', '3401', 3); +INSERT INTO `dic_city` VALUES ('340122', '340122', '肥东县', '3401', 3); +INSERT INTO `dic_city` VALUES ('340123', '340123', '肥西县', '3401', 3); +INSERT INTO `dic_city` VALUES ('340124', '340124', '庐江县', '3401', 3); +INSERT INTO `dic_city` VALUES ('340171', '340171', '合肥高新技术产业开发区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340172', '340172', '合肥经济技术开发区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340173', '340173', '合肥新站高新技术产业开发区', '3401', 3); +INSERT INTO `dic_city` VALUES ('340181', '340181', '巢湖市', '3401', 3); +INSERT INTO `dic_city` VALUES ('3402', '3402', '芜湖市', '34', 2); +INSERT INTO `dic_city` VALUES ('340202', '340202', '镜湖区', '3402', 3); +INSERT INTO `dic_city` VALUES ('340203', '340203', '弋江区', '3402', 3); +INSERT INTO `dic_city` VALUES ('340207', '340207', '鸠江区', '3402', 3); +INSERT INTO `dic_city` VALUES ('340208', '340208', '三山区', '3402', 3); +INSERT INTO `dic_city` VALUES ('340221', '340221', '芜湖县', '3402', 3); +INSERT INTO `dic_city` VALUES ('340222', '340222', '繁昌县', '3402', 3); +INSERT INTO `dic_city` VALUES ('340223', '340223', '南陵县', '3402', 3); +INSERT INTO `dic_city` VALUES ('340271', '340271', '芜湖经济技术开发区', '3402', 3); +INSERT INTO `dic_city` VALUES ('340272', '340272', '安徽芜湖长江大桥经济开发区', '3402', 3); +INSERT INTO `dic_city` VALUES ('340281', '340281', '无为市', '3402', 3); +INSERT INTO `dic_city` VALUES ('3403', '3403', '蚌埠市', '34', 2); +INSERT INTO `dic_city` VALUES ('340302', '340302', '龙子湖区', '3403', 3); +INSERT INTO `dic_city` VALUES ('340303', '340303', '蚌山区', '3403', 3); +INSERT INTO `dic_city` VALUES ('340304', '340304', '禹会区', '3403', 3); +INSERT INTO `dic_city` VALUES ('340311', '340311', '淮上区', '3403', 3); +INSERT INTO `dic_city` VALUES ('340321', '340321', '怀远县', '3403', 3); +INSERT INTO `dic_city` VALUES ('340322', '340322', '五河县', '3403', 3); +INSERT INTO `dic_city` VALUES ('340323', '340323', '固镇县', '3403', 3); +INSERT INTO `dic_city` VALUES ('340371', '340371', '蚌埠市高新技术开发区', '3403', 3); +INSERT INTO `dic_city` VALUES ('340372', '340372', '蚌埠市经济开发区', '3403', 3); +INSERT INTO `dic_city` VALUES ('3404', '3404', '淮南市', '34', 2); +INSERT INTO `dic_city` VALUES ('340402', '340402', '大通区', '3404', 3); +INSERT INTO `dic_city` VALUES ('340403', '340403', '田家庵区', '3404', 3); +INSERT INTO `dic_city` VALUES ('340404', '340404', '谢家集区', '3404', 3); +INSERT INTO `dic_city` VALUES ('340405', '340405', '八公山区', '3404', 3); +INSERT INTO `dic_city` VALUES ('340406', '340406', '潘集区', '3404', 3); +INSERT INTO `dic_city` VALUES ('340421', '340421', '凤台县', '3404', 3); +INSERT INTO `dic_city` VALUES ('340422', '340422', '寿县', '3404', 3); +INSERT INTO `dic_city` VALUES ('3405', '3405', '马鞍山市', '34', 2); +INSERT INTO `dic_city` VALUES ('340503', '340503', '花山区', '3405', 3); +INSERT INTO `dic_city` VALUES ('340504', '340504', '雨山区', '3405', 3); +INSERT INTO `dic_city` VALUES ('340506', '340506', '博望区', '3405', 3); +INSERT INTO `dic_city` VALUES ('340521', '340521', '当涂县', '3405', 3); +INSERT INTO `dic_city` VALUES ('340522', '340522', '含山县', '3405', 3); +INSERT INTO `dic_city` VALUES ('340523', '340523', '和县', '3405', 3); +INSERT INTO `dic_city` VALUES ('3406', '3406', '淮北市', '34', 2); +INSERT INTO `dic_city` VALUES ('340602', '340602', '杜集区', '3406', 3); +INSERT INTO `dic_city` VALUES ('340603', '340603', '相山区', '3406', 3); +INSERT INTO `dic_city` VALUES ('340604', '340604', '烈山区', '3406', 3); +INSERT INTO `dic_city` VALUES ('340621', '340621', '濉溪县', '3406', 3); +INSERT INTO `dic_city` VALUES ('3407', '3407', '铜陵市', '34', 2); +INSERT INTO `dic_city` VALUES ('340705', '340705', '铜官区', '3407', 3); +INSERT INTO `dic_city` VALUES ('340706', '340706', '义安区', '3407', 3); +INSERT INTO `dic_city` VALUES ('340711', '340711', '郊区', '3407', 3); +INSERT INTO `dic_city` VALUES ('340722', '340722', '枞阳县', '3407', 3); +INSERT INTO `dic_city` VALUES ('3408', '3408', '安庆市', '34', 2); +INSERT INTO `dic_city` VALUES ('340802', '340802', '迎江区', '3408', 3); +INSERT INTO `dic_city` VALUES ('340803', '340803', '大观区', '3408', 3); +INSERT INTO `dic_city` VALUES ('340811', '340811', '宜秀区', '3408', 3); +INSERT INTO `dic_city` VALUES ('340822', '340822', '怀宁县', '3408', 3); +INSERT INTO `dic_city` VALUES ('340825', '340825', '太湖县', '3408', 3); +INSERT INTO `dic_city` VALUES ('340826', '340826', '宿松县', '3408', 3); +INSERT INTO `dic_city` VALUES ('340827', '340827', '望江县', '3408', 3); +INSERT INTO `dic_city` VALUES ('340828', '340828', '岳西县', '3408', 3); +INSERT INTO `dic_city` VALUES ('340871', '340871', '安徽安庆经济开发区', '3408', 3); +INSERT INTO `dic_city` VALUES ('340881', '340881', '桐城市', '3408', 3); +INSERT INTO `dic_city` VALUES ('340882', '340882', '潜山市', '3408', 3); +INSERT INTO `dic_city` VALUES ('3410', '3410', '黄山市', '34', 2); +INSERT INTO `dic_city` VALUES ('341002', '341002', '屯溪区', '3410', 3); +INSERT INTO `dic_city` VALUES ('341003', '341003', '黄山区', '3410', 3); +INSERT INTO `dic_city` VALUES ('341004', '341004', '徽州区', '3410', 3); +INSERT INTO `dic_city` VALUES ('341021', '341021', '歙县', '3410', 3); +INSERT INTO `dic_city` VALUES ('341022', '341022', '休宁县', '3410', 3); +INSERT INTO `dic_city` VALUES ('341023', '341023', '黟县', '3410', 3); +INSERT INTO `dic_city` VALUES ('341024', '341024', '祁门县', '3410', 3); +INSERT INTO `dic_city` VALUES ('3411', '3411', '滁州市', '34', 2); +INSERT INTO `dic_city` VALUES ('341102', '341102', '琅琊区', '3411', 3); +INSERT INTO `dic_city` VALUES ('341103', '341103', '南谯区', '3411', 3); +INSERT INTO `dic_city` VALUES ('341122', '341122', '来安县', '3411', 3); +INSERT INTO `dic_city` VALUES ('341124', '341124', '全椒县', '3411', 3); +INSERT INTO `dic_city` VALUES ('341125', '341125', '定远县', '3411', 3); +INSERT INTO `dic_city` VALUES ('341126', '341126', '凤阳县', '3411', 3); +INSERT INTO `dic_city` VALUES ('341171', '341171', '苏滁现代产业园', '3411', 3); +INSERT INTO `dic_city` VALUES ('341172', '341172', '滁州经济技术开发区', '3411', 3); +INSERT INTO `dic_city` VALUES ('341181', '341181', '天长市', '3411', 3); +INSERT INTO `dic_city` VALUES ('341182', '341182', '明光市', '3411', 3); +INSERT INTO `dic_city` VALUES ('3412', '3412', '阜阳市', '34', 2); +INSERT INTO `dic_city` VALUES ('341202', '341202', '颍州区', '3412', 3); +INSERT INTO `dic_city` VALUES ('341203', '341203', '颍东区', '3412', 3); +INSERT INTO `dic_city` VALUES ('341204', '341204', '颍泉区', '3412', 3); +INSERT INTO `dic_city` VALUES ('341221', '341221', '临泉县', '3412', 3); +INSERT INTO `dic_city` VALUES ('341222', '341222', '太和县', '3412', 3); +INSERT INTO `dic_city` VALUES ('341225', '341225', '阜南县', '3412', 3); +INSERT INTO `dic_city` VALUES ('341226', '341226', '颍上县', '3412', 3); +INSERT INTO `dic_city` VALUES ('341271', '341271', '阜阳合肥现代产业园区', '3412', 3); +INSERT INTO `dic_city` VALUES ('341272', '341272', '阜阳经济技术开发区', '3412', 3); +INSERT INTO `dic_city` VALUES ('341282', '341282', '界首市', '3412', 3); +INSERT INTO `dic_city` VALUES ('3413', '3413', '宿州市', '34', 2); +INSERT INTO `dic_city` VALUES ('341302', '341302', '埇桥区', '3413', 3); +INSERT INTO `dic_city` VALUES ('341321', '341321', '砀山县', '3413', 3); +INSERT INTO `dic_city` VALUES ('341322', '341322', '萧县', '3413', 3); +INSERT INTO `dic_city` VALUES ('341323', '341323', '灵璧县', '3413', 3); +INSERT INTO `dic_city` VALUES ('341324', '341324', '泗县', '3413', 3); +INSERT INTO `dic_city` VALUES ('341371', '341371', '宿州马鞍山现代产业园区', '3413', 3); +INSERT INTO `dic_city` VALUES ('341372', '341372', '宿州经济技术开发区', '3413', 3); +INSERT INTO `dic_city` VALUES ('3415', '3415', '六安市', '34', 2); +INSERT INTO `dic_city` VALUES ('341502', '341502', '金安区', '3415', 3); +INSERT INTO `dic_city` VALUES ('341503', '341503', '裕安区', '3415', 3); +INSERT INTO `dic_city` VALUES ('341504', '341504', '叶集区', '3415', 3); +INSERT INTO `dic_city` VALUES ('341522', '341522', '霍邱县', '3415', 3); +INSERT INTO `dic_city` VALUES ('341523', '341523', '舒城县', '3415', 3); +INSERT INTO `dic_city` VALUES ('341524', '341524', '金寨县', '3415', 3); +INSERT INTO `dic_city` VALUES ('341525', '341525', '霍山县', '3415', 3); +INSERT INTO `dic_city` VALUES ('3416', '3416', '亳州市', '34', 2); +INSERT INTO `dic_city` VALUES ('341602', '341602', '谯城区', '3416', 3); +INSERT INTO `dic_city` VALUES ('341621', '341621', '涡阳县', '3416', 3); +INSERT INTO `dic_city` VALUES ('341622', '341622', '蒙城县', '3416', 3); +INSERT INTO `dic_city` VALUES ('341623', '341623', '利辛县', '3416', 3); +INSERT INTO `dic_city` VALUES ('3417', '3417', '池州市', '34', 2); +INSERT INTO `dic_city` VALUES ('341702', '341702', '贵池区', '3417', 3); +INSERT INTO `dic_city` VALUES ('341721', '341721', '东至县', '3417', 3); +INSERT INTO `dic_city` VALUES ('341722', '341722', '石台县', '3417', 3); +INSERT INTO `dic_city` VALUES ('341723', '341723', '青阳县', '3417', 3); +INSERT INTO `dic_city` VALUES ('3418', '3418', '宣城市', '34', 2); +INSERT INTO `dic_city` VALUES ('341802', '341802', '宣州区', '3418', 3); +INSERT INTO `dic_city` VALUES ('341821', '341821', '郎溪县', '3418', 3); +INSERT INTO `dic_city` VALUES ('341823', '341823', '泾县', '3418', 3); +INSERT INTO `dic_city` VALUES ('341824', '341824', '绩溪县', '3418', 3); +INSERT INTO `dic_city` VALUES ('341825', '341825', '旌德县', '3418', 3); +INSERT INTO `dic_city` VALUES ('341871', '341871', '宣城市经济开发区', '3418', 3); +INSERT INTO `dic_city` VALUES ('341881', '341881', '宁国市', '3418', 3); +INSERT INTO `dic_city` VALUES ('341882', '341882', '广德市', '3418', 3); +INSERT INTO `dic_city` VALUES ('35', '35', '福建省', NULL, 1); +INSERT INTO `dic_city` VALUES ('3501', '3501', '福州市', '35', 2); +INSERT INTO `dic_city` VALUES ('350102', '350102', '鼓楼区', '3501', 3); +INSERT INTO `dic_city` VALUES ('350103', '350103', '台江区', '3501', 3); +INSERT INTO `dic_city` VALUES ('350104', '350104', '仓山区', '3501', 3); +INSERT INTO `dic_city` VALUES ('350105', '350105', '马尾区', '3501', 3); +INSERT INTO `dic_city` VALUES ('350111', '350111', '晋安区', '3501', 3); +INSERT INTO `dic_city` VALUES ('350112', '350112', '长乐区', '3501', 3); +INSERT INTO `dic_city` VALUES ('350121', '350121', '闽侯县', '3501', 3); +INSERT INTO `dic_city` VALUES ('350122', '350122', '连江县', '3501', 3); +INSERT INTO `dic_city` VALUES ('350123', '350123', '罗源县', '3501', 3); +INSERT INTO `dic_city` VALUES ('350124', '350124', '闽清县', '3501', 3); +INSERT INTO `dic_city` VALUES ('350125', '350125', '永泰县', '3501', 3); +INSERT INTO `dic_city` VALUES ('350128', '350128', '平潭县', '3501', 3); +INSERT INTO `dic_city` VALUES ('350181', '350181', '福清市', '3501', 3); +INSERT INTO `dic_city` VALUES ('3502', '3502', '厦门市', '35', 2); +INSERT INTO `dic_city` VALUES ('350203', '350203', '思明区', '3502', 3); +INSERT INTO `dic_city` VALUES ('350205', '350205', '海沧区', '3502', 3); +INSERT INTO `dic_city` VALUES ('350206', '350206', '湖里区', '3502', 3); +INSERT INTO `dic_city` VALUES ('350211', '350211', '集美区', '3502', 3); +INSERT INTO `dic_city` VALUES ('350212', '350212', '同安区', '3502', 3); +INSERT INTO `dic_city` VALUES ('350213', '350213', '翔安区', '3502', 3); +INSERT INTO `dic_city` VALUES ('3503', '3503', '莆田市', '35', 2); +INSERT INTO `dic_city` VALUES ('350302', '350302', '城厢区', '3503', 3); +INSERT INTO `dic_city` VALUES ('350303', '350303', '涵江区', '3503', 3); +INSERT INTO `dic_city` VALUES ('350304', '350304', '荔城区', '3503', 3); +INSERT INTO `dic_city` VALUES ('350305', '350305', '秀屿区', '3503', 3); +INSERT INTO `dic_city` VALUES ('350322', '350322', '仙游县', '3503', 3); +INSERT INTO `dic_city` VALUES ('3504', '3504', '三明市', '35', 2); +INSERT INTO `dic_city` VALUES ('350402', '350402', '梅列区', '3504', 3); +INSERT INTO `dic_city` VALUES ('350403', '350403', '三元区', '3504', 3); +INSERT INTO `dic_city` VALUES ('350421', '350421', '明溪县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350423', '350423', '清流县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350424', '350424', '宁化县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350425', '350425', '大田县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350426', '350426', '尤溪县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350427', '350427', '沙县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350428', '350428', '将乐县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350429', '350429', '泰宁县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350430', '350430', '建宁县', '3504', 3); +INSERT INTO `dic_city` VALUES ('350481', '350481', '永安市', '3504', 3); +INSERT INTO `dic_city` VALUES ('3505', '3505', '泉州市', '35', 2); +INSERT INTO `dic_city` VALUES ('350502', '350502', '鲤城区', '3505', 3); +INSERT INTO `dic_city` VALUES ('350503', '350503', '丰泽区', '3505', 3); +INSERT INTO `dic_city` VALUES ('350504', '350504', '洛江区', '3505', 3); +INSERT INTO `dic_city` VALUES ('350505', '350505', '泉港区', '3505', 3); +INSERT INTO `dic_city` VALUES ('350521', '350521', '惠安县', '3505', 3); +INSERT INTO `dic_city` VALUES ('350524', '350524', '安溪县', '3505', 3); +INSERT INTO `dic_city` VALUES ('350525', '350525', '永春县', '3505', 3); +INSERT INTO `dic_city` VALUES ('350526', '350526', '德化县', '3505', 3); +INSERT INTO `dic_city` VALUES ('350527', '350527', '金门县', '3505', 3); +INSERT INTO `dic_city` VALUES ('350581', '350581', '石狮市', '3505', 3); +INSERT INTO `dic_city` VALUES ('350582', '350582', '晋江市', '3505', 3); +INSERT INTO `dic_city` VALUES ('350583', '350583', '南安市', '3505', 3); +INSERT INTO `dic_city` VALUES ('3506', '3506', '漳州市', '35', 2); +INSERT INTO `dic_city` VALUES ('350602', '350602', '芗城区', '3506', 3); +INSERT INTO `dic_city` VALUES ('350603', '350603', '龙文区', '3506', 3); +INSERT INTO `dic_city` VALUES ('350622', '350622', '云霄县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350623', '350623', '漳浦县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350624', '350624', '诏安县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350625', '350625', '长泰县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350626', '350626', '东山县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350627', '350627', '南靖县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350628', '350628', '平和县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350629', '350629', '华安县', '3506', 3); +INSERT INTO `dic_city` VALUES ('350681', '350681', '龙海市', '3506', 3); +INSERT INTO `dic_city` VALUES ('3507', '3507', '南平市', '35', 2); +INSERT INTO `dic_city` VALUES ('350702', '350702', '延平区', '3507', 3); +INSERT INTO `dic_city` VALUES ('350703', '350703', '建阳区', '3507', 3); +INSERT INTO `dic_city` VALUES ('350721', '350721', '顺昌县', '3507', 3); +INSERT INTO `dic_city` VALUES ('350722', '350722', '浦城县', '3507', 3); +INSERT INTO `dic_city` VALUES ('350723', '350723', '光泽县', '3507', 3); +INSERT INTO `dic_city` VALUES ('350724', '350724', '松溪县', '3507', 3); +INSERT INTO `dic_city` VALUES ('350725', '350725', '政和县', '3507', 3); +INSERT INTO `dic_city` VALUES ('350781', '350781', '邵武市', '3507', 3); +INSERT INTO `dic_city` VALUES ('350782', '350782', '武夷山市', '3507', 3); +INSERT INTO `dic_city` VALUES ('350783', '350783', '建瓯市', '3507', 3); +INSERT INTO `dic_city` VALUES ('3508', '3508', '龙岩市', '35', 2); +INSERT INTO `dic_city` VALUES ('350802', '350802', '新罗区', '3508', 3); +INSERT INTO `dic_city` VALUES ('350803', '350803', '永定区', '3508', 3); +INSERT INTO `dic_city` VALUES ('350821', '350821', '长汀县', '3508', 3); +INSERT INTO `dic_city` VALUES ('350823', '350823', '上杭县', '3508', 3); +INSERT INTO `dic_city` VALUES ('350824', '350824', '武平县', '3508', 3); +INSERT INTO `dic_city` VALUES ('350825', '350825', '连城县', '3508', 3); +INSERT INTO `dic_city` VALUES ('350881', '350881', '漳平市', '3508', 3); +INSERT INTO `dic_city` VALUES ('3509', '3509', '宁德市', '35', 2); +INSERT INTO `dic_city` VALUES ('350902', '350902', '蕉城区', '3509', 3); +INSERT INTO `dic_city` VALUES ('350921', '350921', '霞浦县', '3509', 3); +INSERT INTO `dic_city` VALUES ('350922', '350922', '古田县', '3509', 3); +INSERT INTO `dic_city` VALUES ('350923', '350923', '屏南县', '3509', 3); +INSERT INTO `dic_city` VALUES ('350924', '350924', '寿宁县', '3509', 3); +INSERT INTO `dic_city` VALUES ('350925', '350925', '周宁县', '3509', 3); +INSERT INTO `dic_city` VALUES ('350926', '350926', '柘荣县', '3509', 3); +INSERT INTO `dic_city` VALUES ('350981', '350981', '福安市', '3509', 3); +INSERT INTO `dic_city` VALUES ('350982', '350982', '福鼎市', '3509', 3); +INSERT INTO `dic_city` VALUES ('36', '36', '江西省', NULL, 1); +INSERT INTO `dic_city` VALUES ('3601', '3601', '南昌市', '36', 2); +INSERT INTO `dic_city` VALUES ('360102', '360102', '东湖区', '3601', 3); +INSERT INTO `dic_city` VALUES ('360103', '360103', '西湖区', '3601', 3); +INSERT INTO `dic_city` VALUES ('360104', '360104', '青云谱区', '3601', 3); +INSERT INTO `dic_city` VALUES ('360111', '360111', '青山湖区', '3601', 3); +INSERT INTO `dic_city` VALUES ('360112', '360112', '新建区', '3601', 3); +INSERT INTO `dic_city` VALUES ('360113', '360113', '红谷滩区', '3601', 3); +INSERT INTO `dic_city` VALUES ('360121', '360121', '南昌县', '3601', 3); +INSERT INTO `dic_city` VALUES ('360123', '360123', '安义县', '3601', 3); +INSERT INTO `dic_city` VALUES ('360124', '360124', '进贤县', '3601', 3); +INSERT INTO `dic_city` VALUES ('3602', '3602', '景德镇市', '36', 2); +INSERT INTO `dic_city` VALUES ('360202', '360202', '昌江区', '3602', 3); +INSERT INTO `dic_city` VALUES ('360203', '360203', '珠山区', '3602', 3); +INSERT INTO `dic_city` VALUES ('360222', '360222', '浮梁县', '3602', 3); +INSERT INTO `dic_city` VALUES ('360281', '360281', '乐平市', '3602', 3); +INSERT INTO `dic_city` VALUES ('3603', '3603', '萍乡市', '36', 2); +INSERT INTO `dic_city` VALUES ('360302', '360302', '安源区', '3603', 3); +INSERT INTO `dic_city` VALUES ('360313', '360313', '湘东区', '3603', 3); +INSERT INTO `dic_city` VALUES ('360321', '360321', '莲花县', '3603', 3); +INSERT INTO `dic_city` VALUES ('360322', '360322', '上栗县', '3603', 3); +INSERT INTO `dic_city` VALUES ('360323', '360323', '芦溪县', '3603', 3); +INSERT INTO `dic_city` VALUES ('3604', '3604', '九江市', '36', 2); +INSERT INTO `dic_city` VALUES ('360402', '360402', '濂溪区', '3604', 3); +INSERT INTO `dic_city` VALUES ('360403', '360403', '浔阳区', '3604', 3); +INSERT INTO `dic_city` VALUES ('360404', '360404', '柴桑区', '3604', 3); +INSERT INTO `dic_city` VALUES ('360423', '360423', '武宁县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360424', '360424', '修水县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360425', '360425', '永修县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360426', '360426', '德安县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360428', '360428', '都昌县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360429', '360429', '湖口县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360430', '360430', '彭泽县', '3604', 3); +INSERT INTO `dic_city` VALUES ('360481', '360481', '瑞昌市', '3604', 3); +INSERT INTO `dic_city` VALUES ('360482', '360482', '共青城市', '3604', 3); +INSERT INTO `dic_city` VALUES ('360483', '360483', '庐山市', '3604', 3); +INSERT INTO `dic_city` VALUES ('3605', '3605', '新余市', '36', 2); +INSERT INTO `dic_city` VALUES ('360502', '360502', '渝水区', '3605', 3); +INSERT INTO `dic_city` VALUES ('360521', '360521', '分宜县', '3605', 3); +INSERT INTO `dic_city` VALUES ('3606', '3606', '鹰潭市', '36', 2); +INSERT INTO `dic_city` VALUES ('360602', '360602', '月湖区', '3606', 3); +INSERT INTO `dic_city` VALUES ('360603', '360603', '余江区', '3606', 3); +INSERT INTO `dic_city` VALUES ('360681', '360681', '贵溪市', '3606', 3); +INSERT INTO `dic_city` VALUES ('3607', '3607', '赣州市', '36', 2); +INSERT INTO `dic_city` VALUES ('360702', '360702', '章贡区', '3607', 3); +INSERT INTO `dic_city` VALUES ('360703', '360703', '南康区', '3607', 3); +INSERT INTO `dic_city` VALUES ('360704', '360704', '赣县区', '3607', 3); +INSERT INTO `dic_city` VALUES ('360722', '360722', '信丰县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360723', '360723', '大余县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360724', '360724', '上犹县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360725', '360725', '崇义县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360726', '360726', '安远县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360728', '360728', '定南县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360729', '360729', '全南县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360730', '360730', '宁都县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360731', '360731', '于都县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360732', '360732', '兴国县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360733', '360733', '会昌县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360734', '360734', '寻乌县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360735', '360735', '石城县', '3607', 3); +INSERT INTO `dic_city` VALUES ('360781', '360781', '瑞金市', '3607', 3); +INSERT INTO `dic_city` VALUES ('360783', '360783', '龙南市', '3607', 3); +INSERT INTO `dic_city` VALUES ('3608', '3608', '吉安市', '36', 2); +INSERT INTO `dic_city` VALUES ('360802', '360802', '吉州区', '3608', 3); +INSERT INTO `dic_city` VALUES ('360803', '360803', '青原区', '3608', 3); +INSERT INTO `dic_city` VALUES ('360821', '360821', '吉安县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360822', '360822', '吉水县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360823', '360823', '峡江县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360824', '360824', '新干县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360825', '360825', '永丰县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360826', '360826', '泰和县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360827', '360827', '遂川县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360828', '360828', '万安县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360829', '360829', '安福县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360830', '360830', '永新县', '3608', 3); +INSERT INTO `dic_city` VALUES ('360881', '360881', '井冈山市', '3608', 3); +INSERT INTO `dic_city` VALUES ('3609', '3609', '宜春市', '36', 2); +INSERT INTO `dic_city` VALUES ('360902', '360902', '袁州区', '3609', 3); +INSERT INTO `dic_city` VALUES ('360921', '360921', '奉新县', '3609', 3); +INSERT INTO `dic_city` VALUES ('360922', '360922', '万载县', '3609', 3); +INSERT INTO `dic_city` VALUES ('360923', '360923', '上高县', '3609', 3); +INSERT INTO `dic_city` VALUES ('360924', '360924', '宜丰县', '3609', 3); +INSERT INTO `dic_city` VALUES ('360925', '360925', '靖安县', '3609', 3); +INSERT INTO `dic_city` VALUES ('360926', '360926', '铜鼓县', '3609', 3); +INSERT INTO `dic_city` VALUES ('360981', '360981', '丰城市', '3609', 3); +INSERT INTO `dic_city` VALUES ('360982', '360982', '樟树市', '3609', 3); +INSERT INTO `dic_city` VALUES ('360983', '360983', '高安市', '3609', 3); +INSERT INTO `dic_city` VALUES ('3610', '3610', '抚州市', '36', 2); +INSERT INTO `dic_city` VALUES ('361002', '361002', '临川区', '3610', 3); +INSERT INTO `dic_city` VALUES ('361003', '361003', '东乡区', '3610', 3); +INSERT INTO `dic_city` VALUES ('361021', '361021', '南城县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361022', '361022', '黎川县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361023', '361023', '南丰县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361024', '361024', '崇仁县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361025', '361025', '乐安县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361026', '361026', '宜黄县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361027', '361027', '金溪县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361028', '361028', '资溪县', '3610', 3); +INSERT INTO `dic_city` VALUES ('361030', '361030', '广昌县', '3610', 3); +INSERT INTO `dic_city` VALUES ('3611', '3611', '上饶市', '36', 2); +INSERT INTO `dic_city` VALUES ('361102', '361102', '信州区', '3611', 3); +INSERT INTO `dic_city` VALUES ('361103', '361103', '广丰区', '3611', 3); +INSERT INTO `dic_city` VALUES ('361104', '361104', '广信区', '3611', 3); +INSERT INTO `dic_city` VALUES ('361123', '361123', '玉山县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361124', '361124', '铅山县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361125', '361125', '横峰县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361126', '361126', '弋阳县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361127', '361127', '余干县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361128', '361128', '鄱阳县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361129', '361129', '万年县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361130', '361130', '婺源县', '3611', 3); +INSERT INTO `dic_city` VALUES ('361181', '361181', '德兴市', '3611', 3); +INSERT INTO `dic_city` VALUES ('37', '37', '山东省', NULL, 1); +INSERT INTO `dic_city` VALUES ('3701', '3701', '济南市', '37', 2); +INSERT INTO `dic_city` VALUES ('370102', '370102', '历下区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370103', '370103', '市中区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370104', '370104', '槐荫区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370105', '370105', '天桥区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370112', '370112', '历城区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370113', '370113', '长清区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370114', '370114', '章丘区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370115', '370115', '济阳区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370116', '370116', '莱芜区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370117', '370117', '钢城区', '3701', 3); +INSERT INTO `dic_city` VALUES ('370124', '370124', '平阴县', '3701', 3); +INSERT INTO `dic_city` VALUES ('370126', '370126', '商河县', '3701', 3); +INSERT INTO `dic_city` VALUES ('370171', '370171', '济南高新技术产业开发区', '3701', 3); +INSERT INTO `dic_city` VALUES ('3702', '3702', '青岛市', '37', 2); +INSERT INTO `dic_city` VALUES ('370202', '370202', '市南区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370203', '370203', '市北区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370211', '370211', '黄岛区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370212', '370212', '崂山区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370213', '370213', '李沧区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370214', '370214', '城阳区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370215', '370215', '即墨区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370271', '370271', '青岛高新技术产业开发区', '3702', 3); +INSERT INTO `dic_city` VALUES ('370281', '370281', '胶州市', '3702', 3); +INSERT INTO `dic_city` VALUES ('370283', '370283', '平度市', '3702', 3); +INSERT INTO `dic_city` VALUES ('370285', '370285', '莱西市', '3702', 3); +INSERT INTO `dic_city` VALUES ('3703', '3703', '淄博市', '37', 2); +INSERT INTO `dic_city` VALUES ('370302', '370302', '淄川区', '3703', 3); +INSERT INTO `dic_city` VALUES ('370303', '370303', '张店区', '3703', 3); +INSERT INTO `dic_city` VALUES ('370304', '370304', '博山区', '3703', 3); +INSERT INTO `dic_city` VALUES ('370305', '370305', '临淄区', '3703', 3); +INSERT INTO `dic_city` VALUES ('370306', '370306', '周村区', '3703', 3); +INSERT INTO `dic_city` VALUES ('370321', '370321', '桓台县', '3703', 3); +INSERT INTO `dic_city` VALUES ('370322', '370322', '高青县', '3703', 3); +INSERT INTO `dic_city` VALUES ('370323', '370323', '沂源县', '3703', 3); +INSERT INTO `dic_city` VALUES ('3704', '3704', '枣庄市', '37', 2); +INSERT INTO `dic_city` VALUES ('370402', '370402', '市中区', '3704', 3); +INSERT INTO `dic_city` VALUES ('370403', '370403', '薛城区', '3704', 3); +INSERT INTO `dic_city` VALUES ('370404', '370404', '峄城区', '3704', 3); +INSERT INTO `dic_city` VALUES ('370405', '370405', '台儿庄区', '3704', 3); +INSERT INTO `dic_city` VALUES ('370406', '370406', '山亭区', '3704', 3); +INSERT INTO `dic_city` VALUES ('370481', '370481', '滕州市', '3704', 3); +INSERT INTO `dic_city` VALUES ('3705', '3705', '东营市', '37', 2); +INSERT INTO `dic_city` VALUES ('370502', '370502', '东营区', '3705', 3); +INSERT INTO `dic_city` VALUES ('370503', '370503', '河口区', '3705', 3); +INSERT INTO `dic_city` VALUES ('370505', '370505', '垦利区', '3705', 3); +INSERT INTO `dic_city` VALUES ('370522', '370522', '利津县', '3705', 3); +INSERT INTO `dic_city` VALUES ('370523', '370523', '广饶县', '3705', 3); +INSERT INTO `dic_city` VALUES ('370571', '370571', '东营经济技术开发区', '3705', 3); +INSERT INTO `dic_city` VALUES ('370572', '370572', '东营港经济开发区', '3705', 3); +INSERT INTO `dic_city` VALUES ('3706', '3706', '烟台市', '37', 2); +INSERT INTO `dic_city` VALUES ('370602', '370602', '芝罘区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370611', '370611', '福山区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370612', '370612', '牟平区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370613', '370613', '莱山区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370614', '370614', '蓬莱区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370671', '370671', '烟台高新技术产业开发区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370672', '370672', '烟台经济技术开发区', '3706', 3); +INSERT INTO `dic_city` VALUES ('370681', '370681', '龙口市', '3706', 3); +INSERT INTO `dic_city` VALUES ('370682', '370682', '莱阳市', '3706', 3); +INSERT INTO `dic_city` VALUES ('370683', '370683', '莱州市', '3706', 3); +INSERT INTO `dic_city` VALUES ('370685', '370685', '招远市', '3706', 3); +INSERT INTO `dic_city` VALUES ('370686', '370686', '栖霞市', '3706', 3); +INSERT INTO `dic_city` VALUES ('370687', '370687', '海阳市', '3706', 3); +INSERT INTO `dic_city` VALUES ('3707', '3707', '潍坊市', '37', 2); +INSERT INTO `dic_city` VALUES ('370702', '370702', '潍城区', '3707', 3); +INSERT INTO `dic_city` VALUES ('370703', '370703', '寒亭区', '3707', 3); +INSERT INTO `dic_city` VALUES ('370704', '370704', '坊子区', '3707', 3); +INSERT INTO `dic_city` VALUES ('370705', '370705', '奎文区', '3707', 3); +INSERT INTO `dic_city` VALUES ('370724', '370724', '临朐县', '3707', 3); +INSERT INTO `dic_city` VALUES ('370725', '370725', '昌乐县', '3707', 3); +INSERT INTO `dic_city` VALUES ('370772', '370772', '潍坊滨海经济技术开发区', '3707', 3); +INSERT INTO `dic_city` VALUES ('370781', '370781', '青州市', '3707', 3); +INSERT INTO `dic_city` VALUES ('370782', '370782', '诸城市', '3707', 3); +INSERT INTO `dic_city` VALUES ('370783', '370783', '寿光市', '3707', 3); +INSERT INTO `dic_city` VALUES ('370784', '370784', '安丘市', '3707', 3); +INSERT INTO `dic_city` VALUES ('370785', '370785', '高密市', '3707', 3); +INSERT INTO `dic_city` VALUES ('370786', '370786', '昌邑市', '3707', 3); +INSERT INTO `dic_city` VALUES ('3708', '3708', '济宁市', '37', 2); +INSERT INTO `dic_city` VALUES ('370811', '370811', '任城区', '3708', 3); +INSERT INTO `dic_city` VALUES ('370812', '370812', '兖州区', '3708', 3); +INSERT INTO `dic_city` VALUES ('370826', '370826', '微山县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370827', '370827', '鱼台县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370828', '370828', '金乡县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370829', '370829', '嘉祥县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370830', '370830', '汶上县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370831', '370831', '泗水县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370832', '370832', '梁山县', '3708', 3); +INSERT INTO `dic_city` VALUES ('370871', '370871', '济宁高新技术产业开发区', '3708', 3); +INSERT INTO `dic_city` VALUES ('370881', '370881', '曲阜市', '3708', 3); +INSERT INTO `dic_city` VALUES ('370883', '370883', '邹城市', '3708', 3); +INSERT INTO `dic_city` VALUES ('3709', '3709', '泰安市', '37', 2); +INSERT INTO `dic_city` VALUES ('370902', '370902', '泰山区', '3709', 3); +INSERT INTO `dic_city` VALUES ('370911', '370911', '岱岳区', '3709', 3); +INSERT INTO `dic_city` VALUES ('370921', '370921', '宁阳县', '3709', 3); +INSERT INTO `dic_city` VALUES ('370923', '370923', '东平县', '3709', 3); +INSERT INTO `dic_city` VALUES ('370982', '370982', '新泰市', '3709', 3); +INSERT INTO `dic_city` VALUES ('370983', '370983', '肥城市', '3709', 3); +INSERT INTO `dic_city` VALUES ('3710', '3710', '威海市', '37', 2); +INSERT INTO `dic_city` VALUES ('371002', '371002', '环翠区', '3710', 3); +INSERT INTO `dic_city` VALUES ('371003', '371003', '文登区', '3710', 3); +INSERT INTO `dic_city` VALUES ('371071', '371071', '威海火炬高技术产业开发区', '3710', 3); +INSERT INTO `dic_city` VALUES ('371072', '371072', '威海经济技术开发区', '3710', 3); +INSERT INTO `dic_city` VALUES ('371073', '371073', '威海临港经济技术开发区', '3710', 3); +INSERT INTO `dic_city` VALUES ('371082', '371082', '荣成市', '3710', 3); +INSERT INTO `dic_city` VALUES ('371083', '371083', '乳山市', '3710', 3); +INSERT INTO `dic_city` VALUES ('3711', '3711', '日照市', '37', 2); +INSERT INTO `dic_city` VALUES ('371102', '371102', '东港区', '3711', 3); +INSERT INTO `dic_city` VALUES ('371103', '371103', '岚山区', '3711', 3); +INSERT INTO `dic_city` VALUES ('371121', '371121', '五莲县', '3711', 3); +INSERT INTO `dic_city` VALUES ('371122', '371122', '莒县', '3711', 3); +INSERT INTO `dic_city` VALUES ('371171', '371171', '日照经济技术开发区', '3711', 3); +INSERT INTO `dic_city` VALUES ('3713', '3713', '临沂市', '37', 2); +INSERT INTO `dic_city` VALUES ('371302', '371302', '兰山区', '3713', 3); +INSERT INTO `dic_city` VALUES ('371311', '371311', '罗庄区', '3713', 3); +INSERT INTO `dic_city` VALUES ('371312', '371312', '河东区', '3713', 3); +INSERT INTO `dic_city` VALUES ('371321', '371321', '沂南县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371322', '371322', '郯城县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371323', '371323', '沂水县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371324', '371324', '兰陵县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371325', '371325', '费县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371326', '371326', '平邑县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371327', '371327', '莒南县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371328', '371328', '蒙阴县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371329', '371329', '临沭县', '3713', 3); +INSERT INTO `dic_city` VALUES ('371371', '371371', '临沂高新技术产业开发区', '3713', 3); +INSERT INTO `dic_city` VALUES ('3714', '3714', '德州市', '37', 2); +INSERT INTO `dic_city` VALUES ('371402', '371402', '德城区', '3714', 3); +INSERT INTO `dic_city` VALUES ('371403', '371403', '陵城区', '3714', 3); +INSERT INTO `dic_city` VALUES ('371422', '371422', '宁津县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371423', '371423', '庆云县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371424', '371424', '临邑县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371425', '371425', '齐河县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371426', '371426', '平原县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371427', '371427', '夏津县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371428', '371428', '武城县', '3714', 3); +INSERT INTO `dic_city` VALUES ('371471', '371471', '德州经济技术开发区', '3714', 3); +INSERT INTO `dic_city` VALUES ('371472', '371472', '德州运河经济开发区', '3714', 3); +INSERT INTO `dic_city` VALUES ('371481', '371481', '乐陵市', '3714', 3); +INSERT INTO `dic_city` VALUES ('371482', '371482', '禹城市', '3714', 3); +INSERT INTO `dic_city` VALUES ('3715', '3715', '聊城市', '37', 2); +INSERT INTO `dic_city` VALUES ('371502', '371502', '东昌府区', '3715', 3); +INSERT INTO `dic_city` VALUES ('371503', '371503', '茌平区', '3715', 3); +INSERT INTO `dic_city` VALUES ('371521', '371521', '阳谷县', '3715', 3); +INSERT INTO `dic_city` VALUES ('371522', '371522', '莘县', '3715', 3); +INSERT INTO `dic_city` VALUES ('371524', '371524', '东阿县', '3715', 3); +INSERT INTO `dic_city` VALUES ('371525', '371525', '冠县', '3715', 3); +INSERT INTO `dic_city` VALUES ('371526', '371526', '高唐县', '3715', 3); +INSERT INTO `dic_city` VALUES ('371581', '371581', '临清市', '3715', 3); +INSERT INTO `dic_city` VALUES ('3716', '3716', '滨州市', '37', 2); +INSERT INTO `dic_city` VALUES ('371602', '371602', '滨城区', '3716', 3); +INSERT INTO `dic_city` VALUES ('371603', '371603', '沾化区', '3716', 3); +INSERT INTO `dic_city` VALUES ('371621', '371621', '惠民县', '3716', 3); +INSERT INTO `dic_city` VALUES ('371622', '371622', '阳信县', '3716', 3); +INSERT INTO `dic_city` VALUES ('371623', '371623', '无棣县', '3716', 3); +INSERT INTO `dic_city` VALUES ('371625', '371625', '博兴县', '3716', 3); +INSERT INTO `dic_city` VALUES ('371681', '371681', '邹平市', '3716', 3); +INSERT INTO `dic_city` VALUES ('3717', '3717', '菏泽市', '37', 2); +INSERT INTO `dic_city` VALUES ('371702', '371702', '牡丹区', '3717', 3); +INSERT INTO `dic_city` VALUES ('371703', '371703', '定陶区', '3717', 3); +INSERT INTO `dic_city` VALUES ('371721', '371721', '曹县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371722', '371722', '单县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371723', '371723', '成武县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371724', '371724', '巨野县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371725', '371725', '郓城县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371726', '371726', '鄄城县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371728', '371728', '东明县', '3717', 3); +INSERT INTO `dic_city` VALUES ('371771', '371771', '菏泽经济技术开发区', '3717', 3); +INSERT INTO `dic_city` VALUES ('371772', '371772', '菏泽高新技术开发区', '3717', 3); +INSERT INTO `dic_city` VALUES ('41', '41', '河南省', NULL, 1); +INSERT INTO `dic_city` VALUES ('4101', '4101', '郑州市', '41', 2); +INSERT INTO `dic_city` VALUES ('410102', '410102', '中原区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410103', '410103', '二七区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410104', '410104', '管城回族区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410105', '410105', '金水区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410106', '410106', '上街区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410108', '410108', '惠济区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410122', '410122', '中牟县', '4101', 3); +INSERT INTO `dic_city` VALUES ('410171', '410171', '郑州经济技术开发区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410172', '410172', '郑州高新技术产业开发区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410173', '410173', '郑州航空港经济综合实验区', '4101', 3); +INSERT INTO `dic_city` VALUES ('410181', '410181', '巩义市', '4101', 3); +INSERT INTO `dic_city` VALUES ('410182', '410182', '荥阳市', '4101', 3); +INSERT INTO `dic_city` VALUES ('410183', '410183', '新密市', '4101', 3); +INSERT INTO `dic_city` VALUES ('410184', '410184', '新郑市', '4101', 3); +INSERT INTO `dic_city` VALUES ('410185', '410185', '登封市', '4101', 3); +INSERT INTO `dic_city` VALUES ('4102', '4102', '开封市', '41', 2); +INSERT INTO `dic_city` VALUES ('410202', '410202', '龙亭区', '4102', 3); +INSERT INTO `dic_city` VALUES ('410203', '410203', '顺河回族区', '4102', 3); +INSERT INTO `dic_city` VALUES ('410204', '410204', '鼓楼区', '4102', 3); +INSERT INTO `dic_city` VALUES ('410205', '410205', '禹王台区', '4102', 3); +INSERT INTO `dic_city` VALUES ('410212', '410212', '祥符区', '4102', 3); +INSERT INTO `dic_city` VALUES ('410221', '410221', '杞县', '4102', 3); +INSERT INTO `dic_city` VALUES ('410222', '410222', '通许县', '4102', 3); +INSERT INTO `dic_city` VALUES ('410223', '410223', '尉氏县', '4102', 3); +INSERT INTO `dic_city` VALUES ('410225', '410225', '兰考县', '4102', 3); +INSERT INTO `dic_city` VALUES ('4103', '4103', '洛阳市', '41', 2); +INSERT INTO `dic_city` VALUES ('410302', '410302', '老城区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410303', '410303', '西工区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410304', '410304', '瀍河回族区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410305', '410305', '涧西区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410306', '410306', '吉利区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410311', '410311', '洛龙区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410322', '410322', '孟津县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410323', '410323', '新安县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410324', '410324', '栾川县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410325', '410325', '嵩县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410326', '410326', '汝阳县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410327', '410327', '宜阳县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410328', '410328', '洛宁县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410329', '410329', '伊川县', '4103', 3); +INSERT INTO `dic_city` VALUES ('410371', '410371', '洛阳高新技术产业开发区', '4103', 3); +INSERT INTO `dic_city` VALUES ('410381', '410381', '偃师市', '4103', 3); +INSERT INTO `dic_city` VALUES ('4104', '4104', '平顶山市', '41', 2); +INSERT INTO `dic_city` VALUES ('410402', '410402', '新华区', '4104', 3); +INSERT INTO `dic_city` VALUES ('410403', '410403', '卫东区', '4104', 3); +INSERT INTO `dic_city` VALUES ('410404', '410404', '石龙区', '4104', 3); +INSERT INTO `dic_city` VALUES ('410411', '410411', '湛河区', '4104', 3); +INSERT INTO `dic_city` VALUES ('410421', '410421', '宝丰县', '4104', 3); +INSERT INTO `dic_city` VALUES ('410422', '410422', '叶县', '4104', 3); +INSERT INTO `dic_city` VALUES ('410423', '410423', '鲁山县', '4104', 3); +INSERT INTO `dic_city` VALUES ('410425', '410425', '郏县', '4104', 3); +INSERT INTO `dic_city` VALUES ('410471', '410471', '平顶山高新技术产业开发区', '4104', 3); +INSERT INTO `dic_city` VALUES ('410472', '410472', '平顶山市城乡一体化示范区', '4104', 3); +INSERT INTO `dic_city` VALUES ('410481', '410481', '舞钢市', '4104', 3); +INSERT INTO `dic_city` VALUES ('410482', '410482', '汝州市', '4104', 3); +INSERT INTO `dic_city` VALUES ('4105', '4105', '安阳市', '41', 2); +INSERT INTO `dic_city` VALUES ('410502', '410502', '文峰区', '4105', 3); +INSERT INTO `dic_city` VALUES ('410503', '410503', '北关区', '4105', 3); +INSERT INTO `dic_city` VALUES ('410505', '410505', '殷都区', '4105', 3); +INSERT INTO `dic_city` VALUES ('410506', '410506', '龙安区', '4105', 3); +INSERT INTO `dic_city` VALUES ('410522', '410522', '安阳县', '4105', 3); +INSERT INTO `dic_city` VALUES ('410523', '410523', '汤阴县', '4105', 3); +INSERT INTO `dic_city` VALUES ('410526', '410526', '滑县', '4105', 3); +INSERT INTO `dic_city` VALUES ('410527', '410527', '内黄县', '4105', 3); +INSERT INTO `dic_city` VALUES ('410571', '410571', '安阳高新技术产业开发区', '4105', 3); +INSERT INTO `dic_city` VALUES ('410581', '410581', '林州市', '4105', 3); +INSERT INTO `dic_city` VALUES ('4106', '4106', '鹤壁市', '41', 2); +INSERT INTO `dic_city` VALUES ('410602', '410602', '鹤山区', '4106', 3); +INSERT INTO `dic_city` VALUES ('410603', '410603', '山城区', '4106', 3); +INSERT INTO `dic_city` VALUES ('410611', '410611', '淇滨区', '4106', 3); +INSERT INTO `dic_city` VALUES ('410621', '410621', '浚县', '4106', 3); +INSERT INTO `dic_city` VALUES ('410622', '410622', '淇县', '4106', 3); +INSERT INTO `dic_city` VALUES ('410671', '410671', '鹤壁经济技术开发区', '4106', 3); +INSERT INTO `dic_city` VALUES ('4107', '4107', '新乡市', '41', 2); +INSERT INTO `dic_city` VALUES ('410702', '410702', '红旗区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410703', '410703', '卫滨区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410704', '410704', '凤泉区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410711', '410711', '牧野区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410721', '410721', '新乡县', '4107', 3); +INSERT INTO `dic_city` VALUES ('410724', '410724', '获嘉县', '4107', 3); +INSERT INTO `dic_city` VALUES ('410725', '410725', '原阳县', '4107', 3); +INSERT INTO `dic_city` VALUES ('410726', '410726', '延津县', '4107', 3); +INSERT INTO `dic_city` VALUES ('410727', '410727', '封丘县', '4107', 3); +INSERT INTO `dic_city` VALUES ('410771', '410771', '新乡高新技术产业开发区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410772', '410772', '新乡经济技术开发区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410773', '410773', '新乡市平原城乡一体化示范区', '4107', 3); +INSERT INTO `dic_city` VALUES ('410781', '410781', '卫辉市', '4107', 3); +INSERT INTO `dic_city` VALUES ('410782', '410782', '辉县市', '4107', 3); +INSERT INTO `dic_city` VALUES ('410783', '410783', '长垣市', '4107', 3); +INSERT INTO `dic_city` VALUES ('4108', '4108', '焦作市', '41', 2); +INSERT INTO `dic_city` VALUES ('410802', '410802', '解放区', '4108', 3); +INSERT INTO `dic_city` VALUES ('410803', '410803', '中站区', '4108', 3); +INSERT INTO `dic_city` VALUES ('410804', '410804', '马村区', '4108', 3); +INSERT INTO `dic_city` VALUES ('410811', '410811', '山阳区', '4108', 3); +INSERT INTO `dic_city` VALUES ('410821', '410821', '修武县', '4108', 3); +INSERT INTO `dic_city` VALUES ('410822', '410822', '博爱县', '4108', 3); +INSERT INTO `dic_city` VALUES ('410823', '410823', '武陟县', '4108', 3); +INSERT INTO `dic_city` VALUES ('410825', '410825', '温县', '4108', 3); +INSERT INTO `dic_city` VALUES ('410871', '410871', '焦作城乡一体化示范区', '4108', 3); +INSERT INTO `dic_city` VALUES ('410882', '410882', '沁阳市', '4108', 3); +INSERT INTO `dic_city` VALUES ('410883', '410883', '孟州市', '4108', 3); +INSERT INTO `dic_city` VALUES ('4109', '4109', '濮阳市', '41', 2); +INSERT INTO `dic_city` VALUES ('410902', '410902', '华龙区', '4109', 3); +INSERT INTO `dic_city` VALUES ('410922', '410922', '清丰县', '4109', 3); +INSERT INTO `dic_city` VALUES ('410923', '410923', '南乐县', '4109', 3); +INSERT INTO `dic_city` VALUES ('410926', '410926', '范县', '4109', 3); +INSERT INTO `dic_city` VALUES ('410927', '410927', '台前县', '4109', 3); +INSERT INTO `dic_city` VALUES ('410928', '410928', '濮阳县', '4109', 3); +INSERT INTO `dic_city` VALUES ('410971', '410971', '河南濮阳工业园区', '4109', 3); +INSERT INTO `dic_city` VALUES ('410972', '410972', '濮阳经济技术开发区', '4109', 3); +INSERT INTO `dic_city` VALUES ('4110', '4110', '许昌市', '41', 2); +INSERT INTO `dic_city` VALUES ('411002', '411002', '魏都区', '4110', 3); +INSERT INTO `dic_city` VALUES ('411003', '411003', '建安区', '4110', 3); +INSERT INTO `dic_city` VALUES ('411024', '411024', '鄢陵县', '4110', 3); +INSERT INTO `dic_city` VALUES ('411025', '411025', '襄城县', '4110', 3); +INSERT INTO `dic_city` VALUES ('411071', '411071', '许昌经济技术开发区', '4110', 3); +INSERT INTO `dic_city` VALUES ('411081', '411081', '禹州市', '4110', 3); +INSERT INTO `dic_city` VALUES ('411082', '411082', '长葛市', '4110', 3); +INSERT INTO `dic_city` VALUES ('4111', '4111', '漯河市', '41', 2); +INSERT INTO `dic_city` VALUES ('411102', '411102', '源汇区', '4111', 3); +INSERT INTO `dic_city` VALUES ('411103', '411103', '郾城区', '4111', 3); +INSERT INTO `dic_city` VALUES ('411104', '411104', '召陵区', '4111', 3); +INSERT INTO `dic_city` VALUES ('411121', '411121', '舞阳县', '4111', 3); +INSERT INTO `dic_city` VALUES ('411122', '411122', '临颍县', '4111', 3); +INSERT INTO `dic_city` VALUES ('411171', '411171', '漯河经济技术开发区', '4111', 3); +INSERT INTO `dic_city` VALUES ('4112', '4112', '三门峡市', '41', 2); +INSERT INTO `dic_city` VALUES ('411202', '411202', '湖滨区', '4112', 3); +INSERT INTO `dic_city` VALUES ('411203', '411203', '陕州区', '4112', 3); +INSERT INTO `dic_city` VALUES ('411221', '411221', '渑池县', '4112', 3); +INSERT INTO `dic_city` VALUES ('411224', '411224', '卢氏县', '4112', 3); +INSERT INTO `dic_city` VALUES ('411271', '411271', '河南三门峡经济开发区', '4112', 3); +INSERT INTO `dic_city` VALUES ('411281', '411281', '义马市', '4112', 3); +INSERT INTO `dic_city` VALUES ('411282', '411282', '灵宝市', '4112', 3); +INSERT INTO `dic_city` VALUES ('4113', '4113', '南阳市', '41', 2); +INSERT INTO `dic_city` VALUES ('411302', '411302', '宛城区', '4113', 3); +INSERT INTO `dic_city` VALUES ('411303', '411303', '卧龙区', '4113', 3); +INSERT INTO `dic_city` VALUES ('411321', '411321', '南召县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411322', '411322', '方城县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411323', '411323', '西峡县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411324', '411324', '镇平县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411325', '411325', '内乡县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411326', '411326', '淅川县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411327', '411327', '社旗县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411328', '411328', '唐河县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411329', '411329', '新野县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411330', '411330', '桐柏县', '4113', 3); +INSERT INTO `dic_city` VALUES ('411371', '411371', '南阳高新技术产业开发区', '4113', 3); +INSERT INTO `dic_city` VALUES ('411372', '411372', '南阳市城乡一体化示范区', '4113', 3); +INSERT INTO `dic_city` VALUES ('411381', '411381', '邓州市', '4113', 3); +INSERT INTO `dic_city` VALUES ('4114', '4114', '商丘市', '41', 2); +INSERT INTO `dic_city` VALUES ('411402', '411402', '梁园区', '4114', 3); +INSERT INTO `dic_city` VALUES ('411403', '411403', '睢阳区', '4114', 3); +INSERT INTO `dic_city` VALUES ('411421', '411421', '民权县', '4114', 3); +INSERT INTO `dic_city` VALUES ('411422', '411422', '睢县', '4114', 3); +INSERT INTO `dic_city` VALUES ('411423', '411423', '宁陵县', '4114', 3); +INSERT INTO `dic_city` VALUES ('411424', '411424', '柘城县', '4114', 3); +INSERT INTO `dic_city` VALUES ('411425', '411425', '虞城县', '4114', 3); +INSERT INTO `dic_city` VALUES ('411426', '411426', '夏邑县', '4114', 3); +INSERT INTO `dic_city` VALUES ('411471', '411471', '豫东综合物流产业聚集区', '4114', 3); +INSERT INTO `dic_city` VALUES ('411472', '411472', '河南商丘经济开发区', '4114', 3); +INSERT INTO `dic_city` VALUES ('411481', '411481', '永城市', '4114', 3); +INSERT INTO `dic_city` VALUES ('4115', '4115', '信阳市', '41', 2); +INSERT INTO `dic_city` VALUES ('411502', '411502', '浉河区', '4115', 3); +INSERT INTO `dic_city` VALUES ('411503', '411503', '平桥区', '4115', 3); +INSERT INTO `dic_city` VALUES ('411521', '411521', '罗山县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411522', '411522', '光山县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411523', '411523', '新县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411524', '411524', '商城县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411525', '411525', '固始县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411526', '411526', '潢川县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411527', '411527', '淮滨县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411528', '411528', '息县', '4115', 3); +INSERT INTO `dic_city` VALUES ('411571', '411571', '信阳高新技术产业开发区', '4115', 3); +INSERT INTO `dic_city` VALUES ('4116', '4116', '周口市', '41', 2); +INSERT INTO `dic_city` VALUES ('411602', '411602', '川汇区', '4116', 3); +INSERT INTO `dic_city` VALUES ('411603', '411603', '淮阳区', '4116', 3); +INSERT INTO `dic_city` VALUES ('411621', '411621', '扶沟县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411622', '411622', '西华县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411623', '411623', '商水县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411624', '411624', '沈丘县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411625', '411625', '郸城县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411627', '411627', '太康县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411628', '411628', '鹿邑县', '4116', 3); +INSERT INTO `dic_city` VALUES ('411671', '411671', '河南周口经济开发区', '4116', 3); +INSERT INTO `dic_city` VALUES ('411681', '411681', '项城市', '4116', 3); +INSERT INTO `dic_city` VALUES ('4117', '4117', '驻马店市', '41', 2); +INSERT INTO `dic_city` VALUES ('411702', '411702', '驿城区', '4117', 3); +INSERT INTO `dic_city` VALUES ('411721', '411721', '西平县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411722', '411722', '上蔡县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411723', '411723', '平舆县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411724', '411724', '正阳县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411725', '411725', '确山县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411726', '411726', '泌阳县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411727', '411727', '汝南县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411728', '411728', '遂平县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411729', '411729', '新蔡县', '4117', 3); +INSERT INTO `dic_city` VALUES ('411771', '411771', '河南驻马店经济开发区', '4117', 3); +INSERT INTO `dic_city` VALUES ('4190', '4190', '省直辖县级行政区划', '41', 2); +INSERT INTO `dic_city` VALUES ('419001', '419001', '济源市', '4190', 3); +INSERT INTO `dic_city` VALUES ('42', '42', '湖北省', NULL, 1); +INSERT INTO `dic_city` VALUES ('4201', '4201', '武汉市', '42', 2); +INSERT INTO `dic_city` VALUES ('420102', '420102', '江岸区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420103', '420103', '江汉区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420104', '420104', '硚口区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420105', '420105', '汉阳区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420106', '420106', '武昌区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420107', '420107', '青山区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420111', '420111', '洪山区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420112', '420112', '东西湖区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420113', '420113', '汉南区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420114', '420114', '蔡甸区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420115', '420115', '江夏区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420116', '420116', '黄陂区', '4201', 3); +INSERT INTO `dic_city` VALUES ('420117', '420117', '新洲区', '4201', 3); +INSERT INTO `dic_city` VALUES ('4202', '4202', '黄石市', '42', 2); +INSERT INTO `dic_city` VALUES ('420202', '420202', '黄石港区', '4202', 3); +INSERT INTO `dic_city` VALUES ('420203', '420203', '西塞山区', '4202', 3); +INSERT INTO `dic_city` VALUES ('420204', '420204', '下陆区', '4202', 3); +INSERT INTO `dic_city` VALUES ('420205', '420205', '铁山区', '4202', 3); +INSERT INTO `dic_city` VALUES ('420222', '420222', '阳新县', '4202', 3); +INSERT INTO `dic_city` VALUES ('420281', '420281', '大冶市', '4202', 3); +INSERT INTO `dic_city` VALUES ('4203', '4203', '十堰市', '42', 2); +INSERT INTO `dic_city` VALUES ('420302', '420302', '茅箭区', '4203', 3); +INSERT INTO `dic_city` VALUES ('420303', '420303', '张湾区', '4203', 3); +INSERT INTO `dic_city` VALUES ('420304', '420304', '郧阳区', '4203', 3); +INSERT INTO `dic_city` VALUES ('420322', '420322', '郧西县', '4203', 3); +INSERT INTO `dic_city` VALUES ('420323', '420323', '竹山县', '4203', 3); +INSERT INTO `dic_city` VALUES ('420324', '420324', '竹溪县', '4203', 3); +INSERT INTO `dic_city` VALUES ('420325', '420325', '房县', '4203', 3); +INSERT INTO `dic_city` VALUES ('420381', '420381', '丹江口市', '4203', 3); +INSERT INTO `dic_city` VALUES ('4205', '4205', '宜昌市', '42', 2); +INSERT INTO `dic_city` VALUES ('420502', '420502', '西陵区', '4205', 3); +INSERT INTO `dic_city` VALUES ('420503', '420503', '伍家岗区', '4205', 3); +INSERT INTO `dic_city` VALUES ('420504', '420504', '点军区', '4205', 3); +INSERT INTO `dic_city` VALUES ('420505', '420505', '猇亭区', '4205', 3); +INSERT INTO `dic_city` VALUES ('420506', '420506', '夷陵区', '4205', 3); +INSERT INTO `dic_city` VALUES ('420525', '420525', '远安县', '4205', 3); +INSERT INTO `dic_city` VALUES ('420526', '420526', '兴山县', '4205', 3); +INSERT INTO `dic_city` VALUES ('420527', '420527', '秭归县', '4205', 3); +INSERT INTO `dic_city` VALUES ('420528', '420528', '长阳土家族自治县', '4205', 3); +INSERT INTO `dic_city` VALUES ('420529', '420529', '五峰土家族自治县', '4205', 3); +INSERT INTO `dic_city` VALUES ('420581', '420581', '宜都市', '4205', 3); +INSERT INTO `dic_city` VALUES ('420582', '420582', '当阳市', '4205', 3); +INSERT INTO `dic_city` VALUES ('420583', '420583', '枝江市', '4205', 3); +INSERT INTO `dic_city` VALUES ('4206', '4206', '襄阳市', '42', 2); +INSERT INTO `dic_city` VALUES ('420602', '420602', '襄城区', '4206', 3); +INSERT INTO `dic_city` VALUES ('420606', '420606', '樊城区', '4206', 3); +INSERT INTO `dic_city` VALUES ('420607', '420607', '襄州区', '4206', 3); +INSERT INTO `dic_city` VALUES ('420624', '420624', '南漳县', '4206', 3); +INSERT INTO `dic_city` VALUES ('420625', '420625', '谷城县', '4206', 3); +INSERT INTO `dic_city` VALUES ('420626', '420626', '保康县', '4206', 3); +INSERT INTO `dic_city` VALUES ('420682', '420682', '老河口市', '4206', 3); +INSERT INTO `dic_city` VALUES ('420683', '420683', '枣阳市', '4206', 3); +INSERT INTO `dic_city` VALUES ('420684', '420684', '宜城市', '4206', 3); +INSERT INTO `dic_city` VALUES ('4207', '4207', '鄂州市', '42', 2); +INSERT INTO `dic_city` VALUES ('420702', '420702', '梁子湖区', '4207', 3); +INSERT INTO `dic_city` VALUES ('420703', '420703', '华容区', '4207', 3); +INSERT INTO `dic_city` VALUES ('420704', '420704', '鄂城区', '4207', 3); +INSERT INTO `dic_city` VALUES ('4208', '4208', '荆门市', '42', 2); +INSERT INTO `dic_city` VALUES ('420802', '420802', '东宝区', '4208', 3); +INSERT INTO `dic_city` VALUES ('420804', '420804', '掇刀区', '4208', 3); +INSERT INTO `dic_city` VALUES ('420822', '420822', '沙洋县', '4208', 3); +INSERT INTO `dic_city` VALUES ('420881', '420881', '钟祥市', '4208', 3); +INSERT INTO `dic_city` VALUES ('420882', '420882', '京山市', '4208', 3); +INSERT INTO `dic_city` VALUES ('4209', '4209', '孝感市', '42', 2); +INSERT INTO `dic_city` VALUES ('420902', '420902', '孝南区', '4209', 3); +INSERT INTO `dic_city` VALUES ('420921', '420921', '孝昌县', '4209', 3); +INSERT INTO `dic_city` VALUES ('420922', '420922', '大悟县', '4209', 3); +INSERT INTO `dic_city` VALUES ('420923', '420923', '云梦县', '4209', 3); +INSERT INTO `dic_city` VALUES ('420981', '420981', '应城市', '4209', 3); +INSERT INTO `dic_city` VALUES ('420982', '420982', '安陆市', '4209', 3); +INSERT INTO `dic_city` VALUES ('420984', '420984', '汉川市', '4209', 3); +INSERT INTO `dic_city` VALUES ('4210', '4210', '荆州市', '42', 2); +INSERT INTO `dic_city` VALUES ('421002', '421002', '沙市区', '4210', 3); +INSERT INTO `dic_city` VALUES ('421003', '421003', '荆州区', '4210', 3); +INSERT INTO `dic_city` VALUES ('421022', '421022', '公安县', '4210', 3); +INSERT INTO `dic_city` VALUES ('421023', '421023', '监利县', '4210', 3); +INSERT INTO `dic_city` VALUES ('421024', '421024', '江陵县', '4210', 3); +INSERT INTO `dic_city` VALUES ('421071', '421071', '荆州经济技术开发区', '4210', 3); +INSERT INTO `dic_city` VALUES ('421081', '421081', '石首市', '4210', 3); +INSERT INTO `dic_city` VALUES ('421083', '421083', '洪湖市', '4210', 3); +INSERT INTO `dic_city` VALUES ('421087', '421087', '松滋市', '4210', 3); +INSERT INTO `dic_city` VALUES ('4211', '4211', '黄冈市', '42', 2); +INSERT INTO `dic_city` VALUES ('421102', '421102', '黄州区', '4211', 3); +INSERT INTO `dic_city` VALUES ('421121', '421121', '团风县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421122', '421122', '红安县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421123', '421123', '罗田县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421124', '421124', '英山县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421125', '421125', '浠水县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421126', '421126', '蕲春县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421127', '421127', '黄梅县', '4211', 3); +INSERT INTO `dic_city` VALUES ('421171', '421171', '龙感湖管理区', '4211', 3); +INSERT INTO `dic_city` VALUES ('421181', '421181', '麻城市', '4211', 3); +INSERT INTO `dic_city` VALUES ('421182', '421182', '武穴市', '4211', 3); +INSERT INTO `dic_city` VALUES ('4212', '4212', '咸宁市', '42', 2); +INSERT INTO `dic_city` VALUES ('421202', '421202', '咸安区', '4212', 3); +INSERT INTO `dic_city` VALUES ('421221', '421221', '嘉鱼县', '4212', 3); +INSERT INTO `dic_city` VALUES ('421222', '421222', '通城县', '4212', 3); +INSERT INTO `dic_city` VALUES ('421223', '421223', '崇阳县', '4212', 3); +INSERT INTO `dic_city` VALUES ('421224', '421224', '通山县', '4212', 3); +INSERT INTO `dic_city` VALUES ('421281', '421281', '赤壁市', '4212', 3); +INSERT INTO `dic_city` VALUES ('4213', '4213', '随州市', '42', 2); +INSERT INTO `dic_city` VALUES ('421303', '421303', '曾都区', '4213', 3); +INSERT INTO `dic_city` VALUES ('421321', '421321', '随县', '4213', 3); +INSERT INTO `dic_city` VALUES ('421381', '421381', '广水市', '4213', 3); +INSERT INTO `dic_city` VALUES ('4228', '4228', '恩施土家族苗族自治州', '42', 2); +INSERT INTO `dic_city` VALUES ('422801', '422801', '恩施市', '4228', 3); +INSERT INTO `dic_city` VALUES ('422802', '422802', '利川市', '4228', 3); +INSERT INTO `dic_city` VALUES ('422822', '422822', '建始县', '4228', 3); +INSERT INTO `dic_city` VALUES ('422823', '422823', '巴东县', '4228', 3); +INSERT INTO `dic_city` VALUES ('422825', '422825', '宣恩县', '4228', 3); +INSERT INTO `dic_city` VALUES ('422826', '422826', '咸丰县', '4228', 3); +INSERT INTO `dic_city` VALUES ('422827', '422827', '来凤县', '4228', 3); +INSERT INTO `dic_city` VALUES ('422828', '422828', '鹤峰县', '4228', 3); +INSERT INTO `dic_city` VALUES ('4290', '4290', '省直辖县级行政区划', '42', 2); +INSERT INTO `dic_city` VALUES ('429004', '429004', '仙桃市', '4290', 3); +INSERT INTO `dic_city` VALUES ('429005', '429005', '潜江市', '4290', 3); +INSERT INTO `dic_city` VALUES ('429006', '429006', '天门市', '4290', 3); +INSERT INTO `dic_city` VALUES ('429021', '429021', '神农架林区', '4290', 3); +INSERT INTO `dic_city` VALUES ('43', '43', '湖南省', NULL, 1); +INSERT INTO `dic_city` VALUES ('4301', '4301', '长沙市', '43', 2); +INSERT INTO `dic_city` VALUES ('430102', '430102', '芙蓉区', '4301', 3); +INSERT INTO `dic_city` VALUES ('430103', '430103', '天心区', '4301', 3); +INSERT INTO `dic_city` VALUES ('430104', '430104', '岳麓区', '4301', 3); +INSERT INTO `dic_city` VALUES ('430105', '430105', '开福区', '4301', 3); +INSERT INTO `dic_city` VALUES ('430111', '430111', '雨花区', '4301', 3); +INSERT INTO `dic_city` VALUES ('430112', '430112', '望城区', '4301', 3); +INSERT INTO `dic_city` VALUES ('430121', '430121', '长沙县', '4301', 3); +INSERT INTO `dic_city` VALUES ('430181', '430181', '浏阳市', '4301', 3); +INSERT INTO `dic_city` VALUES ('430182', '430182', '宁乡市', '4301', 3); +INSERT INTO `dic_city` VALUES ('4302', '4302', '株洲市', '43', 2); +INSERT INTO `dic_city` VALUES ('430202', '430202', '荷塘区', '4302', 3); +INSERT INTO `dic_city` VALUES ('430203', '430203', '芦淞区', '4302', 3); +INSERT INTO `dic_city` VALUES ('430204', '430204', '石峰区', '4302', 3); +INSERT INTO `dic_city` VALUES ('430211', '430211', '天元区', '4302', 3); +INSERT INTO `dic_city` VALUES ('430212', '430212', '渌口区', '4302', 3); +INSERT INTO `dic_city` VALUES ('430223', '430223', '攸县', '4302', 3); +INSERT INTO `dic_city` VALUES ('430224', '430224', '茶陵县', '4302', 3); +INSERT INTO `dic_city` VALUES ('430225', '430225', '炎陵县', '4302', 3); +INSERT INTO `dic_city` VALUES ('430271', '430271', '云龙示范区', '4302', 3); +INSERT INTO `dic_city` VALUES ('430281', '430281', '醴陵市', '4302', 3); +INSERT INTO `dic_city` VALUES ('4303', '4303', '湘潭市', '43', 2); +INSERT INTO `dic_city` VALUES ('430302', '430302', '雨湖区', '4303', 3); +INSERT INTO `dic_city` VALUES ('430304', '430304', '岳塘区', '4303', 3); +INSERT INTO `dic_city` VALUES ('430321', '430321', '湘潭县', '4303', 3); +INSERT INTO `dic_city` VALUES ('430371', '430371', '湖南湘潭高新技术产业园区', '4303', 3); +INSERT INTO `dic_city` VALUES ('430372', '430372', '湘潭昭山示范区', '4303', 3); +INSERT INTO `dic_city` VALUES ('430373', '430373', '湘潭九华示范区', '4303', 3); +INSERT INTO `dic_city` VALUES ('430381', '430381', '湘乡市', '4303', 3); +INSERT INTO `dic_city` VALUES ('430382', '430382', '韶山市', '4303', 3); +INSERT INTO `dic_city` VALUES ('4304', '4304', '衡阳市', '43', 2); +INSERT INTO `dic_city` VALUES ('430405', '430405', '珠晖区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430406', '430406', '雁峰区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430407', '430407', '石鼓区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430408', '430408', '蒸湘区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430412', '430412', '南岳区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430421', '430421', '衡阳县', '4304', 3); +INSERT INTO `dic_city` VALUES ('430422', '430422', '衡南县', '4304', 3); +INSERT INTO `dic_city` VALUES ('430423', '430423', '衡山县', '4304', 3); +INSERT INTO `dic_city` VALUES ('430424', '430424', '衡东县', '4304', 3); +INSERT INTO `dic_city` VALUES ('430426', '430426', '祁东县', '4304', 3); +INSERT INTO `dic_city` VALUES ('430471', '430471', '衡阳综合保税区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430472', '430472', '湖南衡阳高新技术产业园区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430473', '430473', '湖南衡阳松木经济开发区', '4304', 3); +INSERT INTO `dic_city` VALUES ('430481', '430481', '耒阳市', '4304', 3); +INSERT INTO `dic_city` VALUES ('430482', '430482', '常宁市', '4304', 3); +INSERT INTO `dic_city` VALUES ('4305', '4305', '邵阳市', '43', 2); +INSERT INTO `dic_city` VALUES ('430502', '430502', '双清区', '4305', 3); +INSERT INTO `dic_city` VALUES ('430503', '430503', '大祥区', '4305', 3); +INSERT INTO `dic_city` VALUES ('430511', '430511', '北塔区', '4305', 3); +INSERT INTO `dic_city` VALUES ('430522', '430522', '新邵县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430523', '430523', '邵阳县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430524', '430524', '隆回县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430525', '430525', '洞口县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430527', '430527', '绥宁县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430528', '430528', '新宁县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430529', '430529', '城步苗族自治县', '4305', 3); +INSERT INTO `dic_city` VALUES ('430581', '430581', '武冈市', '4305', 3); +INSERT INTO `dic_city` VALUES ('430582', '430582', '邵东市', '4305', 3); +INSERT INTO `dic_city` VALUES ('4306', '4306', '岳阳市', '43', 2); +INSERT INTO `dic_city` VALUES ('430602', '430602', '岳阳楼区', '4306', 3); +INSERT INTO `dic_city` VALUES ('430603', '430603', '云溪区', '4306', 3); +INSERT INTO `dic_city` VALUES ('430611', '430611', '君山区', '4306', 3); +INSERT INTO `dic_city` VALUES ('430621', '430621', '岳阳县', '4306', 3); +INSERT INTO `dic_city` VALUES ('430623', '430623', '华容县', '4306', 3); +INSERT INTO `dic_city` VALUES ('430624', '430624', '湘阴县', '4306', 3); +INSERT INTO `dic_city` VALUES ('430626', '430626', '平江县', '4306', 3); +INSERT INTO `dic_city` VALUES ('430671', '430671', '岳阳市屈原管理区', '4306', 3); +INSERT INTO `dic_city` VALUES ('430681', '430681', '汨罗市', '4306', 3); +INSERT INTO `dic_city` VALUES ('430682', '430682', '临湘市', '4306', 3); +INSERT INTO `dic_city` VALUES ('4307', '4307', '常德市', '43', 2); +INSERT INTO `dic_city` VALUES ('430702', '430702', '武陵区', '4307', 3); +INSERT INTO `dic_city` VALUES ('430703', '430703', '鼎城区', '4307', 3); +INSERT INTO `dic_city` VALUES ('430721', '430721', '安乡县', '4307', 3); +INSERT INTO `dic_city` VALUES ('430722', '430722', '汉寿县', '4307', 3); +INSERT INTO `dic_city` VALUES ('430723', '430723', '澧县', '4307', 3); +INSERT INTO `dic_city` VALUES ('430724', '430724', '临澧县', '4307', 3); +INSERT INTO `dic_city` VALUES ('430725', '430725', '桃源县', '4307', 3); +INSERT INTO `dic_city` VALUES ('430726', '430726', '石门县', '4307', 3); +INSERT INTO `dic_city` VALUES ('430771', '430771', '常德市西洞庭管理区', '4307', 3); +INSERT INTO `dic_city` VALUES ('430781', '430781', '津市市', '4307', 3); +INSERT INTO `dic_city` VALUES ('4308', '4308', '张家界市', '43', 2); +INSERT INTO `dic_city` VALUES ('430802', '430802', '永定区', '4308', 3); +INSERT INTO `dic_city` VALUES ('430811', '430811', '武陵源区', '4308', 3); +INSERT INTO `dic_city` VALUES ('430821', '430821', '慈利县', '4308', 3); +INSERT INTO `dic_city` VALUES ('430822', '430822', '桑植县', '4308', 3); +INSERT INTO `dic_city` VALUES ('4309', '4309', '益阳市', '43', 2); +INSERT INTO `dic_city` VALUES ('430902', '430902', '资阳区', '4309', 3); +INSERT INTO `dic_city` VALUES ('430903', '430903', '赫山区', '4309', 3); +INSERT INTO `dic_city` VALUES ('430921', '430921', '南县', '4309', 3); +INSERT INTO `dic_city` VALUES ('430922', '430922', '桃江县', '4309', 3); +INSERT INTO `dic_city` VALUES ('430923', '430923', '安化县', '4309', 3); +INSERT INTO `dic_city` VALUES ('430971', '430971', '益阳市大通湖管理区', '4309', 3); +INSERT INTO `dic_city` VALUES ('430972', '430972', '湖南益阳高新技术产业园区', '4309', 3); +INSERT INTO `dic_city` VALUES ('430981', '430981', '沅江市', '4309', 3); +INSERT INTO `dic_city` VALUES ('4310', '4310', '郴州市', '43', 2); +INSERT INTO `dic_city` VALUES ('431002', '431002', '北湖区', '4310', 3); +INSERT INTO `dic_city` VALUES ('431003', '431003', '苏仙区', '4310', 3); +INSERT INTO `dic_city` VALUES ('431021', '431021', '桂阳县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431022', '431022', '宜章县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431023', '431023', '永兴县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431024', '431024', '嘉禾县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431025', '431025', '临武县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431026', '431026', '汝城县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431027', '431027', '桂东县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431028', '431028', '安仁县', '4310', 3); +INSERT INTO `dic_city` VALUES ('431081', '431081', '资兴市', '4310', 3); +INSERT INTO `dic_city` VALUES ('4311', '4311', '永州市', '43', 2); +INSERT INTO `dic_city` VALUES ('431102', '431102', '零陵区', '4311', 3); +INSERT INTO `dic_city` VALUES ('431103', '431103', '冷水滩区', '4311', 3); +INSERT INTO `dic_city` VALUES ('431121', '431121', '祁阳县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431122', '431122', '东安县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431123', '431123', '双牌县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431124', '431124', '道县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431125', '431125', '江永县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431126', '431126', '宁远县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431127', '431127', '蓝山县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431128', '431128', '新田县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431129', '431129', '江华瑶族自治县', '4311', 3); +INSERT INTO `dic_city` VALUES ('431171', '431171', '永州经济技术开发区', '4311', 3); +INSERT INTO `dic_city` VALUES ('431172', '431172', '永州市金洞管理区', '4311', 3); +INSERT INTO `dic_city` VALUES ('431173', '431173', '永州市回龙圩管理区', '4311', 3); +INSERT INTO `dic_city` VALUES ('4312', '4312', '怀化市', '43', 2); +INSERT INTO `dic_city` VALUES ('431202', '431202', '鹤城区', '4312', 3); +INSERT INTO `dic_city` VALUES ('431221', '431221', '中方县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431222', '431222', '沅陵县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431223', '431223', '辰溪县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431224', '431224', '溆浦县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431225', '431225', '会同县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431226', '431226', '麻阳苗族自治县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431227', '431227', '新晃侗族自治县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431228', '431228', '芷江侗族自治县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431229', '431229', '靖州苗族侗族自治县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431230', '431230', '通道侗族自治县', '4312', 3); +INSERT INTO `dic_city` VALUES ('431271', '431271', '怀化市洪江管理区', '4312', 3); +INSERT INTO `dic_city` VALUES ('431281', '431281', '洪江市', '4312', 3); +INSERT INTO `dic_city` VALUES ('4313', '4313', '娄底市', '43', 2); +INSERT INTO `dic_city` VALUES ('431302', '431302', '娄星区', '4313', 3); +INSERT INTO `dic_city` VALUES ('431321', '431321', '双峰县', '4313', 3); +INSERT INTO `dic_city` VALUES ('431322', '431322', '新化县', '4313', 3); +INSERT INTO `dic_city` VALUES ('431381', '431381', '冷水江市', '4313', 3); +INSERT INTO `dic_city` VALUES ('431382', '431382', '涟源市', '4313', 3); +INSERT INTO `dic_city` VALUES ('4331', '4331', '湘西土家族苗族自治州', '43', 2); +INSERT INTO `dic_city` VALUES ('433101', '433101', '吉首市', '4331', 3); +INSERT INTO `dic_city` VALUES ('433122', '433122', '泸溪县', '4331', 3); +INSERT INTO `dic_city` VALUES ('433123', '433123', '凤凰县', '4331', 3); +INSERT INTO `dic_city` VALUES ('433124', '433124', '花垣县', '4331', 3); +INSERT INTO `dic_city` VALUES ('433125', '433125', '保靖县', '4331', 3); +INSERT INTO `dic_city` VALUES ('433126', '433126', '古丈县', '4331', 3); +INSERT INTO `dic_city` VALUES ('433127', '433127', '永顺县', '4331', 3); +INSERT INTO `dic_city` VALUES ('433130', '433130', '龙山县', '4331', 3); +INSERT INTO `dic_city` VALUES ('44', '44', '广东省', NULL, 1); +INSERT INTO `dic_city` VALUES ('4401', '4401', '广州市', '44', 2); +INSERT INTO `dic_city` VALUES ('440103', '440103', '荔湾区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440104', '440104', '越秀区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440105', '440105', '海珠区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440106', '440106', '天河区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440111', '440111', '白云区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440112', '440112', '黄埔区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440113', '440113', '番禺区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440114', '440114', '花都区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440115', '440115', '南沙区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440117', '440117', '从化区', '4401', 3); +INSERT INTO `dic_city` VALUES ('440118', '440118', '增城区', '4401', 3); +INSERT INTO `dic_city` VALUES ('4402', '4402', '韶关市', '44', 2); +INSERT INTO `dic_city` VALUES ('440203', '440203', '武江区', '4402', 3); +INSERT INTO `dic_city` VALUES ('440204', '440204', '浈江区', '4402', 3); +INSERT INTO `dic_city` VALUES ('440205', '440205', '曲江区', '4402', 3); +INSERT INTO `dic_city` VALUES ('440222', '440222', '始兴县', '4402', 3); +INSERT INTO `dic_city` VALUES ('440224', '440224', '仁化县', '4402', 3); +INSERT INTO `dic_city` VALUES ('440229', '440229', '翁源县', '4402', 3); +INSERT INTO `dic_city` VALUES ('440232', '440232', '乳源瑶族自治县', '4402', 3); +INSERT INTO `dic_city` VALUES ('440233', '440233', '新丰县', '4402', 3); +INSERT INTO `dic_city` VALUES ('440281', '440281', '乐昌市', '4402', 3); +INSERT INTO `dic_city` VALUES ('440282', '440282', '南雄市', '4402', 3); +INSERT INTO `dic_city` VALUES ('4403', '4403', '深圳市', '44', 2); +INSERT INTO `dic_city` VALUES ('440303', '440303', '罗湖区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440304', '440304', '福田区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440305', '440305', '南山区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440306', '440306', '宝安区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440307', '440307', '龙岗区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440308', '440308', '盐田区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440309', '440309', '龙华区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440310', '440310', '坪山区', '4403', 3); +INSERT INTO `dic_city` VALUES ('440311', '440311', '光明区', '4403', 3); +INSERT INTO `dic_city` VALUES ('4404', '4404', '珠海市', '44', 2); +INSERT INTO `dic_city` VALUES ('440402', '440402', '香洲区', '4404', 3); +INSERT INTO `dic_city` VALUES ('440403', '440403', '斗门区', '4404', 3); +INSERT INTO `dic_city` VALUES ('440404', '440404', '金湾区', '4404', 3); +INSERT INTO `dic_city` VALUES ('4405', '4405', '汕头市', '44', 2); +INSERT INTO `dic_city` VALUES ('440507', '440507', '龙湖区', '4405', 3); +INSERT INTO `dic_city` VALUES ('440511', '440511', '金平区', '4405', 3); +INSERT INTO `dic_city` VALUES ('440512', '440512', '濠江区', '4405', 3); +INSERT INTO `dic_city` VALUES ('440513', '440513', '潮阳区', '4405', 3); +INSERT INTO `dic_city` VALUES ('440514', '440514', '潮南区', '4405', 3); +INSERT INTO `dic_city` VALUES ('440515', '440515', '澄海区', '4405', 3); +INSERT INTO `dic_city` VALUES ('440523', '440523', '南澳县', '4405', 3); +INSERT INTO `dic_city` VALUES ('4406', '4406', '佛山市', '44', 2); +INSERT INTO `dic_city` VALUES ('440604', '440604', '禅城区', '4406', 3); +INSERT INTO `dic_city` VALUES ('440605', '440605', '南海区', '4406', 3); +INSERT INTO `dic_city` VALUES ('440606', '440606', '顺德区', '4406', 3); +INSERT INTO `dic_city` VALUES ('440607', '440607', '三水区', '4406', 3); +INSERT INTO `dic_city` VALUES ('440608', '440608', '高明区', '4406', 3); +INSERT INTO `dic_city` VALUES ('4407', '4407', '江门市', '44', 2); +INSERT INTO `dic_city` VALUES ('440703', '440703', '蓬江区', '4407', 3); +INSERT INTO `dic_city` VALUES ('440704', '440704', '江海区', '4407', 3); +INSERT INTO `dic_city` VALUES ('440705', '440705', '新会区', '4407', 3); +INSERT INTO `dic_city` VALUES ('440781', '440781', '台山市', '4407', 3); +INSERT INTO `dic_city` VALUES ('440783', '440783', '开平市', '4407', 3); +INSERT INTO `dic_city` VALUES ('440784', '440784', '鹤山市', '4407', 3); +INSERT INTO `dic_city` VALUES ('440785', '440785', '恩平市', '4407', 3); +INSERT INTO `dic_city` VALUES ('4408', '4408', '湛江市', '44', 2); +INSERT INTO `dic_city` VALUES ('440802', '440802', '赤坎区', '4408', 3); +INSERT INTO `dic_city` VALUES ('440803', '440803', '霞山区', '4408', 3); +INSERT INTO `dic_city` VALUES ('440804', '440804', '坡头区', '4408', 3); +INSERT INTO `dic_city` VALUES ('440811', '440811', '麻章区', '4408', 3); +INSERT INTO `dic_city` VALUES ('440823', '440823', '遂溪县', '4408', 3); +INSERT INTO `dic_city` VALUES ('440825', '440825', '徐闻县', '4408', 3); +INSERT INTO `dic_city` VALUES ('440881', '440881', '廉江市', '4408', 3); +INSERT INTO `dic_city` VALUES ('440882', '440882', '雷州市', '4408', 3); +INSERT INTO `dic_city` VALUES ('440883', '440883', '吴川市', '4408', 3); +INSERT INTO `dic_city` VALUES ('4409', '4409', '茂名市', '44', 2); +INSERT INTO `dic_city` VALUES ('440902', '440902', '茂南区', '4409', 3); +INSERT INTO `dic_city` VALUES ('440904', '440904', '电白区', '4409', 3); +INSERT INTO `dic_city` VALUES ('440981', '440981', '高州市', '4409', 3); +INSERT INTO `dic_city` VALUES ('440982', '440982', '化州市', '4409', 3); +INSERT INTO `dic_city` VALUES ('440983', '440983', '信宜市', '4409', 3); +INSERT INTO `dic_city` VALUES ('4412', '4412', '肇庆市', '44', 2); +INSERT INTO `dic_city` VALUES ('441202', '441202', '端州区', '4412', 3); +INSERT INTO `dic_city` VALUES ('441203', '441203', '鼎湖区', '4412', 3); +INSERT INTO `dic_city` VALUES ('441204', '441204', '高要区', '4412', 3); +INSERT INTO `dic_city` VALUES ('441223', '441223', '广宁县', '4412', 3); +INSERT INTO `dic_city` VALUES ('441224', '441224', '怀集县', '4412', 3); +INSERT INTO `dic_city` VALUES ('441225', '441225', '封开县', '4412', 3); +INSERT INTO `dic_city` VALUES ('441226', '441226', '德庆县', '4412', 3); +INSERT INTO `dic_city` VALUES ('441284', '441284', '四会市', '4412', 3); +INSERT INTO `dic_city` VALUES ('4413', '4413', '惠州市', '44', 2); +INSERT INTO `dic_city` VALUES ('441302', '441302', '惠城区', '4413', 3); +INSERT INTO `dic_city` VALUES ('441303', '441303', '惠阳区', '4413', 3); +INSERT INTO `dic_city` VALUES ('441322', '441322', '博罗县', '4413', 3); +INSERT INTO `dic_city` VALUES ('441323', '441323', '惠东县', '4413', 3); +INSERT INTO `dic_city` VALUES ('441324', '441324', '龙门县', '4413', 3); +INSERT INTO `dic_city` VALUES ('4414', '4414', '梅州市', '44', 2); +INSERT INTO `dic_city` VALUES ('441402', '441402', '梅江区', '4414', 3); +INSERT INTO `dic_city` VALUES ('441403', '441403', '梅县区', '4414', 3); +INSERT INTO `dic_city` VALUES ('441422', '441422', '大埔县', '4414', 3); +INSERT INTO `dic_city` VALUES ('441423', '441423', '丰顺县', '4414', 3); +INSERT INTO `dic_city` VALUES ('441424', '441424', '五华县', '4414', 3); +INSERT INTO `dic_city` VALUES ('441426', '441426', '平远县', '4414', 3); +INSERT INTO `dic_city` VALUES ('441427', '441427', '蕉岭县', '4414', 3); +INSERT INTO `dic_city` VALUES ('441481', '441481', '兴宁市', '4414', 3); +INSERT INTO `dic_city` VALUES ('4415', '4415', '汕尾市', '44', 2); +INSERT INTO `dic_city` VALUES ('441502', '441502', '城区', '4415', 3); +INSERT INTO `dic_city` VALUES ('441521', '441521', '海丰县', '4415', 3); +INSERT INTO `dic_city` VALUES ('441523', '441523', '陆河县', '4415', 3); +INSERT INTO `dic_city` VALUES ('441581', '441581', '陆丰市', '4415', 3); +INSERT INTO `dic_city` VALUES ('4416', '4416', '河源市', '44', 2); +INSERT INTO `dic_city` VALUES ('441602', '441602', '源城区', '4416', 3); +INSERT INTO `dic_city` VALUES ('441621', '441621', '紫金县', '4416', 3); +INSERT INTO `dic_city` VALUES ('441622', '441622', '龙川县', '4416', 3); +INSERT INTO `dic_city` VALUES ('441623', '441623', '连平县', '4416', 3); +INSERT INTO `dic_city` VALUES ('441624', '441624', '和平县', '4416', 3); +INSERT INTO `dic_city` VALUES ('441625', '441625', '东源县', '4416', 3); +INSERT INTO `dic_city` VALUES ('4417', '4417', '阳江市', '44', 2); +INSERT INTO `dic_city` VALUES ('441702', '441702', '江城区', '4417', 3); +INSERT INTO `dic_city` VALUES ('441704', '441704', '阳东区', '4417', 3); +INSERT INTO `dic_city` VALUES ('441721', '441721', '阳西县', '4417', 3); +INSERT INTO `dic_city` VALUES ('441781', '441781', '阳春市', '4417', 3); +INSERT INTO `dic_city` VALUES ('4418', '4418', '清远市', '44', 2); +INSERT INTO `dic_city` VALUES ('441802', '441802', '清城区', '4418', 3); +INSERT INTO `dic_city` VALUES ('441803', '441803', '清新区', '4418', 3); +INSERT INTO `dic_city` VALUES ('441821', '441821', '佛冈县', '4418', 3); +INSERT INTO `dic_city` VALUES ('441823', '441823', '阳山县', '4418', 3); +INSERT INTO `dic_city` VALUES ('441825', '441825', '连山壮族瑶族自治县', '4418', 3); +INSERT INTO `dic_city` VALUES ('441826', '441826', '连南瑶族自治县', '4418', 3); +INSERT INTO `dic_city` VALUES ('441881', '441881', '英德市', '4418', 3); +INSERT INTO `dic_city` VALUES ('441882', '441882', '连州市', '4418', 3); +INSERT INTO `dic_city` VALUES ('4419', '4419', '东莞市', '44', 2); +INSERT INTO `dic_city` VALUES ('441900003', '441900003', '东城街道', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900004', '441900004', '南城街道', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900005', '441900005', '万江街道', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900006', '441900006', '莞城街道', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900101', '441900101', '石碣镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900102', '441900102', '石龙镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900103', '441900103', '茶山镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900104', '441900104', '石排镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900105', '441900105', '企石镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900106', '441900106', '横沥镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900107', '441900107', '桥头镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900108', '441900108', '谢岗镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900109', '441900109', '东坑镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900110', '441900110', '常平镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900111', '441900111', '寮步镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900112', '441900112', '樟木头镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900113', '441900113', '大朗镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900114', '441900114', '黄江镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900115', '441900115', '清溪镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900116', '441900116', '塘厦镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900117', '441900117', '凤岗镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900118', '441900118', '大岭山镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900119', '441900119', '长安镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900121', '441900121', '虎门镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900122', '441900122', '厚街镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900123', '441900123', '沙田镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900124', '441900124', '道滘镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900125', '441900125', '洪梅镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900126', '441900126', '麻涌镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900127', '441900127', '望牛墩镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900128', '441900128', '中堂镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900129', '441900129', '高埗镇', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900401', '441900401', '松山湖', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900402', '441900402', '东莞港', '4419', 3); +INSERT INTO `dic_city` VALUES ('441900403', '441900403', '东莞生态园', '4419', 3); +INSERT INTO `dic_city` VALUES ('4420', '4420', '中山市', '44', 2); +INSERT INTO `dic_city` VALUES ('442000001', '442000001', '石岐街道', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000002', '442000002', '东区街道', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000003', '442000003', '中山港街道', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000004', '442000004', '西区街道', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000005', '442000005', '南区街道', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000006', '442000006', '五桂山街道', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000100', '442000100', '小榄镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000101', '442000101', '黄圃镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000102', '442000102', '民众镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000103', '442000103', '东凤镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000104', '442000104', '东升镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000105', '442000105', '古镇镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000106', '442000106', '沙溪镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000107', '442000107', '坦洲镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000108', '442000108', '港口镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000109', '442000109', '三角镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000110', '442000110', '横栏镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000111', '442000111', '南头镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000112', '442000112', '阜沙镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000113', '442000113', '南朗镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000114', '442000114', '三乡镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000115', '442000115', '板芙镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000116', '442000116', '大涌镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('442000117', '442000117', '神湾镇', '4420', 3); +INSERT INTO `dic_city` VALUES ('4451', '4451', '潮州市', '44', 2); +INSERT INTO `dic_city` VALUES ('445102', '445102', '湘桥区', '4451', 3); +INSERT INTO `dic_city` VALUES ('445103', '445103', '潮安区', '4451', 3); +INSERT INTO `dic_city` VALUES ('445122', '445122', '饶平县', '4451', 3); +INSERT INTO `dic_city` VALUES ('4452', '4452', '揭阳市', '44', 2); +INSERT INTO `dic_city` VALUES ('445202', '445202', '榕城区', '4452', 3); +INSERT INTO `dic_city` VALUES ('445203', '445203', '揭东区', '4452', 3); +INSERT INTO `dic_city` VALUES ('445222', '445222', '揭西县', '4452', 3); +INSERT INTO `dic_city` VALUES ('445224', '445224', '惠来县', '4452', 3); +INSERT INTO `dic_city` VALUES ('445281', '445281', '普宁市', '4452', 3); +INSERT INTO `dic_city` VALUES ('4453', '4453', '云浮市', '44', 2); +INSERT INTO `dic_city` VALUES ('445302', '445302', '云城区', '4453', 3); +INSERT INTO `dic_city` VALUES ('445303', '445303', '云安区', '4453', 3); +INSERT INTO `dic_city` VALUES ('445321', '445321', '新兴县', '4453', 3); +INSERT INTO `dic_city` VALUES ('445322', '445322', '郁南县', '4453', 3); +INSERT INTO `dic_city` VALUES ('445381', '445381', '罗定市', '4453', 3); +INSERT INTO `dic_city` VALUES ('45', '45', '广西壮族自治区', NULL, 1); +INSERT INTO `dic_city` VALUES ('4501', '4501', '南宁市', '45', 2); +INSERT INTO `dic_city` VALUES ('450102', '450102', '兴宁区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450103', '450103', '青秀区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450105', '450105', '江南区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450107', '450107', '西乡塘区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450108', '450108', '良庆区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450109', '450109', '邕宁区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450110', '450110', '武鸣区', '4501', 3); +INSERT INTO `dic_city` VALUES ('450123', '450123', '隆安县', '4501', 3); +INSERT INTO `dic_city` VALUES ('450124', '450124', '马山县', '4501', 3); +INSERT INTO `dic_city` VALUES ('450125', '450125', '上林县', '4501', 3); +INSERT INTO `dic_city` VALUES ('450126', '450126', '宾阳县', '4501', 3); +INSERT INTO `dic_city` VALUES ('450127', '450127', '横县', '4501', 3); +INSERT INTO `dic_city` VALUES ('4502', '4502', '柳州市', '45', 2); +INSERT INTO `dic_city` VALUES ('450202', '450202', '城中区', '4502', 3); +INSERT INTO `dic_city` VALUES ('450203', '450203', '鱼峰区', '4502', 3); +INSERT INTO `dic_city` VALUES ('450204', '450204', '柳南区', '4502', 3); +INSERT INTO `dic_city` VALUES ('450205', '450205', '柳北区', '4502', 3); +INSERT INTO `dic_city` VALUES ('450206', '450206', '柳江区', '4502', 3); +INSERT INTO `dic_city` VALUES ('450222', '450222', '柳城县', '4502', 3); +INSERT INTO `dic_city` VALUES ('450223', '450223', '鹿寨县', '4502', 3); +INSERT INTO `dic_city` VALUES ('450224', '450224', '融安县', '4502', 3); +INSERT INTO `dic_city` VALUES ('450225', '450225', '融水苗族自治县', '4502', 3); +INSERT INTO `dic_city` VALUES ('450226', '450226', '三江侗族自治县', '4502', 3); +INSERT INTO `dic_city` VALUES ('4503', '4503', '桂林市', '45', 2); +INSERT INTO `dic_city` VALUES ('450302', '450302', '秀峰区', '4503', 3); +INSERT INTO `dic_city` VALUES ('450303', '450303', '叠彩区', '4503', 3); +INSERT INTO `dic_city` VALUES ('450304', '450304', '象山区', '4503', 3); +INSERT INTO `dic_city` VALUES ('450305', '450305', '七星区', '4503', 3); +INSERT INTO `dic_city` VALUES ('450311', '450311', '雁山区', '4503', 3); +INSERT INTO `dic_city` VALUES ('450312', '450312', '临桂区', '4503', 3); +INSERT INTO `dic_city` VALUES ('450321', '450321', '阳朔县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450323', '450323', '灵川县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450324', '450324', '全州县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450325', '450325', '兴安县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450326', '450326', '永福县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450327', '450327', '灌阳县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450328', '450328', '龙胜各族自治县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450329', '450329', '资源县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450330', '450330', '平乐县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450332', '450332', '恭城瑶族自治县', '4503', 3); +INSERT INTO `dic_city` VALUES ('450381', '450381', '荔浦市', '4503', 3); +INSERT INTO `dic_city` VALUES ('4504', '4504', '梧州市', '45', 2); +INSERT INTO `dic_city` VALUES ('450403', '450403', '万秀区', '4504', 3); +INSERT INTO `dic_city` VALUES ('450405', '450405', '长洲区', '4504', 3); +INSERT INTO `dic_city` VALUES ('450406', '450406', '龙圩区', '4504', 3); +INSERT INTO `dic_city` VALUES ('450421', '450421', '苍梧县', '4504', 3); +INSERT INTO `dic_city` VALUES ('450422', '450422', '藤县', '4504', 3); +INSERT INTO `dic_city` VALUES ('450423', '450423', '蒙山县', '4504', 3); +INSERT INTO `dic_city` VALUES ('450481', '450481', '岑溪市', '4504', 3); +INSERT INTO `dic_city` VALUES ('4505', '4505', '北海市', '45', 2); +INSERT INTO `dic_city` VALUES ('450502', '450502', '海城区', '4505', 3); +INSERT INTO `dic_city` VALUES ('450503', '450503', '银海区', '4505', 3); +INSERT INTO `dic_city` VALUES ('450512', '450512', '铁山港区', '4505', 3); +INSERT INTO `dic_city` VALUES ('450521', '450521', '合浦县', '4505', 3); +INSERT INTO `dic_city` VALUES ('4506', '4506', '防城港市', '45', 2); +INSERT INTO `dic_city` VALUES ('450602', '450602', '港口区', '4506', 3); +INSERT INTO `dic_city` VALUES ('450603', '450603', '防城区', '4506', 3); +INSERT INTO `dic_city` VALUES ('450621', '450621', '上思县', '4506', 3); +INSERT INTO `dic_city` VALUES ('450681', '450681', '东兴市', '4506', 3); +INSERT INTO `dic_city` VALUES ('4507', '4507', '钦州市', '45', 2); +INSERT INTO `dic_city` VALUES ('450702', '450702', '钦南区', '4507', 3); +INSERT INTO `dic_city` VALUES ('450703', '450703', '钦北区', '4507', 3); +INSERT INTO `dic_city` VALUES ('450721', '450721', '灵山县', '4507', 3); +INSERT INTO `dic_city` VALUES ('450722', '450722', '浦北县', '4507', 3); +INSERT INTO `dic_city` VALUES ('4508', '4508', '贵港市', '45', 2); +INSERT INTO `dic_city` VALUES ('450802', '450802', '港北区', '4508', 3); +INSERT INTO `dic_city` VALUES ('450803', '450803', '港南区', '4508', 3); +INSERT INTO `dic_city` VALUES ('450804', '450804', '覃塘区', '4508', 3); +INSERT INTO `dic_city` VALUES ('450821', '450821', '平南县', '4508', 3); +INSERT INTO `dic_city` VALUES ('450881', '450881', '桂平市', '4508', 3); +INSERT INTO `dic_city` VALUES ('4509', '4509', '玉林市', '45', 2); +INSERT INTO `dic_city` VALUES ('450902', '450902', '玉州区', '4509', 3); +INSERT INTO `dic_city` VALUES ('450903', '450903', '福绵区', '4509', 3); +INSERT INTO `dic_city` VALUES ('450921', '450921', '容县', '4509', 3); +INSERT INTO `dic_city` VALUES ('450922', '450922', '陆川县', '4509', 3); +INSERT INTO `dic_city` VALUES ('450923', '450923', '博白县', '4509', 3); +INSERT INTO `dic_city` VALUES ('450924', '450924', '兴业县', '4509', 3); +INSERT INTO `dic_city` VALUES ('450981', '450981', '北流市', '4509', 3); +INSERT INTO `dic_city` VALUES ('4510', '4510', '百色市', '45', 2); +INSERT INTO `dic_city` VALUES ('451002', '451002', '右江区', '4510', 3); +INSERT INTO `dic_city` VALUES ('451003', '451003', '田阳区', '4510', 3); +INSERT INTO `dic_city` VALUES ('451022', '451022', '田东县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451024', '451024', '德保县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451026', '451026', '那坡县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451027', '451027', '凌云县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451028', '451028', '乐业县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451029', '451029', '田林县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451030', '451030', '西林县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451031', '451031', '隆林各族自治县', '4510', 3); +INSERT INTO `dic_city` VALUES ('451081', '451081', '靖西市', '4510', 3); +INSERT INTO `dic_city` VALUES ('451082', '451082', '平果市', '4510', 3); +INSERT INTO `dic_city` VALUES ('4511', '4511', '贺州市', '45', 2); +INSERT INTO `dic_city` VALUES ('451102', '451102', '八步区', '4511', 3); +INSERT INTO `dic_city` VALUES ('451103', '451103', '平桂区', '4511', 3); +INSERT INTO `dic_city` VALUES ('451121', '451121', '昭平县', '4511', 3); +INSERT INTO `dic_city` VALUES ('451122', '451122', '钟山县', '4511', 3); +INSERT INTO `dic_city` VALUES ('451123', '451123', '富川瑶族自治县', '4511', 3); +INSERT INTO `dic_city` VALUES ('4512', '4512', '河池市', '45', 2); +INSERT INTO `dic_city` VALUES ('451202', '451202', '金城江区', '4512', 3); +INSERT INTO `dic_city` VALUES ('451203', '451203', '宜州区', '4512', 3); +INSERT INTO `dic_city` VALUES ('451221', '451221', '南丹县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451222', '451222', '天峨县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451223', '451223', '凤山县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451224', '451224', '东兰县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451225', '451225', '罗城仫佬族自治县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451226', '451226', '环江毛南族自治县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451227', '451227', '巴马瑶族自治县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451228', '451228', '都安瑶族自治县', '4512', 3); +INSERT INTO `dic_city` VALUES ('451229', '451229', '大化瑶族自治县', '4512', 3); +INSERT INTO `dic_city` VALUES ('4513', '4513', '来宾市', '45', 2); +INSERT INTO `dic_city` VALUES ('451302', '451302', '兴宾区', '4513', 3); +INSERT INTO `dic_city` VALUES ('451321', '451321', '忻城县', '4513', 3); +INSERT INTO `dic_city` VALUES ('451322', '451322', '象州县', '4513', 3); +INSERT INTO `dic_city` VALUES ('451323', '451323', '武宣县', '4513', 3); +INSERT INTO `dic_city` VALUES ('451324', '451324', '金秀瑶族自治县', '4513', 3); +INSERT INTO `dic_city` VALUES ('451381', '451381', '合山市', '4513', 3); +INSERT INTO `dic_city` VALUES ('4514', '4514', '崇左市', '45', 2); +INSERT INTO `dic_city` VALUES ('451402', '451402', '江州区', '4514', 3); +INSERT INTO `dic_city` VALUES ('451421', '451421', '扶绥县', '4514', 3); +INSERT INTO `dic_city` VALUES ('451422', '451422', '宁明县', '4514', 3); +INSERT INTO `dic_city` VALUES ('451423', '451423', '龙州县', '4514', 3); +INSERT INTO `dic_city` VALUES ('451424', '451424', '大新县', '4514', 3); +INSERT INTO `dic_city` VALUES ('451425', '451425', '天等县', '4514', 3); +INSERT INTO `dic_city` VALUES ('451481', '451481', '凭祥市', '4514', 3); +INSERT INTO `dic_city` VALUES ('46', '46', '海南省', NULL, 1); +INSERT INTO `dic_city` VALUES ('4601', '4601', '海口市', '46', 2); +INSERT INTO `dic_city` VALUES ('460105', '460105', '秀英区', '4601', 3); +INSERT INTO `dic_city` VALUES ('460106', '460106', '龙华区', '4601', 3); +INSERT INTO `dic_city` VALUES ('460107', '460107', '琼山区', '4601', 3); +INSERT INTO `dic_city` VALUES ('460108', '460108', '美兰区', '4601', 3); +INSERT INTO `dic_city` VALUES ('4602', '4602', '三亚市', '46', 2); +INSERT INTO `dic_city` VALUES ('460202', '460202', '海棠区', '4602', 3); +INSERT INTO `dic_city` VALUES ('460203', '460203', '吉阳区', '4602', 3); +INSERT INTO `dic_city` VALUES ('460204', '460204', '天涯区', '4602', 3); +INSERT INTO `dic_city` VALUES ('460205', '460205', '崖州区', '4602', 3); +INSERT INTO `dic_city` VALUES ('4603', '4603', '三沙市', '46', 2); +INSERT INTO `dic_city` VALUES ('460321', '460321', '西沙群岛', '4603', 3); +INSERT INTO `dic_city` VALUES ('460322', '460322', '南沙群岛', '4603', 3); +INSERT INTO `dic_city` VALUES ('460323', '460323', '中沙群岛的岛礁及其海域', '4603', 3); +INSERT INTO `dic_city` VALUES ('4604', '4604', '儋州市', '46', 2); +INSERT INTO `dic_city` VALUES ('460400100', '460400100', '那大镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400101', '460400101', '和庆镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400102', '460400102', '南丰镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400103', '460400103', '大成镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400104', '460400104', '雅星镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400105', '460400105', '兰洋镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400106', '460400106', '光村镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400107', '460400107', '木棠镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400108', '460400108', '海头镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400109', '460400109', '峨蔓镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400111', '460400111', '王五镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400112', '460400112', '白马井镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400113', '460400113', '中和镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400114', '460400114', '排浦镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400115', '460400115', '东成镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400116', '460400116', '新州镇', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400499', '460400499', '洋浦经济开发区', '4604', 3); +INSERT INTO `dic_city` VALUES ('460400500', '460400500', '华南热作学院', '4604', 3); +INSERT INTO `dic_city` VALUES ('4690', '4690', '省直辖县级行政区划', '46', 2); +INSERT INTO `dic_city` VALUES ('469001', '469001', '五指山市', '4690', 3); +INSERT INTO `dic_city` VALUES ('469002', '469002', '琼海市', '4690', 3); +INSERT INTO `dic_city` VALUES ('469005', '469005', '文昌市', '4690', 3); +INSERT INTO `dic_city` VALUES ('469006', '469006', '万宁市', '4690', 3); +INSERT INTO `dic_city` VALUES ('469007', '469007', '东方市', '4690', 3); +INSERT INTO `dic_city` VALUES ('469021', '469021', '定安县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469022', '469022', '屯昌县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469023', '469023', '澄迈县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469024', '469024', '临高县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469025', '469025', '白沙黎族自治县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469026', '469026', '昌江黎族自治县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469027', '469027', '乐东黎族自治县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469028', '469028', '陵水黎族自治县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469029', '469029', '保亭黎族苗族自治县', '4690', 3); +INSERT INTO `dic_city` VALUES ('469030', '469030', '琼中黎族苗族自治县', '4690', 3); +INSERT INTO `dic_city` VALUES ('50', '50', '重庆市', NULL, 1); +INSERT INTO `dic_city` VALUES ('5001', '5001', '市辖区', '50', 2); +INSERT INTO `dic_city` VALUES ('500101', '500101', '万州区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500102', '500102', '涪陵区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500103', '500103', '渝中区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500104', '500104', '大渡口区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500105', '500105', '江北区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500106', '500106', '沙坪坝区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500107', '500107', '九龙坡区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500108', '500108', '南岸区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500109', '500109', '北碚区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500110', '500110', '綦江区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500111', '500111', '大足区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500112', '500112', '渝北区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500113', '500113', '巴南区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500114', '500114', '黔江区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500115', '500115', '长寿区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500116', '500116', '江津区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500117', '500117', '合川区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500118', '500118', '永川区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500119', '500119', '南川区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500120', '500120', '璧山区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500151', '500151', '铜梁区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500152', '500152', '潼南区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500153', '500153', '荣昌区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500154', '500154', '开州区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500155', '500155', '梁平区', '5001', 3); +INSERT INTO `dic_city` VALUES ('500156', '500156', '武隆区', '5001', 3); +INSERT INTO `dic_city` VALUES ('5002', '5002', '县', '50', 2); +INSERT INTO `dic_city` VALUES ('500229', '500229', '城口县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500230', '500230', '丰都县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500231', '500231', '垫江县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500233', '500233', '忠县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500235', '500235', '云阳县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500236', '500236', '奉节县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500237', '500237', '巫山县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500238', '500238', '巫溪县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500240', '500240', '石柱土家族自治县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500241', '500241', '秀山土家族苗族自治县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500242', '500242', '酉阳土家族苗族自治县', '5002', 3); +INSERT INTO `dic_city` VALUES ('500243', '500243', '彭水苗族土家族自治县', '5002', 3); +INSERT INTO `dic_city` VALUES ('51', '51', '四川省', NULL, 1); +INSERT INTO `dic_city` VALUES ('5101', '5101', '成都市', '51', 2); +INSERT INTO `dic_city` VALUES ('510104', '510104', '锦江区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510105', '510105', '青羊区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510106', '510106', '金牛区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510107', '510107', '武侯区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510108', '510108', '成华区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510112', '510112', '龙泉驿区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510113', '510113', '青白江区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510114', '510114', '新都区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510115', '510115', '温江区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510116', '510116', '双流区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510117', '510117', '郫都区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510118', '510118', '新津区', '5101', 3); +INSERT INTO `dic_city` VALUES ('510121', '510121', '金堂县', '5101', 3); +INSERT INTO `dic_city` VALUES ('510129', '510129', '大邑县', '5101', 3); +INSERT INTO `dic_city` VALUES ('510131', '510131', '蒲江县', '5101', 3); +INSERT INTO `dic_city` VALUES ('510181', '510181', '都江堰市', '5101', 3); +INSERT INTO `dic_city` VALUES ('510182', '510182', '彭州市', '5101', 3); +INSERT INTO `dic_city` VALUES ('510183', '510183', '邛崃市', '5101', 3); +INSERT INTO `dic_city` VALUES ('510184', '510184', '崇州市', '5101', 3); +INSERT INTO `dic_city` VALUES ('510185', '510185', '简阳市', '5101', 3); +INSERT INTO `dic_city` VALUES ('5103', '5103', '自贡市', '51', 2); +INSERT INTO `dic_city` VALUES ('510302', '510302', '自流井区', '5103', 3); +INSERT INTO `dic_city` VALUES ('510303', '510303', '贡井区', '5103', 3); +INSERT INTO `dic_city` VALUES ('510304', '510304', '大安区', '5103', 3); +INSERT INTO `dic_city` VALUES ('510311', '510311', '沿滩区', '5103', 3); +INSERT INTO `dic_city` VALUES ('510321', '510321', '荣县', '5103', 3); +INSERT INTO `dic_city` VALUES ('510322', '510322', '富顺县', '5103', 3); +INSERT INTO `dic_city` VALUES ('5104', '5104', '攀枝花市', '51', 2); +INSERT INTO `dic_city` VALUES ('510402', '510402', '东区', '5104', 3); +INSERT INTO `dic_city` VALUES ('510403', '510403', '西区', '5104', 3); +INSERT INTO `dic_city` VALUES ('510411', '510411', '仁和区', '5104', 3); +INSERT INTO `dic_city` VALUES ('510421', '510421', '米易县', '5104', 3); +INSERT INTO `dic_city` VALUES ('510422', '510422', '盐边县', '5104', 3); +INSERT INTO `dic_city` VALUES ('5105', '5105', '泸州市', '51', 2); +INSERT INTO `dic_city` VALUES ('510502', '510502', '江阳区', '5105', 3); +INSERT INTO `dic_city` VALUES ('510503', '510503', '纳溪区', '5105', 3); +INSERT INTO `dic_city` VALUES ('510504', '510504', '龙马潭区', '5105', 3); +INSERT INTO `dic_city` VALUES ('510521', '510521', '泸县', '5105', 3); +INSERT INTO `dic_city` VALUES ('510522', '510522', '合江县', '5105', 3); +INSERT INTO `dic_city` VALUES ('510524', '510524', '叙永县', '5105', 3); +INSERT INTO `dic_city` VALUES ('510525', '510525', '古蔺县', '5105', 3); +INSERT INTO `dic_city` VALUES ('5106', '5106', '德阳市', '51', 2); +INSERT INTO `dic_city` VALUES ('510603', '510603', '旌阳区', '5106', 3); +INSERT INTO `dic_city` VALUES ('510604', '510604', '罗江区', '5106', 3); +INSERT INTO `dic_city` VALUES ('510623', '510623', '中江县', '5106', 3); +INSERT INTO `dic_city` VALUES ('510681', '510681', '广汉市', '5106', 3); +INSERT INTO `dic_city` VALUES ('510682', '510682', '什邡市', '5106', 3); +INSERT INTO `dic_city` VALUES ('510683', '510683', '绵竹市', '5106', 3); +INSERT INTO `dic_city` VALUES ('5107', '5107', '绵阳市', '51', 2); +INSERT INTO `dic_city` VALUES ('510703', '510703', '涪城区', '5107', 3); +INSERT INTO `dic_city` VALUES ('510704', '510704', '游仙区', '5107', 3); +INSERT INTO `dic_city` VALUES ('510705', '510705', '安州区', '5107', 3); +INSERT INTO `dic_city` VALUES ('510722', '510722', '三台县', '5107', 3); +INSERT INTO `dic_city` VALUES ('510723', '510723', '盐亭县', '5107', 3); +INSERT INTO `dic_city` VALUES ('510725', '510725', '梓潼县', '5107', 3); +INSERT INTO `dic_city` VALUES ('510726', '510726', '北川羌族自治县', '5107', 3); +INSERT INTO `dic_city` VALUES ('510727', '510727', '平武县', '5107', 3); +INSERT INTO `dic_city` VALUES ('510781', '510781', '江油市', '5107', 3); +INSERT INTO `dic_city` VALUES ('5108', '5108', '广元市', '51', 2); +INSERT INTO `dic_city` VALUES ('510802', '510802', '利州区', '5108', 3); +INSERT INTO `dic_city` VALUES ('510811', '510811', '昭化区', '5108', 3); +INSERT INTO `dic_city` VALUES ('510812', '510812', '朝天区', '5108', 3); +INSERT INTO `dic_city` VALUES ('510821', '510821', '旺苍县', '5108', 3); +INSERT INTO `dic_city` VALUES ('510822', '510822', '青川县', '5108', 3); +INSERT INTO `dic_city` VALUES ('510823', '510823', '剑阁县', '5108', 3); +INSERT INTO `dic_city` VALUES ('510824', '510824', '苍溪县', '5108', 3); +INSERT INTO `dic_city` VALUES ('5109', '5109', '遂宁市', '51', 2); +INSERT INTO `dic_city` VALUES ('510903', '510903', '船山区', '5109', 3); +INSERT INTO `dic_city` VALUES ('510904', '510904', '安居区', '5109', 3); +INSERT INTO `dic_city` VALUES ('510921', '510921', '蓬溪县', '5109', 3); +INSERT INTO `dic_city` VALUES ('510923', '510923', '大英县', '5109', 3); +INSERT INTO `dic_city` VALUES ('510981', '510981', '射洪市', '5109', 3); +INSERT INTO `dic_city` VALUES ('5110', '5110', '内江市', '51', 2); +INSERT INTO `dic_city` VALUES ('511002', '511002', '市中区', '5110', 3); +INSERT INTO `dic_city` VALUES ('511011', '511011', '东兴区', '5110', 3); +INSERT INTO `dic_city` VALUES ('511024', '511024', '威远县', '5110', 3); +INSERT INTO `dic_city` VALUES ('511025', '511025', '资中县', '5110', 3); +INSERT INTO `dic_city` VALUES ('511071', '511071', '内江经济开发区', '5110', 3); +INSERT INTO `dic_city` VALUES ('511083', '511083', '隆昌市', '5110', 3); +INSERT INTO `dic_city` VALUES ('5111', '5111', '乐山市', '51', 2); +INSERT INTO `dic_city` VALUES ('511102', '511102', '市中区', '5111', 3); +INSERT INTO `dic_city` VALUES ('511111', '511111', '沙湾区', '5111', 3); +INSERT INTO `dic_city` VALUES ('511112', '511112', '五通桥区', '5111', 3); +INSERT INTO `dic_city` VALUES ('511113', '511113', '金口河区', '5111', 3); +INSERT INTO `dic_city` VALUES ('511123', '511123', '犍为县', '5111', 3); +INSERT INTO `dic_city` VALUES ('511124', '511124', '井研县', '5111', 3); +INSERT INTO `dic_city` VALUES ('511126', '511126', '夹江县', '5111', 3); +INSERT INTO `dic_city` VALUES ('511129', '511129', '沐川县', '5111', 3); +INSERT INTO `dic_city` VALUES ('511132', '511132', '峨边彝族自治县', '5111', 3); +INSERT INTO `dic_city` VALUES ('511133', '511133', '马边彝族自治县', '5111', 3); +INSERT INTO `dic_city` VALUES ('511181', '511181', '峨眉山市', '5111', 3); +INSERT INTO `dic_city` VALUES ('5113', '5113', '南充市', '51', 2); +INSERT INTO `dic_city` VALUES ('511302', '511302', '顺庆区', '5113', 3); +INSERT INTO `dic_city` VALUES ('511303', '511303', '高坪区', '5113', 3); +INSERT INTO `dic_city` VALUES ('511304', '511304', '嘉陵区', '5113', 3); +INSERT INTO `dic_city` VALUES ('511321', '511321', '南部县', '5113', 3); +INSERT INTO `dic_city` VALUES ('511322', '511322', '营山县', '5113', 3); +INSERT INTO `dic_city` VALUES ('511323', '511323', '蓬安县', '5113', 3); +INSERT INTO `dic_city` VALUES ('511324', '511324', '仪陇县', '5113', 3); +INSERT INTO `dic_city` VALUES ('511325', '511325', '西充县', '5113', 3); +INSERT INTO `dic_city` VALUES ('511381', '511381', '阆中市', '5113', 3); +INSERT INTO `dic_city` VALUES ('5114', '5114', '眉山市', '51', 2); +INSERT INTO `dic_city` VALUES ('511402', '511402', '东坡区', '5114', 3); +INSERT INTO `dic_city` VALUES ('511403', '511403', '彭山区', '5114', 3); +INSERT INTO `dic_city` VALUES ('511421', '511421', '仁寿县', '5114', 3); +INSERT INTO `dic_city` VALUES ('511423', '511423', '洪雅县', '5114', 3); +INSERT INTO `dic_city` VALUES ('511424', '511424', '丹棱县', '5114', 3); +INSERT INTO `dic_city` VALUES ('511425', '511425', '青神县', '5114', 3); +INSERT INTO `dic_city` VALUES ('5115', '5115', '宜宾市', '51', 2); +INSERT INTO `dic_city` VALUES ('511502', '511502', '翠屏区', '5115', 3); +INSERT INTO `dic_city` VALUES ('511503', '511503', '南溪区', '5115', 3); +INSERT INTO `dic_city` VALUES ('511504', '511504', '叙州区', '5115', 3); +INSERT INTO `dic_city` VALUES ('511523', '511523', '江安县', '5115', 3); +INSERT INTO `dic_city` VALUES ('511524', '511524', '长宁县', '5115', 3); +INSERT INTO `dic_city` VALUES ('511525', '511525', '高县', '5115', 3); +INSERT INTO `dic_city` VALUES ('511526', '511526', '珙县', '5115', 3); +INSERT INTO `dic_city` VALUES ('511527', '511527', '筠连县', '5115', 3); +INSERT INTO `dic_city` VALUES ('511528', '511528', '兴文县', '5115', 3); +INSERT INTO `dic_city` VALUES ('511529', '511529', '屏山县', '5115', 3); +INSERT INTO `dic_city` VALUES ('5116', '5116', '广安市', '51', 2); +INSERT INTO `dic_city` VALUES ('511602', '511602', '广安区', '5116', 3); +INSERT INTO `dic_city` VALUES ('511603', '511603', '前锋区', '5116', 3); +INSERT INTO `dic_city` VALUES ('511621', '511621', '岳池县', '5116', 3); +INSERT INTO `dic_city` VALUES ('511622', '511622', '武胜县', '5116', 3); +INSERT INTO `dic_city` VALUES ('511623', '511623', '邻水县', '5116', 3); +INSERT INTO `dic_city` VALUES ('511681', '511681', '华蓥市', '5116', 3); +INSERT INTO `dic_city` VALUES ('5117', '5117', '达州市', '51', 2); +INSERT INTO `dic_city` VALUES ('511702', '511702', '通川区', '5117', 3); +INSERT INTO `dic_city` VALUES ('511703', '511703', '达川区', '5117', 3); +INSERT INTO `dic_city` VALUES ('511722', '511722', '宣汉县', '5117', 3); +INSERT INTO `dic_city` VALUES ('511723', '511723', '开江县', '5117', 3); +INSERT INTO `dic_city` VALUES ('511724', '511724', '大竹县', '5117', 3); +INSERT INTO `dic_city` VALUES ('511725', '511725', '渠县', '5117', 3); +INSERT INTO `dic_city` VALUES ('511771', '511771', '达州经济开发区', '5117', 3); +INSERT INTO `dic_city` VALUES ('511781', '511781', '万源市', '5117', 3); +INSERT INTO `dic_city` VALUES ('5118', '5118', '雅安市', '51', 2); +INSERT INTO `dic_city` VALUES ('511802', '511802', '雨城区', '5118', 3); +INSERT INTO `dic_city` VALUES ('511803', '511803', '名山区', '5118', 3); +INSERT INTO `dic_city` VALUES ('511822', '511822', '荥经县', '5118', 3); +INSERT INTO `dic_city` VALUES ('511823', '511823', '汉源县', '5118', 3); +INSERT INTO `dic_city` VALUES ('511824', '511824', '石棉县', '5118', 3); +INSERT INTO `dic_city` VALUES ('511825', '511825', '天全县', '5118', 3); +INSERT INTO `dic_city` VALUES ('511826', '511826', '芦山县', '5118', 3); +INSERT INTO `dic_city` VALUES ('511827', '511827', '宝兴县', '5118', 3); +INSERT INTO `dic_city` VALUES ('5119', '5119', '巴中市', '51', 2); +INSERT INTO `dic_city` VALUES ('511902', '511902', '巴州区', '5119', 3); +INSERT INTO `dic_city` VALUES ('511903', '511903', '恩阳区', '5119', 3); +INSERT INTO `dic_city` VALUES ('511921', '511921', '通江县', '5119', 3); +INSERT INTO `dic_city` VALUES ('511922', '511922', '南江县', '5119', 3); +INSERT INTO `dic_city` VALUES ('511923', '511923', '平昌县', '5119', 3); +INSERT INTO `dic_city` VALUES ('511971', '511971', '巴中经济开发区', '5119', 3); +INSERT INTO `dic_city` VALUES ('5120', '5120', '资阳市', '51', 2); +INSERT INTO `dic_city` VALUES ('512002', '512002', '雁江区', '5120', 3); +INSERT INTO `dic_city` VALUES ('512021', '512021', '安岳县', '5120', 3); +INSERT INTO `dic_city` VALUES ('512022', '512022', '乐至县', '5120', 3); +INSERT INTO `dic_city` VALUES ('5132', '5132', '阿坝藏族羌族自治州', '51', 2); +INSERT INTO `dic_city` VALUES ('513201', '513201', '马尔康市', '5132', 3); +INSERT INTO `dic_city` VALUES ('513221', '513221', '汶川县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513222', '513222', '理县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513223', '513223', '茂县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513224', '513224', '松潘县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513225', '513225', '九寨沟县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513226', '513226', '金川县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513227', '513227', '小金县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513228', '513228', '黑水县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513230', '513230', '壤塘县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513231', '513231', '阿坝县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513232', '513232', '若尔盖县', '5132', 3); +INSERT INTO `dic_city` VALUES ('513233', '513233', '红原县', '5132', 3); +INSERT INTO `dic_city` VALUES ('5133', '5133', '甘孜藏族自治州', '51', 2); +INSERT INTO `dic_city` VALUES ('513301', '513301', '康定市', '5133', 3); +INSERT INTO `dic_city` VALUES ('513322', '513322', '泸定县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513323', '513323', '丹巴县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513324', '513324', '九龙县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513325', '513325', '雅江县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513326', '513326', '道孚县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513327', '513327', '炉霍县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513328', '513328', '甘孜县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513329', '513329', '新龙县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513330', '513330', '德格县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513331', '513331', '白玉县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513332', '513332', '石渠县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513333', '513333', '色达县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513334', '513334', '理塘县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513335', '513335', '巴塘县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513336', '513336', '乡城县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513337', '513337', '稻城县', '5133', 3); +INSERT INTO `dic_city` VALUES ('513338', '513338', '得荣县', '5133', 3); +INSERT INTO `dic_city` VALUES ('5134', '5134', '凉山彝族自治州', '51', 2); +INSERT INTO `dic_city` VALUES ('513401', '513401', '西昌市', '5134', 3); +INSERT INTO `dic_city` VALUES ('513422', '513422', '木里藏族自治县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513423', '513423', '盐源县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513424', '513424', '德昌县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513425', '513425', '会理县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513426', '513426', '会东县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513427', '513427', '宁南县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513428', '513428', '普格县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513429', '513429', '布拖县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513430', '513430', '金阳县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513431', '513431', '昭觉县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513432', '513432', '喜德县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513433', '513433', '冕宁县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513434', '513434', '越西县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513435', '513435', '甘洛县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513436', '513436', '美姑县', '5134', 3); +INSERT INTO `dic_city` VALUES ('513437', '513437', '雷波县', '5134', 3); +INSERT INTO `dic_city` VALUES ('52', '52', '贵州省', NULL, 1); +INSERT INTO `dic_city` VALUES ('5201', '5201', '贵阳市', '52', 2); +INSERT INTO `dic_city` VALUES ('520102', '520102', '南明区', '5201', 3); +INSERT INTO `dic_city` VALUES ('520103', '520103', '云岩区', '5201', 3); +INSERT INTO `dic_city` VALUES ('520111', '520111', '花溪区', '5201', 3); +INSERT INTO `dic_city` VALUES ('520112', '520112', '乌当区', '5201', 3); +INSERT INTO `dic_city` VALUES ('520113', '520113', '白云区', '5201', 3); +INSERT INTO `dic_city` VALUES ('520115', '520115', '观山湖区', '5201', 3); +INSERT INTO `dic_city` VALUES ('520121', '520121', '开阳县', '5201', 3); +INSERT INTO `dic_city` VALUES ('520122', '520122', '息烽县', '5201', 3); +INSERT INTO `dic_city` VALUES ('520123', '520123', '修文县', '5201', 3); +INSERT INTO `dic_city` VALUES ('520181', '520181', '清镇市', '5201', 3); +INSERT INTO `dic_city` VALUES ('5202', '5202', '六盘水市', '52', 2); +INSERT INTO `dic_city` VALUES ('520201', '520201', '钟山区', '5202', 3); +INSERT INTO `dic_city` VALUES ('520203', '520203', '六枝特区', '5202', 3); +INSERT INTO `dic_city` VALUES ('520221', '520221', '水城县', '5202', 3); +INSERT INTO `dic_city` VALUES ('520281', '520281', '盘州市', '5202', 3); +INSERT INTO `dic_city` VALUES ('5203', '5203', '遵义市', '52', 2); +INSERT INTO `dic_city` VALUES ('520302', '520302', '红花岗区', '5203', 3); +INSERT INTO `dic_city` VALUES ('520303', '520303', '汇川区', '5203', 3); +INSERT INTO `dic_city` VALUES ('520304', '520304', '播州区', '5203', 3); +INSERT INTO `dic_city` VALUES ('520322', '520322', '桐梓县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520323', '520323', '绥阳县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520324', '520324', '正安县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520325', '520325', '道真仡佬族苗族自治县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520326', '520326', '务川仡佬族苗族自治县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520327', '520327', '凤冈县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520328', '520328', '湄潭县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520329', '520329', '余庆县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520330', '520330', '习水县', '5203', 3); +INSERT INTO `dic_city` VALUES ('520381', '520381', '赤水市', '5203', 3); +INSERT INTO `dic_city` VALUES ('520382', '520382', '仁怀市', '5203', 3); +INSERT INTO `dic_city` VALUES ('5204', '5204', '安顺市', '52', 2); +INSERT INTO `dic_city` VALUES ('520402', '520402', '西秀区', '5204', 3); +INSERT INTO `dic_city` VALUES ('520403', '520403', '平坝区', '5204', 3); +INSERT INTO `dic_city` VALUES ('520422', '520422', '普定县', '5204', 3); +INSERT INTO `dic_city` VALUES ('520423', '520423', '镇宁布依族苗族自治县', '5204', 3); +INSERT INTO `dic_city` VALUES ('520424', '520424', '关岭布依族苗族自治县', '5204', 3); +INSERT INTO `dic_city` VALUES ('520425', '520425', '紫云苗族布依族自治县', '5204', 3); +INSERT INTO `dic_city` VALUES ('5205', '5205', '毕节市', '52', 2); +INSERT INTO `dic_city` VALUES ('520502', '520502', '七星关区', '5205', 3); +INSERT INTO `dic_city` VALUES ('520521', '520521', '大方县', '5205', 3); +INSERT INTO `dic_city` VALUES ('520522', '520522', '黔西县', '5205', 3); +INSERT INTO `dic_city` VALUES ('520523', '520523', '金沙县', '5205', 3); +INSERT INTO `dic_city` VALUES ('520524', '520524', '织金县', '5205', 3); +INSERT INTO `dic_city` VALUES ('520525', '520525', '纳雍县', '5205', 3); +INSERT INTO `dic_city` VALUES ('520526', '520526', '威宁彝族回族苗族自治县', '5205', 3); +INSERT INTO `dic_city` VALUES ('520527', '520527', '赫章县', '5205', 3); +INSERT INTO `dic_city` VALUES ('5206', '5206', '铜仁市', '52', 2); +INSERT INTO `dic_city` VALUES ('520602', '520602', '碧江区', '5206', 3); +INSERT INTO `dic_city` VALUES ('520603', '520603', '万山区', '5206', 3); +INSERT INTO `dic_city` VALUES ('520621', '520621', '江口县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520622', '520622', '玉屏侗族自治县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520623', '520623', '石阡县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520624', '520624', '思南县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520625', '520625', '印江土家族苗族自治县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520626', '520626', '德江县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520627', '520627', '沿河土家族自治县', '5206', 3); +INSERT INTO `dic_city` VALUES ('520628', '520628', '松桃苗族自治县', '5206', 3); +INSERT INTO `dic_city` VALUES ('5223', '5223', '黔西南布依族苗族自治州', '52', 2); +INSERT INTO `dic_city` VALUES ('522301', '522301', '兴义市', '5223', 3); +INSERT INTO `dic_city` VALUES ('522302', '522302', '兴仁市', '5223', 3); +INSERT INTO `dic_city` VALUES ('522323', '522323', '普安县', '5223', 3); +INSERT INTO `dic_city` VALUES ('522324', '522324', '晴隆县', '5223', 3); +INSERT INTO `dic_city` VALUES ('522325', '522325', '贞丰县', '5223', 3); +INSERT INTO `dic_city` VALUES ('522326', '522326', '望谟县', '5223', 3); +INSERT INTO `dic_city` VALUES ('522327', '522327', '册亨县', '5223', 3); +INSERT INTO `dic_city` VALUES ('522328', '522328', '安龙县', '5223', 3); +INSERT INTO `dic_city` VALUES ('5226', '5226', '黔东南苗族侗族自治州', '52', 2); +INSERT INTO `dic_city` VALUES ('522601', '522601', '凯里市', '5226', 3); +INSERT INTO `dic_city` VALUES ('522622', '522622', '黄平县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522623', '522623', '施秉县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522624', '522624', '三穗县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522625', '522625', '镇远县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522626', '522626', '岑巩县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522627', '522627', '天柱县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522628', '522628', '锦屏县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522629', '522629', '剑河县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522630', '522630', '台江县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522631', '522631', '黎平县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522632', '522632', '榕江县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522633', '522633', '从江县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522634', '522634', '雷山县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522635', '522635', '麻江县', '5226', 3); +INSERT INTO `dic_city` VALUES ('522636', '522636', '丹寨县', '5226', 3); +INSERT INTO `dic_city` VALUES ('5227', '5227', '黔南布依族苗族自治州', '52', 2); +INSERT INTO `dic_city` VALUES ('522701', '522701', '都匀市', '5227', 3); +INSERT INTO `dic_city` VALUES ('522702', '522702', '福泉市', '5227', 3); +INSERT INTO `dic_city` VALUES ('522722', '522722', '荔波县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522723', '522723', '贵定县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522725', '522725', '瓮安县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522726', '522726', '独山县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522727', '522727', '平塘县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522728', '522728', '罗甸县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522729', '522729', '长顺县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522730', '522730', '龙里县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522731', '522731', '惠水县', '5227', 3); +INSERT INTO `dic_city` VALUES ('522732', '522732', '三都水族自治县', '5227', 3); +INSERT INTO `dic_city` VALUES ('53', '53', '云南省', NULL, 1); +INSERT INTO `dic_city` VALUES ('5301', '5301', '昆明市', '53', 2); +INSERT INTO `dic_city` VALUES ('530102', '530102', '五华区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530103', '530103', '盘龙区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530111', '530111', '官渡区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530112', '530112', '西山区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530113', '530113', '东川区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530114', '530114', '呈贡区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530115', '530115', '晋宁区', '5301', 3); +INSERT INTO `dic_city` VALUES ('530124', '530124', '富民县', '5301', 3); +INSERT INTO `dic_city` VALUES ('530125', '530125', '宜良县', '5301', 3); +INSERT INTO `dic_city` VALUES ('530126', '530126', '石林彝族自治县', '5301', 3); +INSERT INTO `dic_city` VALUES ('530127', '530127', '嵩明县', '5301', 3); +INSERT INTO `dic_city` VALUES ('530128', '530128', '禄劝彝族苗族自治县', '5301', 3); +INSERT INTO `dic_city` VALUES ('530129', '530129', '寻甸回族彝族自治县', '5301', 3); +INSERT INTO `dic_city` VALUES ('530181', '530181', '安宁市', '5301', 3); +INSERT INTO `dic_city` VALUES ('5303', '5303', '曲靖市', '53', 2); +INSERT INTO `dic_city` VALUES ('530302', '530302', '麒麟区', '5303', 3); +INSERT INTO `dic_city` VALUES ('530303', '530303', '沾益区', '5303', 3); +INSERT INTO `dic_city` VALUES ('530304', '530304', '马龙区', '5303', 3); +INSERT INTO `dic_city` VALUES ('530322', '530322', '陆良县', '5303', 3); +INSERT INTO `dic_city` VALUES ('530323', '530323', '师宗县', '5303', 3); +INSERT INTO `dic_city` VALUES ('530324', '530324', '罗平县', '5303', 3); +INSERT INTO `dic_city` VALUES ('530325', '530325', '富源县', '5303', 3); +INSERT INTO `dic_city` VALUES ('530326', '530326', '会泽县', '5303', 3); +INSERT INTO `dic_city` VALUES ('530381', '530381', '宣威市', '5303', 3); +INSERT INTO `dic_city` VALUES ('5304', '5304', '玉溪市', '53', 2); +INSERT INTO `dic_city` VALUES ('530402', '530402', '红塔区', '5304', 3); +INSERT INTO `dic_city` VALUES ('530403', '530403', '江川区', '5304', 3); +INSERT INTO `dic_city` VALUES ('530423', '530423', '通海县', '5304', 3); +INSERT INTO `dic_city` VALUES ('530424', '530424', '华宁县', '5304', 3); +INSERT INTO `dic_city` VALUES ('530425', '530425', '易门县', '5304', 3); +INSERT INTO `dic_city` VALUES ('530426', '530426', '峨山彝族自治县', '5304', 3); +INSERT INTO `dic_city` VALUES ('530427', '530427', '新平彝族傣族自治县', '5304', 3); +INSERT INTO `dic_city` VALUES ('530428', '530428', '元江哈尼族彝族傣族自治县', '5304', 3); +INSERT INTO `dic_city` VALUES ('530481', '530481', '澄江市', '5304', 3); +INSERT INTO `dic_city` VALUES ('5305', '5305', '保山市', '53', 2); +INSERT INTO `dic_city` VALUES ('530502', '530502', '隆阳区', '5305', 3); +INSERT INTO `dic_city` VALUES ('530521', '530521', '施甸县', '5305', 3); +INSERT INTO `dic_city` VALUES ('530523', '530523', '龙陵县', '5305', 3); +INSERT INTO `dic_city` VALUES ('530524', '530524', '昌宁县', '5305', 3); +INSERT INTO `dic_city` VALUES ('530581', '530581', '腾冲市', '5305', 3); +INSERT INTO `dic_city` VALUES ('5306', '5306', '昭通市', '53', 2); +INSERT INTO `dic_city` VALUES ('530602', '530602', '昭阳区', '5306', 3); +INSERT INTO `dic_city` VALUES ('530621', '530621', '鲁甸县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530622', '530622', '巧家县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530623', '530623', '盐津县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530624', '530624', '大关县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530625', '530625', '永善县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530626', '530626', '绥江县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530627', '530627', '镇雄县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530628', '530628', '彝良县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530629', '530629', '威信县', '5306', 3); +INSERT INTO `dic_city` VALUES ('530681', '530681', '水富市', '5306', 3); +INSERT INTO `dic_city` VALUES ('5307', '5307', '丽江市', '53', 2); +INSERT INTO `dic_city` VALUES ('530702', '530702', '古城区', '5307', 3); +INSERT INTO `dic_city` VALUES ('530721', '530721', '玉龙纳西族自治县', '5307', 3); +INSERT INTO `dic_city` VALUES ('530722', '530722', '永胜县', '5307', 3); +INSERT INTO `dic_city` VALUES ('530723', '530723', '华坪县', '5307', 3); +INSERT INTO `dic_city` VALUES ('530724', '530724', '宁蒗彝族自治县', '5307', 3); +INSERT INTO `dic_city` VALUES ('5308', '5308', '普洱市', '53', 2); +INSERT INTO `dic_city` VALUES ('530802', '530802', '思茅区', '5308', 3); +INSERT INTO `dic_city` VALUES ('530821', '530821', '宁洱哈尼族彝族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530822', '530822', '墨江哈尼族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530823', '530823', '景东彝族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530824', '530824', '景谷傣族彝族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530825', '530825', '镇沅彝族哈尼族拉祜族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530826', '530826', '江城哈尼族彝族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530827', '530827', '孟连傣族拉祜族佤族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530828', '530828', '澜沧拉祜族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('530829', '530829', '西盟佤族自治县', '5308', 3); +INSERT INTO `dic_city` VALUES ('5309', '5309', '临沧市', '53', 2); +INSERT INTO `dic_city` VALUES ('530902', '530902', '临翔区', '5309', 3); +INSERT INTO `dic_city` VALUES ('530921', '530921', '凤庆县', '5309', 3); +INSERT INTO `dic_city` VALUES ('530922', '530922', '云县', '5309', 3); +INSERT INTO `dic_city` VALUES ('530923', '530923', '永德县', '5309', 3); +INSERT INTO `dic_city` VALUES ('530924', '530924', '镇康县', '5309', 3); +INSERT INTO `dic_city` VALUES ('530925', '530925', '双江拉祜族佤族布朗族傣族自治县', '5309', 3); +INSERT INTO `dic_city` VALUES ('530926', '530926', '耿马傣族佤族自治县', '5309', 3); +INSERT INTO `dic_city` VALUES ('530927', '530927', '沧源佤族自治县', '5309', 3); +INSERT INTO `dic_city` VALUES ('5323', '5323', '楚雄彝族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('532301', '532301', '楚雄市', '5323', 3); +INSERT INTO `dic_city` VALUES ('532322', '532322', '双柏县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532323', '532323', '牟定县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532324', '532324', '南华县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532325', '532325', '姚安县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532326', '532326', '大姚县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532327', '532327', '永仁县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532328', '532328', '元谋县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532329', '532329', '武定县', '5323', 3); +INSERT INTO `dic_city` VALUES ('532331', '532331', '禄丰县', '5323', 3); +INSERT INTO `dic_city` VALUES ('5325', '5325', '红河哈尼族彝族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('532501', '532501', '个旧市', '5325', 3); +INSERT INTO `dic_city` VALUES ('532502', '532502', '开远市', '5325', 3); +INSERT INTO `dic_city` VALUES ('532503', '532503', '蒙自市', '5325', 3); +INSERT INTO `dic_city` VALUES ('532504', '532504', '弥勒市', '5325', 3); +INSERT INTO `dic_city` VALUES ('532523', '532523', '屏边苗族自治县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532524', '532524', '建水县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532525', '532525', '石屏县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532527', '532527', '泸西县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532528', '532528', '元阳县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532529', '532529', '红河县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532530', '532530', '金平苗族瑶族傣族自治县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532531', '532531', '绿春县', '5325', 3); +INSERT INTO `dic_city` VALUES ('532532', '532532', '河口瑶族自治县', '5325', 3); +INSERT INTO `dic_city` VALUES ('5326', '5326', '文山壮族苗族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('532601', '532601', '文山市', '5326', 3); +INSERT INTO `dic_city` VALUES ('532622', '532622', '砚山县', '5326', 3); +INSERT INTO `dic_city` VALUES ('532623', '532623', '西畴县', '5326', 3); +INSERT INTO `dic_city` VALUES ('532624', '532624', '麻栗坡县', '5326', 3); +INSERT INTO `dic_city` VALUES ('532625', '532625', '马关县', '5326', 3); +INSERT INTO `dic_city` VALUES ('532626', '532626', '丘北县', '5326', 3); +INSERT INTO `dic_city` VALUES ('532627', '532627', '广南县', '5326', 3); +INSERT INTO `dic_city` VALUES ('532628', '532628', '富宁县', '5326', 3); +INSERT INTO `dic_city` VALUES ('5328', '5328', '西双版纳傣族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('532801', '532801', '景洪市', '5328', 3); +INSERT INTO `dic_city` VALUES ('532822', '532822', '勐海县', '5328', 3); +INSERT INTO `dic_city` VALUES ('532823', '532823', '勐腊县', '5328', 3); +INSERT INTO `dic_city` VALUES ('5329', '5329', '大理白族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('532901', '532901', '大理市', '5329', 3); +INSERT INTO `dic_city` VALUES ('532922', '532922', '漾濞彝族自治县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532923', '532923', '祥云县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532924', '532924', '宾川县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532925', '532925', '弥渡县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532926', '532926', '南涧彝族自治县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532927', '532927', '巍山彝族回族自治县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532928', '532928', '永平县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532929', '532929', '云龙县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532930', '532930', '洱源县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532931', '532931', '剑川县', '5329', 3); +INSERT INTO `dic_city` VALUES ('532932', '532932', '鹤庆县', '5329', 3); +INSERT INTO `dic_city` VALUES ('5331', '5331', '德宏傣族景颇族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('533102', '533102', '瑞丽市', '5331', 3); +INSERT INTO `dic_city` VALUES ('533103', '533103', '芒市', '5331', 3); +INSERT INTO `dic_city` VALUES ('533122', '533122', '梁河县', '5331', 3); +INSERT INTO `dic_city` VALUES ('533123', '533123', '盈江县', '5331', 3); +INSERT INTO `dic_city` VALUES ('533124', '533124', '陇川县', '5331', 3); +INSERT INTO `dic_city` VALUES ('5333', '5333', '怒江傈僳族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('533301', '533301', '泸水市', '5333', 3); +INSERT INTO `dic_city` VALUES ('533323', '533323', '福贡县', '5333', 3); +INSERT INTO `dic_city` VALUES ('533324', '533324', '贡山独龙族怒族自治县', '5333', 3); +INSERT INTO `dic_city` VALUES ('533325', '533325', '兰坪白族普米族自治县', '5333', 3); +INSERT INTO `dic_city` VALUES ('5334', '5334', '迪庆藏族自治州', '53', 2); +INSERT INTO `dic_city` VALUES ('533401', '533401', '香格里拉市', '5334', 3); +INSERT INTO `dic_city` VALUES ('533422', '533422', '德钦县', '5334', 3); +INSERT INTO `dic_city` VALUES ('533423', '533423', '维西傈僳族自治县', '5334', 3); +INSERT INTO `dic_city` VALUES ('54', '54', '西藏自治区', NULL, 1); +INSERT INTO `dic_city` VALUES ('5401', '5401', '拉萨市', '54', 2); +INSERT INTO `dic_city` VALUES ('540102', '540102', '城关区', '5401', 3); +INSERT INTO `dic_city` VALUES ('540103', '540103', '堆龙德庆区', '5401', 3); +INSERT INTO `dic_city` VALUES ('540104', '540104', '达孜区', '5401', 3); +INSERT INTO `dic_city` VALUES ('540121', '540121', '林周县', '5401', 3); +INSERT INTO `dic_city` VALUES ('540122', '540122', '当雄县', '5401', 3); +INSERT INTO `dic_city` VALUES ('540123', '540123', '尼木县', '5401', 3); +INSERT INTO `dic_city` VALUES ('540124', '540124', '曲水县', '5401', 3); +INSERT INTO `dic_city` VALUES ('540127', '540127', '墨竹工卡县', '5401', 3); +INSERT INTO `dic_city` VALUES ('540171', '540171', '格尔木藏青工业园区', '5401', 3); +INSERT INTO `dic_city` VALUES ('540172', '540172', '拉萨经济技术开发区', '5401', 3); +INSERT INTO `dic_city` VALUES ('540173', '540173', '西藏文化旅游创意园区', '5401', 3); +INSERT INTO `dic_city` VALUES ('540174', '540174', '达孜工业园区', '5401', 3); +INSERT INTO `dic_city` VALUES ('5402', '5402', '日喀则市', '54', 2); +INSERT INTO `dic_city` VALUES ('540202', '540202', '桑珠孜区', '5402', 3); +INSERT INTO `dic_city` VALUES ('540221', '540221', '南木林县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540222', '540222', '江孜县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540223', '540223', '定日县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540224', '540224', '萨迦县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540225', '540225', '拉孜县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540226', '540226', '昂仁县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540227', '540227', '谢通门县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540228', '540228', '白朗县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540229', '540229', '仁布县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540230', '540230', '康马县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540231', '540231', '定结县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540232', '540232', '仲巴县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540233', '540233', '亚东县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540234', '540234', '吉隆县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540235', '540235', '聂拉木县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540236', '540236', '萨嘎县', '5402', 3); +INSERT INTO `dic_city` VALUES ('540237', '540237', '岗巴县', '5402', 3); +INSERT INTO `dic_city` VALUES ('5403', '5403', '昌都市', '54', 2); +INSERT INTO `dic_city` VALUES ('540302', '540302', '卡若区', '5403', 3); +INSERT INTO `dic_city` VALUES ('540321', '540321', '江达县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540322', '540322', '贡觉县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540323', '540323', '类乌齐县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540324', '540324', '丁青县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540325', '540325', '察雅县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540326', '540326', '八宿县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540327', '540327', '左贡县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540328', '540328', '芒康县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540329', '540329', '洛隆县', '5403', 3); +INSERT INTO `dic_city` VALUES ('540330', '540330', '边坝县', '5403', 3); +INSERT INTO `dic_city` VALUES ('5404', '5404', '林芝市', '54', 2); +INSERT INTO `dic_city` VALUES ('540402', '540402', '巴宜区', '5404', 3); +INSERT INTO `dic_city` VALUES ('540421', '540421', '工布江达县', '5404', 3); +INSERT INTO `dic_city` VALUES ('540422', '540422', '米林县', '5404', 3); +INSERT INTO `dic_city` VALUES ('540423', '540423', '墨脱县', '5404', 3); +INSERT INTO `dic_city` VALUES ('540424', '540424', '波密县', '5404', 3); +INSERT INTO `dic_city` VALUES ('540425', '540425', '察隅县', '5404', 3); +INSERT INTO `dic_city` VALUES ('540426', '540426', '朗县', '5404', 3); +INSERT INTO `dic_city` VALUES ('5405', '5405', '山南市', '54', 2); +INSERT INTO `dic_city` VALUES ('540502', '540502', '乃东区', '5405', 3); +INSERT INTO `dic_city` VALUES ('540521', '540521', '扎囊县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540522', '540522', '贡嘎县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540523', '540523', '桑日县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540524', '540524', '琼结县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540525', '540525', '曲松县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540526', '540526', '措美县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540527', '540527', '洛扎县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540528', '540528', '加查县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540529', '540529', '隆子县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540530', '540530', '错那县', '5405', 3); +INSERT INTO `dic_city` VALUES ('540531', '540531', '浪卡子县', '5405', 3); +INSERT INTO `dic_city` VALUES ('5406', '5406', '那曲市', '54', 2); +INSERT INTO `dic_city` VALUES ('540602', '540602', '色尼区', '5406', 3); +INSERT INTO `dic_city` VALUES ('540621', '540621', '嘉黎县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540622', '540622', '比如县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540623', '540623', '聂荣县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540624', '540624', '安多县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540625', '540625', '申扎县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540626', '540626', '索县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540627', '540627', '班戈县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540628', '540628', '巴青县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540629', '540629', '尼玛县', '5406', 3); +INSERT INTO `dic_city` VALUES ('540630', '540630', '双湖县', '5406', 3); +INSERT INTO `dic_city` VALUES ('5425', '5425', '阿里地区', '54', 2); +INSERT INTO `dic_city` VALUES ('542521', '542521', '普兰县', '5425', 3); +INSERT INTO `dic_city` VALUES ('542522', '542522', '札达县', '5425', 3); +INSERT INTO `dic_city` VALUES ('542523', '542523', '噶尔县', '5425', 3); +INSERT INTO `dic_city` VALUES ('542524', '542524', '日土县', '5425', 3); +INSERT INTO `dic_city` VALUES ('542525', '542525', '革吉县', '5425', 3); +INSERT INTO `dic_city` VALUES ('542526', '542526', '改则县', '5425', 3); +INSERT INTO `dic_city` VALUES ('542527', '542527', '措勤县', '5425', 3); +INSERT INTO `dic_city` VALUES ('61', '61', '陕西省', NULL, 1); +INSERT INTO `dic_city` VALUES ('6101', '6101', '西安市', '61', 2); +INSERT INTO `dic_city` VALUES ('610102', '610102', '新城区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610103', '610103', '碑林区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610104', '610104', '莲湖区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610111', '610111', '灞桥区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610112', '610112', '未央区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610113', '610113', '雁塔区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610114', '610114', '阎良区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610115', '610115', '临潼区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610116', '610116', '长安区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610117', '610117', '高陵区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610118', '610118', '鄠邑区', '6101', 3); +INSERT INTO `dic_city` VALUES ('610122', '610122', '蓝田县', '6101', 3); +INSERT INTO `dic_city` VALUES ('610124', '610124', '周至县', '6101', 3); +INSERT INTO `dic_city` VALUES ('6102', '6102', '铜川市', '61', 2); +INSERT INTO `dic_city` VALUES ('610202', '610202', '王益区', '6102', 3); +INSERT INTO `dic_city` VALUES ('610203', '610203', '印台区', '6102', 3); +INSERT INTO `dic_city` VALUES ('610204', '610204', '耀州区', '6102', 3); +INSERT INTO `dic_city` VALUES ('610222', '610222', '宜君县', '6102', 3); +INSERT INTO `dic_city` VALUES ('6103', '6103', '宝鸡市', '61', 2); +INSERT INTO `dic_city` VALUES ('610302', '610302', '渭滨区', '6103', 3); +INSERT INTO `dic_city` VALUES ('610303', '610303', '金台区', '6103', 3); +INSERT INTO `dic_city` VALUES ('610304', '610304', '陈仓区', '6103', 3); +INSERT INTO `dic_city` VALUES ('610322', '610322', '凤翔县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610323', '610323', '岐山县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610324', '610324', '扶风县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610326', '610326', '眉县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610327', '610327', '陇县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610328', '610328', '千阳县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610329', '610329', '麟游县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610330', '610330', '凤县', '6103', 3); +INSERT INTO `dic_city` VALUES ('610331', '610331', '太白县', '6103', 3); +INSERT INTO `dic_city` VALUES ('6104', '6104', '咸阳市', '61', 2); +INSERT INTO `dic_city` VALUES ('610402', '610402', '秦都区', '6104', 3); +INSERT INTO `dic_city` VALUES ('610403', '610403', '杨陵区', '6104', 3); +INSERT INTO `dic_city` VALUES ('610404', '610404', '渭城区', '6104', 3); +INSERT INTO `dic_city` VALUES ('610422', '610422', '三原县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610423', '610423', '泾阳县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610424', '610424', '乾县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610425', '610425', '礼泉县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610426', '610426', '永寿县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610428', '610428', '长武县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610429', '610429', '旬邑县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610430', '610430', '淳化县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610431', '610431', '武功县', '6104', 3); +INSERT INTO `dic_city` VALUES ('610481', '610481', '兴平市', '6104', 3); +INSERT INTO `dic_city` VALUES ('610482', '610482', '彬州市', '6104', 3); +INSERT INTO `dic_city` VALUES ('6105', '6105', '渭南市', '61', 2); +INSERT INTO `dic_city` VALUES ('610502', '610502', '临渭区', '6105', 3); +INSERT INTO `dic_city` VALUES ('610503', '610503', '华州区', '6105', 3); +INSERT INTO `dic_city` VALUES ('610522', '610522', '潼关县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610523', '610523', '大荔县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610524', '610524', '合阳县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610525', '610525', '澄城县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610526', '610526', '蒲城县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610527', '610527', '白水县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610528', '610528', '富平县', '6105', 3); +INSERT INTO `dic_city` VALUES ('610581', '610581', '韩城市', '6105', 3); +INSERT INTO `dic_city` VALUES ('610582', '610582', '华阴市', '6105', 3); +INSERT INTO `dic_city` VALUES ('6106', '6106', '延安市', '61', 2); +INSERT INTO `dic_city` VALUES ('610602', '610602', '宝塔区', '6106', 3); +INSERT INTO `dic_city` VALUES ('610603', '610603', '安塞区', '6106', 3); +INSERT INTO `dic_city` VALUES ('610621', '610621', '延长县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610622', '610622', '延川县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610625', '610625', '志丹县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610626', '610626', '吴起县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610627', '610627', '甘泉县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610628', '610628', '富县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610629', '610629', '洛川县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610630', '610630', '宜川县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610631', '610631', '黄龙县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610632', '610632', '黄陵县', '6106', 3); +INSERT INTO `dic_city` VALUES ('610681', '610681', '子长市', '6106', 3); +INSERT INTO `dic_city` VALUES ('6107', '6107', '汉中市', '61', 2); +INSERT INTO `dic_city` VALUES ('610702', '610702', '汉台区', '6107', 3); +INSERT INTO `dic_city` VALUES ('610703', '610703', '南郑区', '6107', 3); +INSERT INTO `dic_city` VALUES ('610722', '610722', '城固县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610723', '610723', '洋县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610724', '610724', '西乡县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610725', '610725', '勉县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610726', '610726', '宁强县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610727', '610727', '略阳县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610728', '610728', '镇巴县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610729', '610729', '留坝县', '6107', 3); +INSERT INTO `dic_city` VALUES ('610730', '610730', '佛坪县', '6107', 3); +INSERT INTO `dic_city` VALUES ('6108', '6108', '榆林市', '61', 2); +INSERT INTO `dic_city` VALUES ('610802', '610802', '榆阳区', '6108', 3); +INSERT INTO `dic_city` VALUES ('610803', '610803', '横山区', '6108', 3); +INSERT INTO `dic_city` VALUES ('610822', '610822', '府谷县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610824', '610824', '靖边县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610825', '610825', '定边县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610826', '610826', '绥德县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610827', '610827', '米脂县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610828', '610828', '佳县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610829', '610829', '吴堡县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610830', '610830', '清涧县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610831', '610831', '子洲县', '6108', 3); +INSERT INTO `dic_city` VALUES ('610881', '610881', '神木市', '6108', 3); +INSERT INTO `dic_city` VALUES ('6109', '6109', '安康市', '61', 2); +INSERT INTO `dic_city` VALUES ('610902', '610902', '汉滨区', '6109', 3); +INSERT INTO `dic_city` VALUES ('610921', '610921', '汉阴县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610922', '610922', '石泉县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610923', '610923', '宁陕县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610924', '610924', '紫阳县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610925', '610925', '岚皋县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610926', '610926', '平利县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610927', '610927', '镇坪县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610928', '610928', '旬阳县', '6109', 3); +INSERT INTO `dic_city` VALUES ('610929', '610929', '白河县', '6109', 3); +INSERT INTO `dic_city` VALUES ('6110', '6110', '商洛市', '61', 2); +INSERT INTO `dic_city` VALUES ('611002', '611002', '商州区', '6110', 3); +INSERT INTO `dic_city` VALUES ('611021', '611021', '洛南县', '6110', 3); +INSERT INTO `dic_city` VALUES ('611022', '611022', '丹凤县', '6110', 3); +INSERT INTO `dic_city` VALUES ('611023', '611023', '商南县', '6110', 3); +INSERT INTO `dic_city` VALUES ('611024', '611024', '山阳县', '6110', 3); +INSERT INTO `dic_city` VALUES ('611025', '611025', '镇安县', '6110', 3); +INSERT INTO `dic_city` VALUES ('611026', '611026', '柞水县', '6110', 3); +INSERT INTO `dic_city` VALUES ('62', '62', '甘肃省', NULL, 1); +INSERT INTO `dic_city` VALUES ('6201', '6201', '兰州市', '62', 2); +INSERT INTO `dic_city` VALUES ('620102', '620102', '城关区', '6201', 3); +INSERT INTO `dic_city` VALUES ('620103', '620103', '七里河区', '6201', 3); +INSERT INTO `dic_city` VALUES ('620104', '620104', '西固区', '6201', 3); +INSERT INTO `dic_city` VALUES ('620105', '620105', '安宁区', '6201', 3); +INSERT INTO `dic_city` VALUES ('620111', '620111', '红古区', '6201', 3); +INSERT INTO `dic_city` VALUES ('620121', '620121', '永登县', '6201', 3); +INSERT INTO `dic_city` VALUES ('620122', '620122', '皋兰县', '6201', 3); +INSERT INTO `dic_city` VALUES ('620123', '620123', '榆中县', '6201', 3); +INSERT INTO `dic_city` VALUES ('620171', '620171', '兰州新区', '6201', 3); +INSERT INTO `dic_city` VALUES ('6202', '6202', '嘉峪关市', '62', 2); +INSERT INTO `dic_city` VALUES ('620201001', '620201001', '雄关街道', '6202', 3); +INSERT INTO `dic_city` VALUES ('620201002', '620201002', '钢城街道', '6202', 3); +INSERT INTO `dic_city` VALUES ('620201100', '620201100', '新城镇', '6202', 3); +INSERT INTO `dic_city` VALUES ('620201101', '620201101', '峪泉镇', '6202', 3); +INSERT INTO `dic_city` VALUES ('620201102', '620201102', '文殊镇', '6202', 3); +INSERT INTO `dic_city` VALUES ('6203', '6203', '金昌市', '62', 2); +INSERT INTO `dic_city` VALUES ('620302', '620302', '金川区', '6203', 3); +INSERT INTO `dic_city` VALUES ('620321', '620321', '永昌县', '6203', 3); +INSERT INTO `dic_city` VALUES ('6204', '6204', '白银市', '62', 2); +INSERT INTO `dic_city` VALUES ('620402', '620402', '白银区', '6204', 3); +INSERT INTO `dic_city` VALUES ('620403', '620403', '平川区', '6204', 3); +INSERT INTO `dic_city` VALUES ('620421', '620421', '靖远县', '6204', 3); +INSERT INTO `dic_city` VALUES ('620422', '620422', '会宁县', '6204', 3); +INSERT INTO `dic_city` VALUES ('620423', '620423', '景泰县', '6204', 3); +INSERT INTO `dic_city` VALUES ('6205', '6205', '天水市', '62', 2); +INSERT INTO `dic_city` VALUES ('620502', '620502', '秦州区', '6205', 3); +INSERT INTO `dic_city` VALUES ('620503', '620503', '麦积区', '6205', 3); +INSERT INTO `dic_city` VALUES ('620521', '620521', '清水县', '6205', 3); +INSERT INTO `dic_city` VALUES ('620522', '620522', '秦安县', '6205', 3); +INSERT INTO `dic_city` VALUES ('620523', '620523', '甘谷县', '6205', 3); +INSERT INTO `dic_city` VALUES ('620524', '620524', '武山县', '6205', 3); +INSERT INTO `dic_city` VALUES ('620525', '620525', '张家川回族自治县', '6205', 3); +INSERT INTO `dic_city` VALUES ('6206', '6206', '武威市', '62', 2); +INSERT INTO `dic_city` VALUES ('620602', '620602', '凉州区', '6206', 3); +INSERT INTO `dic_city` VALUES ('620621', '620621', '民勤县', '6206', 3); +INSERT INTO `dic_city` VALUES ('620622', '620622', '古浪县', '6206', 3); +INSERT INTO `dic_city` VALUES ('620623', '620623', '天祝藏族自治县', '6206', 3); +INSERT INTO `dic_city` VALUES ('6207', '6207', '张掖市', '62', 2); +INSERT INTO `dic_city` VALUES ('620702', '620702', '甘州区', '6207', 3); +INSERT INTO `dic_city` VALUES ('620721', '620721', '肃南裕固族自治县', '6207', 3); +INSERT INTO `dic_city` VALUES ('620722', '620722', '民乐县', '6207', 3); +INSERT INTO `dic_city` VALUES ('620723', '620723', '临泽县', '6207', 3); +INSERT INTO `dic_city` VALUES ('620724', '620724', '高台县', '6207', 3); +INSERT INTO `dic_city` VALUES ('620725', '620725', '山丹县', '6207', 3); +INSERT INTO `dic_city` VALUES ('6208', '6208', '平凉市', '62', 2); +INSERT INTO `dic_city` VALUES ('620802', '620802', '崆峒区', '6208', 3); +INSERT INTO `dic_city` VALUES ('620821', '620821', '泾川县', '6208', 3); +INSERT INTO `dic_city` VALUES ('620822', '620822', '灵台县', '6208', 3); +INSERT INTO `dic_city` VALUES ('620823', '620823', '崇信县', '6208', 3); +INSERT INTO `dic_city` VALUES ('620825', '620825', '庄浪县', '6208', 3); +INSERT INTO `dic_city` VALUES ('620826', '620826', '静宁县', '6208', 3); +INSERT INTO `dic_city` VALUES ('620881', '620881', '华亭市', '6208', 3); +INSERT INTO `dic_city` VALUES ('6209', '6209', '酒泉市', '62', 2); +INSERT INTO `dic_city` VALUES ('620902', '620902', '肃州区', '6209', 3); +INSERT INTO `dic_city` VALUES ('620921', '620921', '金塔县', '6209', 3); +INSERT INTO `dic_city` VALUES ('620922', '620922', '瓜州县', '6209', 3); +INSERT INTO `dic_city` VALUES ('620923', '620923', '肃北蒙古族自治县', '6209', 3); +INSERT INTO `dic_city` VALUES ('620924', '620924', '阿克塞哈萨克族自治县', '6209', 3); +INSERT INTO `dic_city` VALUES ('620981', '620981', '玉门市', '6209', 3); +INSERT INTO `dic_city` VALUES ('620982', '620982', '敦煌市', '6209', 3); +INSERT INTO `dic_city` VALUES ('6210', '6210', '庆阳市', '62', 2); +INSERT INTO `dic_city` VALUES ('621002', '621002', '西峰区', '6210', 3); +INSERT INTO `dic_city` VALUES ('621021', '621021', '庆城县', '6210', 3); +INSERT INTO `dic_city` VALUES ('621022', '621022', '环县', '6210', 3); +INSERT INTO `dic_city` VALUES ('621023', '621023', '华池县', '6210', 3); +INSERT INTO `dic_city` VALUES ('621024', '621024', '合水县', '6210', 3); +INSERT INTO `dic_city` VALUES ('621025', '621025', '正宁县', '6210', 3); +INSERT INTO `dic_city` VALUES ('621026', '621026', '宁县', '6210', 3); +INSERT INTO `dic_city` VALUES ('621027', '621027', '镇原县', '6210', 3); +INSERT INTO `dic_city` VALUES ('6211', '6211', '定西市', '62', 2); +INSERT INTO `dic_city` VALUES ('621102', '621102', '安定区', '6211', 3); +INSERT INTO `dic_city` VALUES ('621121', '621121', '通渭县', '6211', 3); +INSERT INTO `dic_city` VALUES ('621122', '621122', '陇西县', '6211', 3); +INSERT INTO `dic_city` VALUES ('621123', '621123', '渭源县', '6211', 3); +INSERT INTO `dic_city` VALUES ('621124', '621124', '临洮县', '6211', 3); +INSERT INTO `dic_city` VALUES ('621125', '621125', '漳县', '6211', 3); +INSERT INTO `dic_city` VALUES ('621126', '621126', '岷县', '6211', 3); +INSERT INTO `dic_city` VALUES ('6212', '6212', '陇南市', '62', 2); +INSERT INTO `dic_city` VALUES ('621202', '621202', '武都区', '6212', 3); +INSERT INTO `dic_city` VALUES ('621221', '621221', '成县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621222', '621222', '文县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621223', '621223', '宕昌县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621224', '621224', '康县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621225', '621225', '西和县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621226', '621226', '礼县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621227', '621227', '徽县', '6212', 3); +INSERT INTO `dic_city` VALUES ('621228', '621228', '两当县', '6212', 3); +INSERT INTO `dic_city` VALUES ('6229', '6229', '临夏回族自治州', '62', 2); +INSERT INTO `dic_city` VALUES ('622901', '622901', '临夏市', '6229', 3); +INSERT INTO `dic_city` VALUES ('622921', '622921', '临夏县', '6229', 3); +INSERT INTO `dic_city` VALUES ('622922', '622922', '康乐县', '6229', 3); +INSERT INTO `dic_city` VALUES ('622923', '622923', '永靖县', '6229', 3); +INSERT INTO `dic_city` VALUES ('622924', '622924', '广河县', '6229', 3); +INSERT INTO `dic_city` VALUES ('622925', '622925', '和政县', '6229', 3); +INSERT INTO `dic_city` VALUES ('622926', '622926', '东乡族自治县', '6229', 3); +INSERT INTO `dic_city` VALUES ('622927', '622927', '积石山保安族东乡族撒拉族自治县', '6229', 3); +INSERT INTO `dic_city` VALUES ('6230', '6230', '甘南藏族自治州', '62', 2); +INSERT INTO `dic_city` VALUES ('623001', '623001', '合作市', '6230', 3); +INSERT INTO `dic_city` VALUES ('623021', '623021', '临潭县', '6230', 3); +INSERT INTO `dic_city` VALUES ('623022', '623022', '卓尼县', '6230', 3); +INSERT INTO `dic_city` VALUES ('623023', '623023', '舟曲县', '6230', 3); +INSERT INTO `dic_city` VALUES ('623024', '623024', '迭部县', '6230', 3); +INSERT INTO `dic_city` VALUES ('623025', '623025', '玛曲县', '6230', 3); +INSERT INTO `dic_city` VALUES ('623026', '623026', '碌曲县', '6230', 3); +INSERT INTO `dic_city` VALUES ('623027', '623027', '夏河县', '6230', 3); +INSERT INTO `dic_city` VALUES ('63', '63', '青海省', NULL, 1); +INSERT INTO `dic_city` VALUES ('6301', '6301', '西宁市', '63', 2); +INSERT INTO `dic_city` VALUES ('630102', '630102', '城东区', '6301', 3); +INSERT INTO `dic_city` VALUES ('630103', '630103', '城中区', '6301', 3); +INSERT INTO `dic_city` VALUES ('630104', '630104', '城西区', '6301', 3); +INSERT INTO `dic_city` VALUES ('630105', '630105', '城北区', '6301', 3); +INSERT INTO `dic_city` VALUES ('630106', '630106', '湟中区', '6301', 3); +INSERT INTO `dic_city` VALUES ('630121', '630121', '大通回族土族自治县', '6301', 3); +INSERT INTO `dic_city` VALUES ('630123', '630123', '湟源县', '6301', 3); +INSERT INTO `dic_city` VALUES ('6302', '6302', '海东市', '63', 2); +INSERT INTO `dic_city` VALUES ('630202', '630202', '乐都区', '6302', 3); +INSERT INTO `dic_city` VALUES ('630203', '630203', '平安区', '6302', 3); +INSERT INTO `dic_city` VALUES ('630222', '630222', '民和回族土族自治县', '6302', 3); +INSERT INTO `dic_city` VALUES ('630223', '630223', '互助土族自治县', '6302', 3); +INSERT INTO `dic_city` VALUES ('630224', '630224', '化隆回族自治县', '6302', 3); +INSERT INTO `dic_city` VALUES ('630225', '630225', '循化撒拉族自治县', '6302', 3); +INSERT INTO `dic_city` VALUES ('6322', '6322', '海北藏族自治州', '63', 2); +INSERT INTO `dic_city` VALUES ('632221', '632221', '门源回族自治县', '6322', 3); +INSERT INTO `dic_city` VALUES ('632222', '632222', '祁连县', '6322', 3); +INSERT INTO `dic_city` VALUES ('632223', '632223', '海晏县', '6322', 3); +INSERT INTO `dic_city` VALUES ('632224', '632224', '刚察县', '6322', 3); +INSERT INTO `dic_city` VALUES ('6323', '6323', '黄南藏族自治州', '63', 2); +INSERT INTO `dic_city` VALUES ('632321', '632321', '同仁县', '6323', 3); +INSERT INTO `dic_city` VALUES ('632322', '632322', '尖扎县', '6323', 3); +INSERT INTO `dic_city` VALUES ('632323', '632323', '泽库县', '6323', 3); +INSERT INTO `dic_city` VALUES ('632324', '632324', '河南蒙古族自治县', '6323', 3); +INSERT INTO `dic_city` VALUES ('6325', '6325', '海南藏族自治州', '63', 2); +INSERT INTO `dic_city` VALUES ('632521', '632521', '共和县', '6325', 3); +INSERT INTO `dic_city` VALUES ('632522', '632522', '同德县', '6325', 3); +INSERT INTO `dic_city` VALUES ('632523', '632523', '贵德县', '6325', 3); +INSERT INTO `dic_city` VALUES ('632524', '632524', '兴海县', '6325', 3); +INSERT INTO `dic_city` VALUES ('632525', '632525', '贵南县', '6325', 3); +INSERT INTO `dic_city` VALUES ('6326', '6326', '果洛藏族自治州', '63', 2); +INSERT INTO `dic_city` VALUES ('632621', '632621', '玛沁县', '6326', 3); +INSERT INTO `dic_city` VALUES ('632622', '632622', '班玛县', '6326', 3); +INSERT INTO `dic_city` VALUES ('632623', '632623', '甘德县', '6326', 3); +INSERT INTO `dic_city` VALUES ('632624', '632624', '达日县', '6326', 3); +INSERT INTO `dic_city` VALUES ('632625', '632625', '久治县', '6326', 3); +INSERT INTO `dic_city` VALUES ('632626', '632626', '玛多县', '6326', 3); +INSERT INTO `dic_city` VALUES ('6327', '6327', '玉树藏族自治州', '63', 2); +INSERT INTO `dic_city` VALUES ('632701', '632701', '玉树市', '6327', 3); +INSERT INTO `dic_city` VALUES ('632722', '632722', '杂多县', '6327', 3); +INSERT INTO `dic_city` VALUES ('632723', '632723', '称多县', '6327', 3); +INSERT INTO `dic_city` VALUES ('632724', '632724', '治多县', '6327', 3); +INSERT INTO `dic_city` VALUES ('632725', '632725', '囊谦县', '6327', 3); +INSERT INTO `dic_city` VALUES ('632726', '632726', '曲麻莱县', '6327', 3); +INSERT INTO `dic_city` VALUES ('6328', '6328', '海西蒙古族藏族自治州', '63', 2); +INSERT INTO `dic_city` VALUES ('632801', '632801', '格尔木市', '6328', 3); +INSERT INTO `dic_city` VALUES ('632802', '632802', '德令哈市', '6328', 3); +INSERT INTO `dic_city` VALUES ('632803', '632803', '茫崖市', '6328', 3); +INSERT INTO `dic_city` VALUES ('632821', '632821', '乌兰县', '6328', 3); +INSERT INTO `dic_city` VALUES ('632822', '632822', '都兰县', '6328', 3); +INSERT INTO `dic_city` VALUES ('632823', '632823', '天峻县', '6328', 3); +INSERT INTO `dic_city` VALUES ('632857', '632857', '大柴旦行政委员会', '6328', 3); +INSERT INTO `dic_city` VALUES ('64', '64', '宁夏回族自治区', NULL, 1); +INSERT INTO `dic_city` VALUES ('6401', '6401', '银川市', '64', 2); +INSERT INTO `dic_city` VALUES ('640104', '640104', '兴庆区', '6401', 3); +INSERT INTO `dic_city` VALUES ('640105', '640105', '西夏区', '6401', 3); +INSERT INTO `dic_city` VALUES ('640106', '640106', '金凤区', '6401', 3); +INSERT INTO `dic_city` VALUES ('640121', '640121', '永宁县', '6401', 3); +INSERT INTO `dic_city` VALUES ('640122', '640122', '贺兰县', '6401', 3); +INSERT INTO `dic_city` VALUES ('640181', '640181', '灵武市', '6401', 3); +INSERT INTO `dic_city` VALUES ('6402', '6402', '石嘴山市', '64', 2); +INSERT INTO `dic_city` VALUES ('640202', '640202', '大武口区', '6402', 3); +INSERT INTO `dic_city` VALUES ('640205', '640205', '惠农区', '6402', 3); +INSERT INTO `dic_city` VALUES ('640221', '640221', '平罗县', '6402', 3); +INSERT INTO `dic_city` VALUES ('6403', '6403', '吴忠市', '64', 2); +INSERT INTO `dic_city` VALUES ('640302', '640302', '利通区', '6403', 3); +INSERT INTO `dic_city` VALUES ('640303', '640303', '红寺堡区', '6403', 3); +INSERT INTO `dic_city` VALUES ('640323', '640323', '盐池县', '6403', 3); +INSERT INTO `dic_city` VALUES ('640324', '640324', '同心县', '6403', 3); +INSERT INTO `dic_city` VALUES ('640381', '640381', '青铜峡市', '6403', 3); +INSERT INTO `dic_city` VALUES ('6404', '6404', '固原市', '64', 2); +INSERT INTO `dic_city` VALUES ('640402', '640402', '原州区', '6404', 3); +INSERT INTO `dic_city` VALUES ('640422', '640422', '西吉县', '6404', 3); +INSERT INTO `dic_city` VALUES ('640423', '640423', '隆德县', '6404', 3); +INSERT INTO `dic_city` VALUES ('640424', '640424', '泾源县', '6404', 3); +INSERT INTO `dic_city` VALUES ('640425', '640425', '彭阳县', '6404', 3); +INSERT INTO `dic_city` VALUES ('6405', '6405', '中卫市', '64', 2); +INSERT INTO `dic_city` VALUES ('640502', '640502', '沙坡头区', '6405', 3); +INSERT INTO `dic_city` VALUES ('640521', '640521', '中宁县', '6405', 3); +INSERT INTO `dic_city` VALUES ('640522', '640522', '海原县', '6405', 3); +INSERT INTO `dic_city` VALUES ('65', '65', '新疆维吾尔自治区', NULL, 1); +INSERT INTO `dic_city` VALUES ('6501', '6501', '乌鲁木齐市', '65', 2); +INSERT INTO `dic_city` VALUES ('650102', '650102', '天山区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650103', '650103', '沙依巴克区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650104', '650104', '新市区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650105', '650105', '水磨沟区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650106', '650106', '头屯河区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650107', '650107', '达坂城区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650109', '650109', '米东区', '6501', 3); +INSERT INTO `dic_city` VALUES ('650121', '650121', '乌鲁木齐县', '6501', 3); +INSERT INTO `dic_city` VALUES ('6502', '6502', '克拉玛依市', '65', 2); +INSERT INTO `dic_city` VALUES ('650202', '650202', '独山子区', '6502', 3); +INSERT INTO `dic_city` VALUES ('650203', '650203', '克拉玛依区', '6502', 3); +INSERT INTO `dic_city` VALUES ('650204', '650204', '白碱滩区', '6502', 3); +INSERT INTO `dic_city` VALUES ('650205', '650205', '乌尔禾区', '6502', 3); +INSERT INTO `dic_city` VALUES ('6504', '6504', '吐鲁番市', '65', 2); +INSERT INTO `dic_city` VALUES ('650402', '650402', '高昌区', '6504', 3); +INSERT INTO `dic_city` VALUES ('650421', '650421', '鄯善县', '6504', 3); +INSERT INTO `dic_city` VALUES ('650422', '650422', '托克逊县', '6504', 3); +INSERT INTO `dic_city` VALUES ('6505', '6505', '哈密市', '65', 2); +INSERT INTO `dic_city` VALUES ('650502', '650502', '伊州区', '6505', 3); +INSERT INTO `dic_city` VALUES ('650521', '650521', '巴里坤哈萨克自治县', '6505', 3); +INSERT INTO `dic_city` VALUES ('650522', '650522', '伊吾县', '6505', 3); +INSERT INTO `dic_city` VALUES ('6523', '6523', '昌吉回族自治州', '65', 2); +INSERT INTO `dic_city` VALUES ('652301', '652301', '昌吉市', '6523', 3); +INSERT INTO `dic_city` VALUES ('652302', '652302', '阜康市', '6523', 3); +INSERT INTO `dic_city` VALUES ('652323', '652323', '呼图壁县', '6523', 3); +INSERT INTO `dic_city` VALUES ('652324', '652324', '玛纳斯县', '6523', 3); +INSERT INTO `dic_city` VALUES ('652325', '652325', '奇台县', '6523', 3); +INSERT INTO `dic_city` VALUES ('652327', '652327', '吉木萨尔县', '6523', 3); +INSERT INTO `dic_city` VALUES ('652328', '652328', '木垒哈萨克自治县', '6523', 3); +INSERT INTO `dic_city` VALUES ('6527', '6527', '博尔塔拉蒙古自治州', '65', 2); +INSERT INTO `dic_city` VALUES ('652701', '652701', '博乐市', '6527', 3); +INSERT INTO `dic_city` VALUES ('652702', '652702', '阿拉山口市', '6527', 3); +INSERT INTO `dic_city` VALUES ('652722', '652722', '精河县', '6527', 3); +INSERT INTO `dic_city` VALUES ('652723', '652723', '温泉县', '6527', 3); +INSERT INTO `dic_city` VALUES ('6528', '6528', '巴音郭楞蒙古自治州', '65', 2); +INSERT INTO `dic_city` VALUES ('652801', '652801', '库尔勒市', '6528', 3); +INSERT INTO `dic_city` VALUES ('652822', '652822', '轮台县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652823', '652823', '尉犁县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652824', '652824', '若羌县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652825', '652825', '且末县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652826', '652826', '焉耆回族自治县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652827', '652827', '和静县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652828', '652828', '和硕县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652829', '652829', '博湖县', '6528', 3); +INSERT INTO `dic_city` VALUES ('652871', '652871', '库尔勒经济技术开发区', '6528', 3); +INSERT INTO `dic_city` VALUES ('6529', '6529', '阿克苏地区', '65', 2); +INSERT INTO `dic_city` VALUES ('652901', '652901', '阿克苏市', '6529', 3); +INSERT INTO `dic_city` VALUES ('652902', '652902', '库车市', '6529', 3); +INSERT INTO `dic_city` VALUES ('652922', '652922', '温宿县', '6529', 3); +INSERT INTO `dic_city` VALUES ('652924', '652924', '沙雅县', '6529', 3); +INSERT INTO `dic_city` VALUES ('652925', '652925', '新和县', '6529', 3); +INSERT INTO `dic_city` VALUES ('652926', '652926', '拜城县', '6529', 3); +INSERT INTO `dic_city` VALUES ('652927', '652927', '乌什县', '6529', 3); +INSERT INTO `dic_city` VALUES ('652928', '652928', '阿瓦提县', '6529', 3); +INSERT INTO `dic_city` VALUES ('652929', '652929', '柯坪县', '6529', 3); +INSERT INTO `dic_city` VALUES ('6530', '6530', '克孜勒苏柯尔克孜自治州', '65', 2); +INSERT INTO `dic_city` VALUES ('653001', '653001', '阿图什市', '6530', 3); +INSERT INTO `dic_city` VALUES ('653022', '653022', '阿克陶县', '6530', 3); +INSERT INTO `dic_city` VALUES ('653023', '653023', '阿合奇县', '6530', 3); +INSERT INTO `dic_city` VALUES ('653024', '653024', '乌恰县', '6530', 3); +INSERT INTO `dic_city` VALUES ('6531', '6531', '喀什地区', '65', 2); +INSERT INTO `dic_city` VALUES ('653101', '653101', '喀什市', '6531', 3); +INSERT INTO `dic_city` VALUES ('653121', '653121', '疏附县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653122', '653122', '疏勒县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653123', '653123', '英吉沙县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653124', '653124', '泽普县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653125', '653125', '莎车县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653126', '653126', '叶城县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653127', '653127', '麦盖提县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653128', '653128', '岳普湖县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653129', '653129', '伽师县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653130', '653130', '巴楚县', '6531', 3); +INSERT INTO `dic_city` VALUES ('653131', '653131', '塔什库尔干塔吉克自治县', '6531', 3); +INSERT INTO `dic_city` VALUES ('6532', '6532', '和田地区', '65', 2); +INSERT INTO `dic_city` VALUES ('653201', '653201', '和田市', '6532', 3); +INSERT INTO `dic_city` VALUES ('653221', '653221', '和田县', '6532', 3); +INSERT INTO `dic_city` VALUES ('653222', '653222', '墨玉县', '6532', 3); +INSERT INTO `dic_city` VALUES ('653223', '653223', '皮山县', '6532', 3); +INSERT INTO `dic_city` VALUES ('653224', '653224', '洛浦县', '6532', 3); +INSERT INTO `dic_city` VALUES ('653225', '653225', '策勒县', '6532', 3); +INSERT INTO `dic_city` VALUES ('653226', '653226', '于田县', '6532', 3); +INSERT INTO `dic_city` VALUES ('653227', '653227', '民丰县', '6532', 3); +INSERT INTO `dic_city` VALUES ('6540', '6540', '伊犁哈萨克自治州', '65', 2); +INSERT INTO `dic_city` VALUES ('654002', '654002', '伊宁市', '6540', 3); +INSERT INTO `dic_city` VALUES ('654003', '654003', '奎屯市', '6540', 3); +INSERT INTO `dic_city` VALUES ('654004', '654004', '霍尔果斯市', '6540', 3); +INSERT INTO `dic_city` VALUES ('654021', '654021', '伊宁县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654022', '654022', '察布查尔锡伯自治县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654023', '654023', '霍城县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654024', '654024', '巩留县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654025', '654025', '新源县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654026', '654026', '昭苏县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654027', '654027', '特克斯县', '6540', 3); +INSERT INTO `dic_city` VALUES ('654028', '654028', '尼勒克县', '6540', 3); +INSERT INTO `dic_city` VALUES ('6542', '6542', '塔城地区', '65', 2); +INSERT INTO `dic_city` VALUES ('654201', '654201', '塔城市', '6542', 3); +INSERT INTO `dic_city` VALUES ('654202', '654202', '乌苏市', '6542', 3); +INSERT INTO `dic_city` VALUES ('654221', '654221', '额敏县', '6542', 3); +INSERT INTO `dic_city` VALUES ('654223', '654223', '沙湾县', '6542', 3); +INSERT INTO `dic_city` VALUES ('654224', '654224', '托里县', '6542', 3); +INSERT INTO `dic_city` VALUES ('654225', '654225', '裕民县', '6542', 3); +INSERT INTO `dic_city` VALUES ('654226', '654226', '和布克赛尔蒙古自治县', '6542', 3); +INSERT INTO `dic_city` VALUES ('6543', '6543', '阿勒泰地区', '65', 2); +INSERT INTO `dic_city` VALUES ('654301', '654301', '阿勒泰市', '6543', 3); +INSERT INTO `dic_city` VALUES ('654321', '654321', '布尔津县', '6543', 3); +INSERT INTO `dic_city` VALUES ('654322', '654322', '富蕴县', '6543', 3); +INSERT INTO `dic_city` VALUES ('654323', '654323', '福海县', '6543', 3); +INSERT INTO `dic_city` VALUES ('654324', '654324', '哈巴河县', '6543', 3); +INSERT INTO `dic_city` VALUES ('654325', '654325', '青河县', '6543', 3); +INSERT INTO `dic_city` VALUES ('654326', '654326', '吉木乃县', '6543', 3); +INSERT INTO `dic_city` VALUES ('6590', '6590', '自治区直辖县级行政区划', '65', 2); +INSERT INTO `dic_city` VALUES ('659001', '659001', '石河子市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659002', '659002', '阿拉尔市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659003', '659003', '图木舒克市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659004', '659004', '五家渠市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659005', '659005', '北屯市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659006', '659006', '铁门关市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659007', '659007', '双河市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659008', '659008', '可克达拉市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659009', '659009', '昆玉市', '6590', 3); +INSERT INTO `dic_city` VALUES ('659010', '659010', '胡杨河市', '6590', 3); + +-- ---------------------------- +-- Table structure for gen_create_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_create_column_config`; +CREATE TABLE `gen_create_column_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `required` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否必填', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '新增功能代码生成配置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_create_column_config +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_form +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_form`; +CREATE TABLE `gen_custom_form` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `is_dialog` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否对话框表单', + `dialog_tittle` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '对话框标题', + `dialog_width` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '1' COMMENT '对话框宽度', + `form_config` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '表单配置', + `prefix_submit` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '前置提交脚本', + `suffix_submit` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '后置提交脚本', + `require_query` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否需要查询', + `query_bean` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '查询数据Bean名称', + `handle_bean` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '操作数据Bean名称', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义对话框' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_form +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_form_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_form_category`; +CREATE TABLE `gen_custom_form_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表分类' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_form_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_list +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list`; +CREATE TABLE `gen_custom_list` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `data_obj_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '数据对象ID', + `list_type` tinyint(3) NOT NULL DEFAULT 0 COMMENT '列表类型', + `label_width` int(11) NOT NULL COMMENT '表单Label宽度', + `has_page` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否分页', + `tree_data` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否树形列表', + `id_column` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ID字段', + `id_column_rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ID字段关联ID', + `tree_pid_column` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID字段', + `tree_pid_column_rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID字段关联ID', + `tree_node_column` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '树形节点字段', + `tree_node_column_rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '树形节点字段关联ID', + `tree_children_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '子节点Key值', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `query_prefix_sql` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '查询前置SQL', + `query_suffix_sql` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '查询后置SQL', + `suffix_sql` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '后置SQL', + `allow_export` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否允许导出', + PRIMARY KEY (`id`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_list +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_list_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_category`; +CREATE TABLE `gen_custom_list_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表分类' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_list_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_list_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_detail`; +CREATE TABLE `gen_custom_list_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `custom_list_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义列表ID', + `rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '关联ID', + `data_entity_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据实体ID', + `width_type` tinyint(3) NOT NULL COMMENT '宽度类型', + `width` int(11) NOT NULL COMMENT '宽度', + `sortable` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否页面排序', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `type` tinyint(3) NOT NULL COMMENT '类型', + `formatter` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '格式化脚本', + PRIMARY KEY (`id`) USING BTREE, + INDEX `custom_list_id`(`custom_list_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_list_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_list_handle_column +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_handle_column`; +CREATE TABLE `gen_custom_list_handle_column` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `custom_list_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义列表ID', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', + `view_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示类型', + `btn_type` tinyint(3) NOT NULL COMMENT '按钮类型', + `btn_config` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '按钮配置', + `request_param` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求参数', + `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + `width` int(11) NOT NULL COMMENT '宽度', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表工具栏' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_list_handle_column +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_list_query_params +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_query_params`; +CREATE TABLE `gen_custom_list_query_params` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `custom_list_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义列表ID', + `rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '关联ID', + `data_entity_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据实体ID', + `front_show` tinyint(1) NOT NULL DEFAULT 1 COMMENT '前端显示', + `query_type` tinyint(3) NOT NULL COMMENT '查询类型', + `form_width` int(11) NOT NULL DEFAULT 6 COMMENT '表单宽度', + `default_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '默认值', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `type` tinyint(3) NOT NULL COMMENT '类型', + PRIMARY KEY (`id`) USING BTREE, + INDEX `custom_list_id`(`custom_list_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表查询参数' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_list_query_params +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_list_toolbar +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_toolbar`; +CREATE TABLE `gen_custom_list_toolbar` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `custom_list_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义列表ID', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', + `view_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示类型', + `btn_type` tinyint(3) NOT NULL COMMENT '按钮类型', + `btn_config` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '按钮配置', + `request_param` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求参数', + `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义列表工具栏' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_list_toolbar +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_page +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_page`; +CREATE TABLE `gen_custom_page` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `page_code` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '页面代码', + `script_code` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '脚本代码', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义页面' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of gen_custom_page +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_page_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_page_category`; +CREATE TABLE `gen_custom_page_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `parent_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义页面分类' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of gen_custom_page_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_selector +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_selector`; +CREATE TABLE `gen_custom_selector` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `custom_list_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '数据对象ID', + `dialog_tittle` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '对话框标题', + `dialog_width` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '对话框宽度', + `placeholder` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '占位符', + `id_column` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ID字段', + `id_column_rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ID字段关联ID', + `name_column` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称ID字段', + `name_column_rela_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称ID字段关联ID', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义对话框' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_selector +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_custom_selector_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_selector_category`; +CREATE TABLE `gen_custom_selector_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '自定义对话框分类' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_custom_selector_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_entity +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_entity`; +CREATE TABLE `gen_data_entity` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `gen_status` tinyint(3) NOT NULL DEFAULT 1 COMMENT '状态', + `table_schema` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据表所属的数据库名', + `table_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据库表名', + `engine` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据库引擎', + `table_collation` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字符校验编码集', + `table_comment` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '备注', + `convert_type` tinyint(3) NOT NULL COMMENT '转换方式', + PRIMARY KEY (`id`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据实体' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_entity +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_entity_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_entity_category`; +CREATE TABLE `gen_data_entity_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据实体分类' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_entity_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_entity_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_entity_detail`; +CREATE TABLE `gen_data_entity_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `entity_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '实体ID', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段显示名称', + `column_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段名称', + `is_key` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否主键', + `data_type` tinyint(3) NOT NULL COMMENT '数据类型', + `column_order` int(11) NOT NULL COMMENT '排序编号', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `view_type` tinyint(3) NOT NULL COMMENT '显示类型', + `data_dic_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据字典ID', + `custom_selector_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '自定义选择器ID', + `fix_enum` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否内置枚举', + `enum_back` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '后端枚举名', + `enum_front` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '前端枚举名', + `regular_expression` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '正则表达式', + `is_order` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否排序字段', + `order_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '排序类型', + `len` bigint(20) NULL DEFAULT NULL COMMENT '长度', + `decimals` int(11) NULL DEFAULT NULL COMMENT '小数位数', + `db_column_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段名', + `db_data_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字段数据类型', + `is_nullable` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否允许为空', + `column_default` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '默认值', + `ordinal_position` bigint(21) UNSIGNED NOT NULL DEFAULT 0 COMMENT '字段排序', + `column_comment` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字段备注', + `db_len` bigint(20) NULL DEFAULT NULL COMMENT '长度', + `db_decimals` int(11) NULL DEFAULT NULL COMMENT '小数位数', + PRIMARY KEY (`id`) USING BTREE, + INDEX `entity_id`(`entity_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据实体明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_entity_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_obj +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj`; +CREATE TABLE `gen_data_obj` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `main_table_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '主表ID', + `main_table_alias` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主表别名', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据对象' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_obj +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_obj_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj_category`; +CREATE TABLE `gen_data_obj_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据实体分类' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_obj_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_obj_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj_detail`; +CREATE TABLE `gen_data_obj_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `data_obj_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据对象ID', + `main_table_detail_ids` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主表字段', + `rela_type` tinyint(3) NOT NULL COMMENT '关联类型', + `rela_mode` tinyint(3) NOT NULL COMMENT '关联方式', + `sub_table_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '子表ID', + `sub_table_alias` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '子表别名', + `sub_table_detail_ids` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '子表字段', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + INDEX `data_obj_id`(`data_obj_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据对象明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_obj_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_data_obj_query_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj_query_detail`; +CREATE TABLE `gen_data_obj_query_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `data_obj_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据对象ID', + `custom_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '显示名称', + `custom_sql` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义SQL', + `custom_alias` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '自定义别名', + `data_type` tinyint(3) NOT NULL COMMENT '数据类型', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + INDEX `data_obj_id`(`data_obj_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据对象自定义查询明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_data_obj_query_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_detail_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_detail_column_config`; +CREATE TABLE `gen_detail_column_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `span` int(11) NOT NULL COMMENT '列宽', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '详情功能代码生成配置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_detail_column_config +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_generate_info +-- ---------------------------- +DROP TABLE IF EXISTS `gen_generate_info`; +CREATE TABLE `gen_generate_info` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `template_type` tinyint(3) NOT NULL COMMENT '生成模板类型', + `package_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '包名', + `module_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '模块名', + `biz_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务名', + `class_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '类名', + `parent_menu_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级菜单ID', + `key_type` tinyint(3) NOT NULL COMMENT '主键类型', + `author` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '作者', + `class_description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '类描述', + `menu_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '本级菜单编号', + `menu_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '本级菜单名称', + `detail_span` int(11) NOT NULL COMMENT '详情页Span总数量', + `is_cache` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否应用缓存', + `has_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否内置删除功能', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '代码生成基本信息' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_generate_info +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_query_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_query_column_config`; +CREATE TABLE `gen_query_column_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `width_type` tinyint(3) NOT NULL COMMENT '宽度类型', + `width` int(11) NOT NULL COMMENT '宽度', + `sortable` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否页面排序', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '查询功能代码生成配置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_query_column_config +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_query_params_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_query_params_column_config`; +CREATE TABLE `gen_query_params_column_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `query_type` tinyint(3) NOT NULL COMMENT '查询类型', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '查询参数功能代码生成配置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_query_params_column_config +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_simple_table +-- ---------------------------- +DROP TABLE IF EXISTS `gen_simple_table`; +CREATE TABLE `gen_simple_table` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `table_schema` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据表所属的数据库名', + `table_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据库表名', + `engine` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据库引擎', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `table_collation` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字符校验编码集', + `table_comment` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '备注', + `convert_type` tinyint(3) NOT NULL COMMENT '转换方式', + PRIMARY KEY (`id`) USING BTREE, + INDEX `table_schema`(`table_schema`, `table_name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据库单表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_simple_table +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_simple_table_column +-- ---------------------------- +DROP TABLE IF EXISTS `gen_simple_table_column`; +CREATE TABLE `gen_simple_table_column` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `table_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `column_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段名', + `data_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字段数据类型', + `is_nullable` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否允许为空', + `is_key` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否主键', + `column_default` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '默认值', + `ordinal_position` bigint(21) UNSIGNED NOT NULL DEFAULT 0 COMMENT '字段排序', + `column_comment` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字段备注', + `len` bigint(20) NULL DEFAULT NULL COMMENT '长度', + `decimals` int(11) NULL DEFAULT NULL COMMENT '小数位数', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据库单表列信息' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_simple_table_column +-- ---------------------------- + +-- ---------------------------- +-- Table structure for gen_update_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_update_column_config`; +CREATE TABLE `gen_update_column_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `required` tinyint(1) NOT NULL DEFAULT 0, + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '修改功能代码生成配置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of gen_update_column_config +-- ---------------------------- + +-- ---------------------------- +-- Table structure for op_logs +-- ---------------------------- +DROP TABLE IF EXISTS `op_logs`; +CREATE TABLE `op_logs` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '日志名称', + `log_type` int(11) NOT NULL COMMENT '类别', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `extra` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '补充信息', + `ip` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'IP地址', + PRIMARY KEY (`id`) USING BTREE, + INDEX `create_by`(`create_by`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of op_logs +-- ---------------------------- + +-- ---------------------------- +-- Table structure for recursion_mapping +-- ---------------------------- +DROP TABLE IF EXISTS `recursion_mapping`; +CREATE TABLE `recursion_mapping` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `node_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '节点ID', + `node_type` tinyint(3) NOT NULL COMMENT '节点类型', + `path` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '从顶点到当前结点的路径,用,分割', + `level` int(11) NOT NULL COMMENT '节点层级', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `node_id`(`node_id`, `node_type`) USING BTREE, + INDEX `node_type`(`node_type`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '树形数据节点关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of recursion_mapping +-- ---------------------------- +INSERT INTO `recursion_mapping` VALUES ('1', '2', 1, NULL, 1); +INSERT INTO `recursion_mapping` VALUES ('2', '4', 1, '2', 2); +INSERT INTO `recursion_mapping` VALUES ('3', '3', 1, '1', 2); +INSERT INTO `recursion_mapping` VALUES ('4', '1', 1, NULL, 1); + +-- ---------------------------- +-- Table structure for settle_check_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_check_sheet`; +CREATE TABLE `settle_check_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `total_pay_amount` decimal(24, 2) NOT NULL COMMENT '应付金额', + `total_payed_amount` decimal(24, 2) NOT NULL COMMENT '已付金额', + `total_discount_amount` decimal(24, 2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商对账单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_check_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_check_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_check_sheet_detail`; +CREATE TABLE `settle_check_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '对账单ID', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `calc_type` tinyint(3) NOT NULL COMMENT '计算类型', + `pay_amount` decimal(24, 2) NOT NULL COMMENT '应付金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `biz_id`) USING BTREE, + INDEX `biz_id`(`biz_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商对账单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_check_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_fee_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_fee_sheet`; +CREATE TABLE `settle_fee_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `sheet_type` tinyint(3) NOT NULL COMMENT '单据类型', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商费用单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_fee_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_fee_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_fee_sheet_detail`; +CREATE TABLE `settle_fee_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '费用单ID', + `item_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '项目ID', + `amount` decimal(24, 2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `item_id`) USING BTREE, + INDEX `item_id`(`item_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商费用单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_fee_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_in_item +-- ---------------------------- +DROP TABLE IF EXISTS `settle_in_item`; +CREATE TABLE `settle_in_item` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '收入项目' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_in_item +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_out_item +-- ---------------------------- +DROP TABLE IF EXISTS `settle_out_item`; +CREATE TABLE `settle_out_item` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支出项目' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_out_item +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_pre_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_pre_sheet`; +CREATE TABLE `settle_pre_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商预付款单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_pre_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_pre_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_pre_sheet_detail`; +CREATE TABLE `settle_pre_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '预付款单ID', + `item_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '项目ID', + `amount` decimal(24, 2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `item_id`) USING BTREE, + INDEX `item_id`(`item_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商预付款单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_pre_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_sheet`; +CREATE TABLE `settle_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '总金额', + `total_discount_amount` decimal(24, 2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商结算单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for settle_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_sheet_detail`; +CREATE TABLE `settle_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '结算单ID', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `pay_amount` decimal(24, 2) NOT NULL COMMENT '实付金额', + `discount_amount` decimal(24, 2) NOT NULL COMMENT '优惠金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `biz_id`) USING BTREE, + INDEX `biz_id`(`biz_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '供应商结算单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of settle_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sw_file_box +-- ---------------------------- +DROP TABLE IF EXISTS `sw_file_box`; +CREATE TABLE `sw_file_box` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `url` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'Url', + `content_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ContentType', + `file_type` tinyint(3) NOT NULL COMMENT '文件类型', + `file_size` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件大小', + `file_path` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件路径', + `file_suffix` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件后缀', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文件收纳箱' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sw_file_box +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sw_online_excel +-- ---------------------------- +DROP TABLE IF EXISTS `sw_online_excel`; +CREATE TABLE `sw_online_excel` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态 1-在用 0停用', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '在线Excel' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sw_online_excel +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_data_dic +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_dic`; +CREATE TABLE `sys_data_dic` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `category_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类ID', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `name`(`name`) USING BTREE, + INDEX `category_id`(`category_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据字典' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_data_dic +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_data_dic_category +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_dic_category`; +CREATE TABLE `sys_data_dic_category` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据字典分类' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_data_dic_category +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_data_dic_item +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_dic_item`; +CREATE TABLE `sys_data_dic_item` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `dic_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字典ID', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `dic_id`(`dic_id`, `code`) USING BTREE, + UNIQUE INDEX `dic_id_2`(`dic_id`, `name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据字典' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_data_dic_item +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_data_permission_data +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_permission_data`; +CREATE TABLE `sys_data_permission_data` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `permission_type` tinyint(3) NOT NULL COMMENT '权限类型', + `permission` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据权限', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `biz_id`(`biz_id`, `biz_type`, `permission_type`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据权限数据' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_data_permission_data +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_data_permission_model_detail +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_permission_model_detail`; +CREATE TABLE `sys_data_permission_model_detail` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `model_id` int(11) NOT NULL COMMENT '模型ID', + `condition_type` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '条件', + `input_type` tinyint(3) NOT NULL COMMENT '输入类型', + `table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '表名', + `column_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段名', + `enum_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '前端枚举名', + `sql_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'SQL', + PRIMARY KEY (`id`) USING BTREE, + INDEX `model_id`(`model_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据权限模型明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_data_permission_model_detail +-- ---------------------------- +INSERT INTO `sys_data_permission_model_detail` VALUES (1, '编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (2, '名称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (3, '简称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'short_name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (4, 'SKU', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'sku_code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (5, '外部编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'external_code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (6, '品类编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'category', 'code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (7, '品类名称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'category', 'name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (8, '品牌编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'brand', 'code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (9, '品牌名称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'brand', 'name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (10, '规格', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'spec', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (11, '单位', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'unit', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (12, '状态', 1, '0,5,6,7', 1, 'product', 'available', 'AVAILABLE', NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (13, '创建时间', 1, '0,1,2,3,4,5', 2, 'product', 'create_time', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (14, '创建人部门与本人相同', 2, '6', 99, 'order', 'create_by_id', NULL, 'SELECT __ud.user_id FROM sys_user_dept AS __ud WHERE __ud.dept_id IN ({__var#curDeptIds})'); +INSERT INTO `sys_data_permission_model_detail` VALUES (15, '创建人部门是本人的上级部门', 2, '6', 99, 'order', 'create_by_id', NULL, 'SELECT DISTINCT __ud.user_id FROM sys_user_dept AS __ud WHERE FIND_IN_SET(__ud.dept_id,(SELECT GROUP_CONCAT(__mp.path) FROM sys_dept AS __d INNER JOIN recursion_mapping AS __mp ON __mp.node_id=__d.id AND __mp.node_type=1 WHERE __d.id IN ({__var#curDeptIds}) AND __mp.level> 1))'); +INSERT INTO `sys_data_permission_model_detail` VALUES (16, '创建人部门是本人的下级部门', 2, '6', 99, 'order', 'create_by_id', NULL, 'SELECT DISTINCT __ud.user_id FROM sys_user_dept AS __ud WHERE __ud.dept_id IN (SELECT __mp.node_id FROM recursion_mapping AS __mp WHERE FIND_IN_SET((SELECT __d.id FROM sys_dept AS __d WHERE __d.id IN ({__var#curDeptIds})),__mp.path) AND __mp.node_type=1)'); +INSERT INTO `sys_data_permission_model_detail` VALUES (17, '创建时间', 2, '0,1,2,3,4,5', 2, 'order', 'create_time', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dept`; +CREATE TABLE `sys_dept` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `short_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '简称', + `parent_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dept +-- ---------------------------- +INSERT INTO `sys_dept` VALUES ('1', '001', '销售中心', '销售中心', NULL, 1, '', '系统管理员', '1', '2022-01-13 00:37:06', '系统管理员', '1', '2022-01-13 00:37:06'); +INSERT INTO `sys_dept` VALUES ('2', '002', '研发中心', '研发中心', NULL, 1, '', '系统管理员', '1', '2022-01-13 00:37:17', '系统管理员', '1', '2022-01-13 00:37:17'); +INSERT INTO `sys_dept` VALUES ('3', '001001', '销售部', '销售部', '1', 1, '', '系统管理员', '1', '2022-01-13 00:38:03', '系统管理员', '1', '2022-01-13 00:38:03'); +INSERT INTO `sys_dept` VALUES ('4', '002001', '研发部', '研发部', '2', 1, '', '系统管理员', '1', '2022-01-13 00:38:15', '系统管理员', '1', '2022-01-13 00:38:15'); + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu`; +CREATE TABLE `sys_menu` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称(前端使用)', + `title` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题', + `icon` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + `component_type` tinyint(3) NULL DEFAULT NULL COMMENT '组件类型(前端使用)', + `component` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组件(前端使用)', + `request_param` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '自定义请求参数', + `parent_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级ID', + `sys_module_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '系统模块ID', + `path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路由路径(前端使用)', + `no_cache` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否缓存(前端使用)', + `display` tinyint(3) NOT NULL COMMENT '类型 0-目录 1-菜单 2-功能', + `hidden` tinyint(1) NULL DEFAULT 0 COMMENT '是否隐藏(前端使用)', + `permission` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限', + `is_special` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否特殊菜单', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `code`(`code`, `name`, `title`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO `sys_menu` VALUES ('1000', '1000', 'System', '系统管理', 'ant-design:setting-outlined', NULL, '', NULL, NULL, '2', '/system', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2023-10-27 17:01:09'); +INSERT INTO `sys_menu` VALUES ('1000001', '1000001', 'Menu', '菜单管理', NULL, 0, '/system/menu/index', NULL, '1000', '2', '/menu', 0, 1, 0, 'system:menu:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2023-10-27 17:01:09'); +INSERT INTO `sys_menu` VALUES ('1000001001', '1000001001', '', '新增菜单', NULL, 0, '', NULL, '1000001', '2', '', 0, 2, 0, 'system:menu:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2023-10-27 17:01:09'); +INSERT INTO `sys_menu` VALUES ('1000001002', '1000001002', '', '修改菜单', NULL, 0, '', NULL, '1000001', '2', '', 0, 2, 0, 'system:menu:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2023-10-27 17:00:27'); +INSERT INTO `sys_menu` VALUES ('1000001003', '1000001003', '', '删除菜单', NULL, 0, '', NULL, '1000001', '2', '', 0, 2, 0, 'system:menu:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2023-10-27 17:00:27'); +INSERT INTO `sys_menu` VALUES ('1000002', '1000002', 'Dept', '部门管理', NULL, 0, '/system/dept/index', NULL, '1000', '2', '/dept', 0, 1, 0, 'system:dept:query', 1, 1, '', '系统管理员', '1', '2021-07-05 01:09:27', '系统管理员', '1', '2023-10-27 17:00:27'); +INSERT INTO `sys_menu` VALUES ('1000002001', '1000002001', '', '新增部门', NULL, 0, '', NULL, '1000002', '2', '', 0, 2, 0, 'system:dept:add', 1, 1, '', '系统管理员', '1', '2021-06-27 01:33:31', '系统管理员', '1', '2023-10-27 17:00:27'); +INSERT INTO `sys_menu` VALUES ('1000002002', '1000002002', '', '修改部门', NULL, 0, '', NULL, '1000002', '2', '', 0, 2, 0, 'system:dept:modify', 1, 1, '', '系统管理员', '1', '2021-06-27 01:33:47', '系统管理员', '1', '2023-10-27 17:00:27'); +INSERT INTO `sys_menu` VALUES ('1000002003', '1000002003', '', '部门权限', NULL, 0, '', NULL, '1000002', '2', '', 0, 2, 0, 'system:dept:permission', 1, 1, '', '系统管理员', '1', '2021-06-27 01:33:47', '系统管理员', '1', '2023-10-27 17:00:27'); +INSERT INTO `sys_menu` VALUES ('1000003', '1000003', 'Position', '岗位管理', NULL, 0, '/system/position/index', NULL, '1000', '2', '/position', 0, 1, 0, 'system:position:query', 1, 1, '', '系统管理员', '1', '2021-07-01 23:26:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000003001', '1000003001', '', '新增岗位', NULL, 0, '', NULL, '1000003', '2', '', 0, 2, 0, 'system:position:add', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000003002', '1000003002', '', '修改岗位', NULL, 0, '', NULL, '1000003', '2', '', 0, 2, 0, 'system:position:modify', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000004', '1000004', 'Role', '角色管理', NULL, 0, '/system/role/index', NULL, '1000', '2', '/role', 0, 1, 0, 'system:role:query', 1, 1, '', '系统管理员', '1', '2021-07-04 00:35:49', '系统管理员', '1', '2021-07-04 00:35:49'); +INSERT INTO `sys_menu` VALUES ('1000004001', '1000004001', '', '新增角色', NULL, 0, '', NULL, '1000004', '2', '', 0, 2, 0, 'system:role:add', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000004002', '1000004002', '', '修改角色', NULL, 0, '', NULL, '1000004', '2', '', 0, 2, 0, 'system:role:modify', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000004003', '1000004003', '', '角色授权', NULL, 0, '', NULL, '1000004', '2', '', 0, 2, 0, 'system:role:permission', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000005', '1000005', 'User', '用户管理', NULL, 0, '/system/user/index', NULL, '1000', '2', '/user', 0, 1, 0, 'system:user:query', 1, 1, '', '系统管理员', '1', '2021-07-05 01:08:40', '系统管理员', '1', '2021-07-05 01:08:40'); +INSERT INTO `sys_menu` VALUES ('1000005001', '1000005001', '', '新增用户', NULL, 0, '', NULL, '1000005', '2', '', 0, 2, 0, 'system:user:add', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000005002', '1000005002', '', '修改用户', NULL, 0, '', NULL, '1000005', '2', '', 0, 2, 0, 'system:user:modify', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000005003', '1000005003', '', '用户授权', NULL, 0, '', NULL, '1000005', '2', '', 0, 2, 0, 'system:user:permission', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000006', '1000006', 'Oplog', '操作日志', NULL, 0, '/system/oplog/index', NULL, '1000', '2', '/oplog', 0, 1, 0, 'system:oplog:query', 1, 1, '', '系统管理员', '1', '2021-07-05 01:08:40', '系统管理员', '1', '2021-07-05 01:08:40'); +INSERT INTO `sys_menu` VALUES ('1000007', '1000007', 'SysParameter', '系统参数', NULL, 0, '/system/parameter/index', NULL, '1000', '2', '/parameter', 0, 1, 0, 'system:parameter:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000007001', '1000007001', '', '新增系统参数', NULL, 0, '', NULL, '1000007', '2', '', 0, 2, 0, 'system:parameter:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000007002', '1000007002', '', '修改系统参数', NULL, 0, '', NULL, '1000007', '2', '', 0, 2, 0, 'system:parameter:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000007003', '1000007003', '', '删除系统参数', NULL, 0, '', NULL, '1000007', '2', '', 0, 2, 0, 'system:parameter:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000008', '1000008', 'PublishSysNotice', '发布系统通知', NULL, 0, '/system/notice/publish', NULL, '1000', '2', '/system/notice/publish', 0, 1, 0, 'system:notice:publish', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000008001', '1000008001', '', '新增系统通知', NULL, 0, '', NULL, '1000008', '2', '', 0, 2, 0, 'system:notice:add', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000008002', '1000008002', '', '修改系统通知', NULL, 0, '', NULL, '1000008', '2', '', 0, 2, 0, 'system:notice:modify', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000009', '1000009', 'SysNotice', '系统通知', NULL, 0, '/system/notice/index', NULL, '1000', '2', '/system/notice', 0, 1, 0, 'system:notice:query', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000010', '1000010', 'SysDataDic', '数据字典', NULL, 0, '/system/dic/index', NULL, '1000', '2', '/dic', 0, 1, 0, 'system:dic:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010001', '1000010001', '', '新增数据字典', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010002', '1000010002', '', '修改数据字典', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010003', '1000010003', '', '删除数据字典', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1000010004', '1000010004', '', '新增数据字典分类', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic-category:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010005', '1000010005', '', '修改数据字典分类', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic-category:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010006', '1000010006', '', '删除数据字典分类', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic-category:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010007', '1000010007', '', '新增数据字典值', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010008', '1000010008', '', '修改数据字典值', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000010009', '1000010009', '', '删除数据字典值', NULL, 0, '', NULL, '1000010', '2', '', 0, 2, 0, 'system:dic-item:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1000011', '1000011', 'SysTenant', '租户管理', NULL, 0, '/system/tenant/index', NULL, '1001', '1', '/system/tenant', 0, 1, 0, 'system:tenant:query', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000011001', '1000011001', '', '新增租户', NULL, 0, '', NULL, '1000011', '1', '', 0, 2, 0, 'system:tenant:add', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000011002', '1000011002', '', '修改租户', NULL, 0, '', NULL, '1000011', '1', '', 0, 2, 0, 'system:tenant:modify', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000011003', '1000011003', '', '授权模块', NULL, 0, '', NULL, '1000011', '1', '', 0, 2, 0, 'system:tenant:module', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` VALUES ('1000012', '1000012', 'OpenDomain', '开放域', NULL, 0, '/system/open-domain/index', NULL, '1001', '14', '/open-domain', 0, 1, 0, 'system:open-domain:config', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('1001', '1001', 'Platform', '平台管理', 'ant-design:global-outlined', NULL, '', NULL, NULL, '1', '/platform', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('1001001', '1001001', 'OnelineCode', '在线开发', NULL, 0, '/iframes/index', NULL, '1001', '1', '/online-code?src=${magic-api.base-url}${magic-api.web}/index.html', 0, 1, 0, 'system:online-code:config', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('2000', '2000', 'BaseData', '基础信息管理', 'ant-design:container-outlined', NULL, '', NULL, NULL, '3', '/base-data', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('2000002', '2000002', 'StoreCenterInfo', '仓库信息', NULL, 0, '/base-data/store-center/index', NULL, '2000', '3', '/store-center', 0, 1, 0, 'base-data:store-center:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000002001', '2000002001', '', '新增仓库', NULL, 0, '', NULL, '2000002', '3', '', 0, 2, 0, 'base-data:store-center:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000002002', '2000002002', '', '修改仓库', NULL, 0, '', NULL, '2000002', '3', '', 0, 2, 0, 'base-data:store-center:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000002003', '2000002003', '', '导入仓库', NULL, 0, '', NULL, '2000002', '3', '', 0, 2, 0, 'base-data:store-center:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000004', '2000004', 'Customer', '客户信息', NULL, 0, '/base-data/customer/index', NULL, '2000', '3', '/customer', 0, 1, 0, 'base-data:customer:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000004001', '2000004001', '', '新增客户', NULL, 0, '', NULL, '2000004', '3', '', 0, 2, 0, 'base-data:customer:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000004002', '2000004002', '', '修改客户', NULL, 0, '', NULL, '2000004', '3', '', 0, 2, 0, 'base-data:customer:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000004003', '2000004003', '', '导入客户', NULL, 0, '', NULL, '2000004', '3', '', 0, 2, 0, 'base-data:customer:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000005', '2000005', 'Supplier', '供应商信息', NULL, 0, '/base-data/supplier/index', NULL, '2000', '3', '/supplier', 0, 1, 0, 'base-data:supplier:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000005001', '2000005001', '', '新增供应商', NULL, 0, '', NULL, '2000005', '3', '', 0, 2, 0, 'base-data:supplier:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000005002', '2000005002', '', '修改供应商', NULL, 0, '', NULL, '2000005', '3', '', 0, 2, 0, 'base-data:supplier:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000005003', '2000005003', '', '导入供应商', NULL, 0, '', NULL, '2000005', '3', '', 0, 2, 0, 'base-data:supplier:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000006', '2000006', 'Member', '会员信息', NULL, 0, '/base-data/member/index', NULL, '2000', '3', '/member', 0, 1, 0, 'base-data:member:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000006001', '2000006001', '', '新增会员', NULL, 0, '', NULL, '2000006', '3', '', 0, 2, 0, 'base-data:member:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000006002', '2000006002', '', '修改会员', NULL, 0, '', NULL, '2000006', '3', '', 0, 2, 0, 'base-data:member:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000006003', '2000006003', '', '导入会员', NULL, 0, '', NULL, '2000006', '3', '', 0, 2, 0, 'base-data:member:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000007', '2000007', 'Shop', '门店信息', NULL, 0, '/base-data/shop/index', NULL, '2000', '3', '/shop', 0, 1, 0, 'base-data:shop:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000007001', '2000007001', '', '新增门店', NULL, 0, '', NULL, '2000007', '3', '', 0, 2, 0, 'base-data:shop:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000007002', '2000007002', '', '修改门店', NULL, 0, '', NULL, '2000007', '3', '', 0, 2, 0, 'base-data:shop:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000007003', '2000007003', '', '导入门店', NULL, 0, '', NULL, '2000007', '3', '', 0, 2, 0, 'base-data:shop:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000008', '2000008', 'PayType', '支付方式', NULL, 0, '/base-data/pay-type/index', NULL, '2000', '3', '/pay-type', 0, 1, 0, 'base-data:pay-type:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000008001', '2000008001', '', '新增支付方式', NULL, 0, '', NULL, '2000008', '3', '', 0, 2, 0, 'base-data:pay-type:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000008002', '2000008002', '', '修改支付方式', NULL, 0, '', NULL, '2000008', '3', '', 0, 2, 0, 'base-data:pay-type:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000009', '2000009', 'Address', '地址库', NULL, 0, '/base-data/address/index', NULL, '2000', '15', '/address', 0, 1, 0, 'base-data:address:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000009001', '2000009001', '', '新增地址', NULL, 0, '', NULL, '2000009', '15', '', 0, 2, 0, 'base-data:address:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000009002', '2000009002', '', '修改地址', NULL, 0, '', NULL, '2000009', '15', '', 0, 2, 0, 'base-data:address:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000009003', '2000009003', '', '导出地址', NULL, 0, '', NULL, '2000009', '15', '', 0, 2, 0, 'base-data:address:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000009004', '2000009004', '', '导入地址', NULL, 0, '', NULL, '2000009', '15', '', 0, 2, 0, 'base-data:address:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000010', '2000010', 'LogisticsCompany', '物流公司', NULL, 0, '/base-data/logistics/company/index', NULL, '2000', '15', '/logistics/company', 0, 1, 0, 'base-data:logistics-company:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2000010001', '2000010001', '', '新增物流公司', NULL, 0, '', NULL, '2000010', '15', '', 0, 2, 0, 'base-data:logistics-company:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2000010002', '2000010002', '', '修改物流公司', NULL, 0, '', NULL, '2000010', '15', '', 0, 2, 0, 'base-data:logistics-company:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001', '2001', 'Product', '商品中心', 'ant-design:appstore-outlined', NULL, '', NULL, NULL, '4', '/product', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('2001001', '2001001', 'ProductCategory', '商品类目', NULL, 0, '/base-data/product/category/index', NULL, '2001', '4', '/category', 0, 1, 0, 'base-data:product:category:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2001001001', '2001001001', '', '新增类目', NULL, 0, '', NULL, '2001001', '4', '', 0, 2, 0, 'base-data:product:category:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001001002', '2001001002', '', '修改类目', NULL, 0, '', NULL, '2001001', '4', '', 0, 2, 0, 'base-data:product:category:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001001003', '2001001003', '', '导入类目', NULL, 0, '', NULL, '2001001', '4', '', 0, 2, 0, 'base-data:product:category:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001002', '2001002', 'ProductBrand', '商品品牌', NULL, 0, '/base-data/product/brand/index', NULL, '2001', '4', '/brand', 0, 1, 0, 'base-data:product:brand:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` VALUES ('2001002001', '2001002001', '', '新增品牌', NULL, 0, '', NULL, '2001002', '4', '', 0, 2, 0, 'base-data:product:brand:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001002002', '2001002002', '', '修改品牌', NULL, 0, '', NULL, '2001002', '4', '', 0, 2, 0, 'base-data:product:brand:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001002003', '2001002003', '', '导入品牌', NULL, 0, '', NULL, '2001002', '4', '', 0, 2, 0, 'base-data:product:brand:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001004', '2001004', 'ProductProperty', '商品属性', NULL, 0, '/base-data/product/property/index', NULL, '2001', '4', '/property', 0, 1, 0, 'base-data:product:property:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` VALUES ('2001004001', '2001004001', '', '新增属性', NULL, 0, '', NULL, '2001004', '4', '', 0, 2, 0, 'base-data:product:property:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001004002', '2001004002', '', '修改属性', NULL, 0, '', NULL, '2001004', '4', '', 0, 2, 0, 'base-data:product:property:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001004003', '2001004003', '', '查询属性值', NULL, 0, '', NULL, '2001004', '4', '', 0, 2, 0, 'base-data:product:property-item:query', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001004004', '2001004004', '', '新增属性值', NULL, 0, '', NULL, '2001004', '4', '', 0, 2, 0, 'base-data:product:property-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001004005', '2001004005', '', '修改属性值', NULL, 0, '', NULL, '2001004', '4', '', 0, 2, 0, 'base-data:product:property-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001005', '2001005', 'ProductInfo', '商品管理', NULL, 0, '/base-data/product/info/index', NULL, '2001', '4', '/info', 0, 1, 0, 'base-data:product:info:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` VALUES ('2001005001', '2001005001', '', '新增商品', NULL, 0, '', NULL, '2001005', '4', '', 0, 2, 0, 'base-data:product:info:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001005002', '2001005002', '', '修改商品', NULL, 0, '', NULL, '2001005', '4', '', 0, 2, 0, 'base-data:product:info:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2001005003', '2001005003', '', '导入商品', NULL, 0, '', NULL, '2001005', '4', '', 0, 2, 0, 'base-data:product:info:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002', '2002', 'Purchase', '采购管理', 'ant-design:money-collect-outlined', NULL, '', NULL, NULL, '5', '/purchase', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('2002001', '2002001', 'PurchaseConfig', '采购参数设置', NULL, 0, '/sc/purchase/config/index', NULL, '2002', '5', '/config', 1, 1, 0, 'purchase:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2002002', '2002002', 'PurchaseOrder', '采购订单管理', NULL, 0, '/sc/purchase/order/index', NULL, '2002', '5', '/order', 0, 1, 0, 'purchase:order:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2002002001', '2002002001', '', '新增采购订单', NULL, 0, '', NULL, '2002002', '5', '', 0, 2, 0, 'purchase:order:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002002002', '2002002002', '', '修改采购订单', NULL, 0, '', NULL, '2002002', '5', '', 0, 2, 0, 'purchase:order:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002002003', '2002002003', '', '删除采购订单', NULL, 0, '', NULL, '2002002', '5', '', 0, 2, 0, 'purchase:order:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002002004', '2002002004', '', '审核采购订单', NULL, 0, '', NULL, '2002002', '5', '', 0, 2, 0, 'purchase:order:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002002005', '2002002005', '', '导出采购订单', NULL, 0, '', NULL, '2002002', '5', '', 0, 2, 0, 'purchase:order:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002002006', '2002002006', '', '导入采购订单', NULL, 0, '', NULL, '2002002', '5', '', 0, 2, 0, 'purchase:order:import', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002003', '2002003', 'ReceiveSheet', '采购收货管理', NULL, 0, '/sc/purchase/receive/index', NULL, '2002', '5', '/receive', 0, 1, 0, 'purchase:receive:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2002003001', '2002003001', '', '新增采购收货单', NULL, 0, '', NULL, '2002003', '5', '', 0, 2, 0, 'purchase:receive:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002003002', '2002003002', '', '修改采购收货单', NULL, 0, '', NULL, '2002003', '5', '', 0, 2, 0, 'purchase:receive:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002003003', '2002003003', '', '删除采购收货单', NULL, 0, '', NULL, '2002003', '5', '', 0, 2, 0, 'purchase:receive:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002003004', '2002003004', '', '审核采购收货单', NULL, 0, '', NULL, '2002003', '5', '', 0, 2, 0, 'purchase:receive:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002003005', '2002003005', '', '导出采购收货单', NULL, 0, '', NULL, '2002003', '5', '', 0, 2, 0, 'purchase:receive:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002003006', '2002003006', '', '导入采购收货单', NULL, 0, '', NULL, '2002003', '5', '', 0, 2, 0, 'purchase:receive:import', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002004', '2002004', 'PurchaseReturn', '采购退货管理', NULL, 0, '/sc/purchase/return/index', NULL, '2002', '5', '/return', 0, 1, 0, 'purchase:return:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2002004001', '2002004001', '', '新增采购退货单', NULL, 0, '', NULL, '2002004', '5', '', 0, 2, 0, 'purchase:return:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002004002', '2002004002', '', '修改采购退货单', NULL, 0, '', NULL, '2002004', '5', '', 0, 2, 0, 'purchase:return:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002004003', '2002004003', '', '删除采购退货单', NULL, 0, '', NULL, '2002004', '5', '', 0, 2, 0, 'purchase:return:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002004004', '2002004004', '', '审核采购退货单', NULL, 0, '', NULL, '2002004', '5', '', 0, 2, 0, 'purchase:return:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2002004005', '2002004005', '', '导出采购退货单', NULL, 0, '', NULL, '2002004', '5', '', 0, 2, 0, 'purchase:return:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003', '2003', 'Sale', '销售管理', 'ant-design:rocket-outlined', NULL, '', NULL, NULL, '6', '/sale', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('2003001', '2003001', 'SaleConfig', '销售参数设置', NULL, 0, '/sc/sale/config/index', NULL, '2003', '6', '/config', 1, 1, 0, 'sale:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2003002', '2003002', 'SaleOrder', '销售订单管理', NULL, 0, '/sc/sale/order/index', NULL, '2003', '6', '/order', 0, 1, 0, 'sale:order:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2003002001', '2003002001', '', '新增销售订单', NULL, 0, '', NULL, '2003002', '6', '', 0, 2, 0, 'sale:order:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003002002', '2003002002', '', '修改销售订单', NULL, 0, '', NULL, '2003002', '6', '', 0, 2, 0, 'sale:order:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003002003', '2003002003', '', '删除销售订单', NULL, 0, '', NULL, '2003002', '6', '', 0, 2, 0, 'sale:order:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003002004', '2003002004', '', '审核销售订单', NULL, 0, '', NULL, '2003002', '6', '', 0, 2, 0, 'sale:order:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003002005', '2003002005', '', '导出销售订单', NULL, 0, '', NULL, '2003002', '6', '', 0, 2, 0, 'sale:order:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003003', '2003003', 'SaleOutSheet', '销售出库管理', NULL, 0, '/sc/sale/out/index', NULL, '2003', '6', '/out', 0, 1, 0, 'sale:out:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2003003001', '2003003001', '', '新增销售出库单', NULL, 0, '', NULL, '2003003', '6', '', 0, 2, 0, 'sale:out:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003003002', '2003003002', '', '修改销售出库单', NULL, 0, '', NULL, '2003003', '6', '', 0, 2, 0, 'sale:out:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003003003', '2003003003', '', '删除销售出库单', NULL, 0, '', NULL, '2003003', '6', '', 0, 2, 0, 'sale:out:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003003004', '2003003004', '', '审核销售出库单', NULL, 0, '', NULL, '2003003', '6', '', 0, 2, 0, 'sale:out:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003003005', '2003003005', '', '导出销售出库单', NULL, 0, '', NULL, '2003003', '6', '', 0, 2, 0, 'sale:out:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003004', '2003004', 'SaleReturn', '销售退货管理', NULL, 0, '/sc/sale/return/index', NULL, '2003', '6', '/return', 0, 1, 0, 'sale:return:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2003004001', '2003004001', '', '新增销售退货单', NULL, 0, '', NULL, '2003004', '6', '', 0, 2, 0, 'sale:return:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003004002', '2003004002', '', '修改销售退货单', NULL, 0, '', NULL, '2003004', '6', '', 0, 2, 0, 'sale:return:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003004003', '2003004003', '', '删除销售退货单', NULL, 0, '', NULL, '2003004', '6', '', 0, 2, 0, 'sale:return:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003004004', '2003004004', '', '审核销售退货单', NULL, 0, '', NULL, '2003004', '6', '', 0, 2, 0, 'sale:return:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2003004005', '2003004005', '', '导出销售退货单', NULL, 0, '', NULL, '2003004', '6', '', 0, 2, 0, 'sale:return:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004', '2004', 'Retail', '零售管理', 'ant-design:flag-outlined', NULL, '', NULL, NULL, '7', '/retail', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('2004001', '2004001', 'RetailConfig', '零售参数设置', NULL, 0, '/sc/retail/config/index', NULL, '2004', '7', '/config', 1, 1, 0, 'retail:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2004002', '2004002', 'RetailOutSheet', '零售出库管理', NULL, 0, '/sc/retail/out/index', NULL, '2004', '7', '/out', 0, 1, 0, 'retail:out:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2004002001', '2004002001', '', '新增零售出库单', NULL, 0, '', NULL, '2004002', '7', '', 0, 2, 0, 'retail:out:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004002002', '2004002002', '', '修改零售出库单', NULL, 0, '', NULL, '2004002', '7', '', 0, 2, 0, 'retail:out:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004002003', '2004002003', '', '删除零售出库单', NULL, 0, '', NULL, '2004002', '7', '', 0, 2, 0, 'retail:out:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004002004', '2004002004', '', '审核零售出库单', NULL, 0, '', NULL, '2004002', '7', '', 0, 2, 0, 'retail:out:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004002005', '2004002005', '', '导出零售出库单', NULL, 0, '', NULL, '2004002', '7', '', 0, 2, 0, 'retail:out:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004003', '2004003', 'RetailReturn', '零售退货管理', NULL, 0, '/sc/retail/return/index', NULL, '2004', '7', '/return', 0, 1, 0, 'retail:return:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('2004003001', '2004003001', '', '新增零售退货单', NULL, 0, '', NULL, '2004003', '7', '', 0, 2, 0, 'retail:return:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004003002', '2004003002', '', '修改零售退货单', NULL, 0, '', NULL, '2004003', '7', '', 0, 2, 0, 'retail:return:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004003003', '2004003003', '', '删除零售退货单', NULL, 0, '', NULL, '2004003', '7', '', 0, 2, 0, 'retail:return:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004003004', '2004003004', '', '审核零售退货单', NULL, 0, '', NULL, '2004003', '7', '', 0, 2, 0, 'retail:return:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('2004003005', '2004003005', '', '导出零售退货单', NULL, 0, '', NULL, '2004003', '7', '', 0, 2, 0, 'retail:return:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000', '3000', 'StockManage', '库存管理', 'ant-design:hdd-outlined', NULL, '', NULL, NULL, '8', '/stock', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('3000001', '3000001', 'ProductStock', '商品库存', NULL, 0, '/sc/stock/product/index', NULL, '3000', '8', '/product', 0, 1, 0, 'stock:product:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000001001', '3000001001', '', '导出商品库存', NULL, 0, '', NULL, '3000001', '8', '', 0, 2, 0, 'stock:product:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000003', '3000003', 'ProductStockLog', '商品库存变动记录', NULL, 0, '/sc/stock/product-log/index', NULL, '3000', '8', '/product/log', 0, 1, 0, 'stock:product-log:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000003001', '3000003001', '', '导出商品库存变动记录', NULL, 0, '', NULL, '3000003', '8', '', 0, 2, 0, 'stock:product-log:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004', '3000004', 'TakeStock', '库存盘点', 'ant-design:monitor-outlined', NULL, '', NULL, NULL, '9', '/take', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('3000004001', '3000004001', 'TakeStockConfig', '盘点参数设置', NULL, 0, '/sc/stock/take/config/index', NULL, '3000004', '9', '/config', 1, 1, 0, 'stock:take:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000004002', '3000004002', 'PreTakeStockSheet', '预先盘点单管理', NULL, 0, '/sc/stock/take/pre/index', NULL, '3000004', '9', '/pre', 0, 1, 0, 'stock:take:pre:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000004002001', '3000004002001', '', '新增预先盘点单', NULL, 0, '', NULL, '3000004002', '9', '', 0, 2, 0, 'stock:take:pre:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004002002', '3000004002002', '', '修改预先盘点单', NULL, 0, '', NULL, '3000004002', '9', '', 0, 2, 0, 'stock:take:pre:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004002003', '3000004002003', '', '删除预先盘点单', NULL, 0, '', NULL, '3000004002', '9', '', 0, 2, 0, 'stock:take:pre:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004002004', '3000004002004', '', '导出预先盘点单', NULL, 0, '', NULL, '3000004002', '9', '', 0, 2, 0, 'stock:take:pre:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003', '3000004003', 'TakeStockPlan', '盘点任务管理', NULL, 0, '/sc/stock/take/plan/index', NULL, '3000004', '9', '/plan', 0, 1, 0, 'stock:take:plan:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000004003001', '3000004003001', '', '新增盘点任务', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003002', '3000004003002', '', '修改盘点任务', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003003', '3000004003003', '', '删除盘点任务', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003004', '3000004003004', '', '导出盘点任务', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003005', '3000004003005', '', '差异生成', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:create-diff', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003006', '3000004003006', '', '差异处理', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:handle-diff', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004003007', '3000004003007', '', '作废盘点任务', NULL, 0, '', NULL, '3000004003', '9', '', 0, 2, 0, 'stock:take:plan:cancel', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004004', '3000004004', 'TakeStockSheet', '盘点单管理', NULL, 0, '/sc/stock/take/sheet/index', NULL, '3000004', '9', '/sheet', 0, 1, 0, 'stock:take:sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000004004001', '3000004004001', '', '新增盘点单', NULL, 0, '', NULL, '3000004004', '9', '', 0, 2, 0, 'stock:take:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004004002', '3000004004002', '', '修改盘点单', NULL, 0, '', NULL, '3000004004', '9', '', 0, 2, 0, 'stock:take:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004004003', '3000004004003', '', '删除盘点单', NULL, 0, '', NULL, '3000004004', '9', '', 0, 2, 0, 'stock:take:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004004004', '3000004004004', '', '导出盘点单', NULL, 0, '', NULL, '3000004004', '9', '', 0, 2, 0, 'stock:take:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004004005', '3000004004005', '', '审核盘点单', NULL, 0, '', NULL, '3000004004', '9', '', 0, 2, 0, 'stock:take:sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000004004006', '3000004004006', '', '取消审核盘点单', NULL, 0, '', NULL, '3000004004', '9', '', 0, 2, 0, 'stock:take:sheet:cancel-approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005', '3000005', 'StockAdjust', '库存调整', 'ant-design:thunderbolt-outlined', NULL, '', NULL, NULL, '10', '/take-adjust', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('3000005001', '3000005001', 'StockCostAdjustSheet', '库存成本调整', NULL, 0, '/sc/stock/adjust/cost/index', NULL, '3000005', '10', '/cost', 0, 1, 0, 'stock:adjust:cost:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000005001001', '3000005001001', '', '新增库存成本调整单', NULL, 0, '', NULL, '3000005001', '10', '', 0, 2, 0, 'stock:adjust:cost:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005001002', '3000005001002', '', '修改库存成本调整单', NULL, 0, '', NULL, '3000005001', '10', '', 0, 2, 0, 'stock:adjust:cost:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005001003', '3000005001003', '', '删除库存成本调整单', NULL, 0, '', NULL, '3000005001', '10', '', 0, 2, 0, 'stock:adjust:cost:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005001004', '3000005001004', '', '导出库存成本调整单', NULL, 0, '', NULL, '3000005001', '10', '', 0, 2, 0, 'stock:adjust:cost:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005001005', '3000005001005', '', '审核库存成本调整单', NULL, 0, '', NULL, '3000005001', '10', '', 0, 2, 0, 'stock:adjust:cost:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005002', '3000005002', 'StockAdjustReason', '库存调整原因', NULL, 0, '/sc/stock/adjust/stock/reason/index', NULL, '3000005', '10', '/stock/reason', 0, 1, 0, 'stock:adjust:reason:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000005002001', '3000005002001', '', '新增库存成本调整单', NULL, 0, '', NULL, '3000005002', '10', '', 0, 2, 0, 'stock:adjust:reason:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005002002', '3000005002002', '', '修改库存成本调整单', NULL, 0, '', NULL, '3000005002', '10', '', 0, 2, 0, 'stock:adjust:reason:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005003', '3000005003', 'StockAdjustSheet', '库存数量调整', NULL, 0, '/sc/stock/adjust/stock/index', NULL, '3000005', '10', '/stock', 0, 1, 0, 'stock:adjust:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000005003001', '3000005003001', '', '新增库存调整单', NULL, 0, '', NULL, '3000005003', '10', '', 0, 2, 0, 'stock:adjust:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005003002', '3000005003002', '', '修改库存调整单', NULL, 0, '', NULL, '3000005003', '10', '', 0, 2, 0, 'stock:adjust:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005003003', '3000005003003', '', '删除库存调整单', NULL, 0, '', NULL, '3000005003', '10', '', 0, 2, 0, 'stock:adjust:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005003004', '3000005003004', '', '导出库存调整单', NULL, 0, '', NULL, '3000005003', '10', '', 0, 2, 0, 'stock:adjust:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000005003005', '3000005003005', '', '审核库存调整单', NULL, 0, '', NULL, '3000005003', '10', '', 0, 2, 0, 'stock:adjust:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000006', '3000006', 'ScTransferOrder', '仓库调拨', NULL, 0, '/sc/stock/transfer/index', NULL, '3000', '8', '/transfer', 0, 1, 0, 'stock:sc-transfer:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('3000006001', '3000006001', '', '新增仓库调拨单', NULL, 0, '', NULL, '3000006', '8', '', 0, 2, 0, 'stock:sc-transfer:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000006002', '3000006002', '', '修改仓库调拨单', NULL, 0, '', NULL, '3000006', '8', '', 0, 2, 0, 'stock:sc-transfer:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000006003', '3000006003', '', '删除仓库调拨单', NULL, 0, '', NULL, '3000006', '8', '', 0, 2, 0, 'stock:sc-transfer:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000006004', '3000006004', '', '导出仓库调拨单', NULL, 0, '', NULL, '3000006', '8', '', 0, 2, 0, 'stock:sc-transfer:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000006005', '3000006005', '', '审核仓库调拨单', NULL, 0, '', NULL, '3000006', '8', '', 0, 2, 0, 'stock:sc-transfer:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('3000006006', '3000006006', '', '仓库调拨单收货', NULL, 0, '', NULL, '3000006', '8', '', 0, 2, 0, 'stock:sc-transfer:receive', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000', '4000', 'SettleManage', '结算管理', 'ant-design:credit-card-outlined', NULL, '', NULL, NULL, '11', '/settle', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('4000001', '4000001', 'SettleInItem', '收入项目', NULL, 0, '/settle/in-item/index', NULL, '4000', '11', '/in-item', 0, 1, 0, 'settle:in-item:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000001001', '4000001001', '', '新增收入项目', NULL, 0, '', NULL, '4000001', '11', '', 0, 2, 0, 'settle:in-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000001002', '4000001002', '', '修改收入项目', NULL, 0, '', NULL, '4000001', '11', '', 0, 2, 0, 'settle:in-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000001003', '4000001003', '', '导出收入项目', NULL, 0, '', NULL, '4000001', '11', '', 0, 2, 0, 'settle:in-item:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000002', '4000002', 'SettleOutItem', '支出项目', NULL, 0, '/settle/out-item/index', NULL, '4000', '11', '/out-item', 0, 1, 0, 'settle:out-item:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000002001', '4000002001', '', '新增支出项目', NULL, 0, '', NULL, '4000002', '11', '', 0, 2, 0, 'settle:out-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000002002', '4000002002', '', '修改支出项目', NULL, 0, '', NULL, '4000002', '11', '', 0, 2, 0, 'settle:out-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000002003', '4000002003', '', '导出支出项目', NULL, 0, '', NULL, '4000002', '11', '', 0, 2, 0, 'settle:out-item:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000003', '4000003', 'SettleFeeSheet', '供应商费用', NULL, 0, '/settle/fee-sheet/index', NULL, '4000007', '11', '/fee-sheet', 0, 1, 0, 'settle:fee-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000003001', '4000003001', '', '新增供应商费用单', NULL, 0, '', NULL, '4000003', '11', '', 0, 2, 0, 'settle:fee-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000003002', '4000003002', '', '修改供应商费用单', NULL, 0, '', NULL, '4000003', '11', '', 0, 2, 0, 'settle:fee-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000003003', '4000003003', '', '删除供应商费用单', NULL, 0, '', NULL, '4000003', '11', '', 0, 2, 0, 'settle:fee-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000003004', '4000003004', '', '审核供应商费用单', NULL, 0, '', NULL, '4000003', '11', '', 0, 2, 0, 'settle:fee-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000003005', '4000003005', '', '导出供应商费用单', NULL, 0, '', NULL, '4000003', '11', '', 0, 2, 0, 'settle:fee-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000004', '4000004', 'SettlePreSheet', '供应商预付款', NULL, 0, '/settle/pre-sheet/index', NULL, '4000007', '11', '/pre-sheet', 0, 1, 0, 'settle:pre-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000004001', '4000004001', '', '新增供应商预付款单', NULL, 0, '', NULL, '4000004', '11', '', 0, 2, 0, 'settle:pre-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000004002', '4000004002', '', '修改供应商预付款单', NULL, 0, '', NULL, '4000004', '11', '', 0, 2, 0, 'settle:pre-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000004003', '4000004003', '', '删除供应商预付款单', NULL, 0, '', NULL, '4000004', '11', '', 0, 2, 0, 'settle:pre-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000004004', '4000004004', '', '审核供应商预付款单', NULL, 0, '', NULL, '4000004', '11', '', 0, 2, 0, 'settle:pre-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000004005', '4000004005', '', '导出供应商预付款单', NULL, 0, '', NULL, '4000004', '11', '', 0, 2, 0, 'settle:pre-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000005', '4000005', 'SettleCheckSheet', '供应商对账', NULL, 0, '/settle/check-sheet/index', NULL, '4000007', '11', '/check-sheet', 0, 1, 0, 'settle:check-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000005001', '4000005001', '', '新增供应商对账单', NULL, 0, '', NULL, '4000005', '11', '', 0, 2, 0, 'settle:check-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000005002', '4000005002', '', '修改供应商对账单', NULL, 0, '', NULL, '4000005', '11', '', 0, 2, 0, 'settle:check-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000005003', '4000005003', '', '删除供应商对账单', NULL, 0, '', NULL, '4000005', '11', '', 0, 2, 0, 'settle:check-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000005004', '4000005004', '', '审核供应商对账单', NULL, 0, '', NULL, '4000005', '11', '', 0, 2, 0, 'settle:check-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000005005', '4000005005', '', '导出供应商对账单', NULL, 0, '', NULL, '4000005', '11', '', 0, 2, 0, 'settle:check-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000006', '4000006', 'SettleSheet', '供应商结算', NULL, 0, '/settle/sheet/index', NULL, '4000007', '11', '/sheet', 0, 1, 0, 'settle:sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000006001', '4000006001', '', '新增供应商结算单', NULL, 0, '', NULL, '4000006', '11', '', 0, 2, 0, 'settle:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000006002', '4000006002', '', '修改供应商结算单', NULL, 0, '', NULL, '4000006', '11', '', 0, 2, 0, 'settle:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000006003', '4000006003', '', '删除供应商结算单', NULL, 0, '', NULL, '4000006', '11', '', 0, 2, 0, 'settle:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000006004', '4000006004', '', '审核供应商结算单', NULL, 0, '', NULL, '4000006', '11', '', 0, 2, 0, 'settle:sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000006005', '4000006005', '', '导出供应商结算单', NULL, 0, '', NULL, '4000006', '11', '', 0, 2, 0, 'settle:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000007', '4000007', 'SupplierSettleManage', '供应商结算', NULL, NULL, '', NULL, '4000', '11', '/supplier', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('4000008', '4000008', 'CustomerSettleManage', '客户结算', NULL, NULL, '', NULL, '4000', '11', '/customer', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` VALUES ('4000009', '4000009', 'CustomerSettleFeeSheet', '客户费用', NULL, 0, '/customer-settle/fee-sheet/index', NULL, '4000008', '11', '/fee-sheet', 0, 1, 0, 'customer-settle:fee-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000009001', '4000009001', '', '新增客户费用单', NULL, 0, '', NULL, '4000009', '11', '', 0, 2, 0, 'customer-settle:fee-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000009002', '4000009002', '', '修改客户费用单', NULL, 0, '', NULL, '4000009', '11', '', 0, 2, 0, 'customer-settle:fee-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000009003', '4000009003', '', '删除客户费用单', NULL, 0, '', NULL, '4000009', '11', '', 0, 2, 0, 'customer-settle:fee-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000009004', '4000009004', '', '审核客户费用单', NULL, 0, '', NULL, '4000009', '11', '', 0, 2, 0, 'customer-settle:fee-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000009005', '4000009005', '', '导出客户费用单', NULL, 0, '', NULL, '4000009', '11', '', 0, 2, 0, 'customer-settle:fee-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000010', '4000010', 'CustomerSettlePreSheet', '客户预收款', NULL, 0, '/customer-settle/pre-sheet/index', NULL, '4000008', '11', '/pre-sheet', 0, 1, 0, 'customer-settle:pre-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000010001', '4000010001', '', '新增客户预收款单', NULL, 0, '', NULL, '4000010', '11', '', 0, 2, 0, 'customer-settle:pre-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000010002', '4000010002', '', '修改客户预收款单', NULL, 0, '', NULL, '4000010', '11', '', 0, 2, 0, 'customer-settle:pre-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000010003', '4000010003', '', '删除客户预收款单', NULL, 0, '', NULL, '4000010', '11', '', 0, 2, 0, 'customer-settle:pre-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000010004', '4000010004', '', '审核客户预收款单', NULL, 0, '', NULL, '4000010', '11', '', 0, 2, 0, 'customer-settle:pre-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000010005', '4000010005', '', '导出客户预收款单', NULL, 0, '', NULL, '4000010', '11', '', 0, 2, 0, 'customer-settle:pre-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000011', '4000011', 'CustomerSettleCheckSheet', '客户对账', NULL, 0, '/customer-settle/check-sheet/index', NULL, '4000008', '11', '/check-sheet', 0, 1, 0, 'customer-settle:check-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000011001', '4000011001', '', '新增客户对账单', NULL, 0, '', NULL, '4000011', '11', '', 0, 2, 0, 'customer-settle:check-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000011002', '4000011002', '', '修改客户对账单', NULL, 0, '', NULL, '4000011', '11', '', 0, 2, 0, 'customer-settle:check-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000011003', '4000011003', '', '删除客户对账单', NULL, 0, '', NULL, '4000011', '11', '', 0, 2, 0, 'customer-settle:check-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000011004', '4000011004', '', '审核客户对账单', NULL, 0, '', NULL, '4000011', '11', '', 0, 2, 0, 'customer-settle:check-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000011005', '4000011005', '', '导出客户对账单', NULL, 0, '', NULL, '4000011', '11', '', 0, 2, 0, 'customer-settle:check-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000012', '4000012', 'CustomerSettleSheet', '客户结算', NULL, 0, '/customer-settle/sheet/index', NULL, '4000008', '11', '/sheet', 0, 1, 0, 'customer-settle:sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` VALUES ('4000012001', '4000012001', '', '新增客户结算单', NULL, 0, '', NULL, '4000012', '11', '', 0, 2, 0, 'customer-settle:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000012002', '4000012002', '', '修改客户结算单', NULL, 0, '', NULL, '4000012', '11', '', 0, 2, 0, 'customer-settle:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000012003', '4000012003', '', '删除客户结算单', NULL, 0, '', NULL, '4000012', '11', '', 0, 2, 0, 'customer-settle:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000012004', '4000012004', '', '审核客户结算单', NULL, 0, '', NULL, '4000012', '11', '', 0, 2, 0, 'customer-settle:sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('4000012005', '4000012005', '', '导出客户结算单', NULL, 0, '', NULL, '4000012', '11', '', 0, 2, 0, 'customer-settle:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('5000', '5000', 'Logistics', '物流管理', 'ant-design:gift-outlined', NULL, '', NULL, NULL, '15', '/logistics', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('5000001', '5000001', 'LogisticsSheet', '物流单管理', NULL, 0, '/sc/logistics/sheet/index', NULL, '5000', '15', '/sheet', 0, 1, 0, 'logistics:sheet:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('5000001001', '5000001001', '', '新增物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('5000001002', '5000001002', '', '修改物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('5000001003', '5000001003', '', '删除物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('5000001004', '5000001004', '', '物流单发货', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:delivery', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('5000001005', '5000001005', '', '导入物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('5000001006', '5000001006', '', '导出物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('9000', '9000', 'Development', '开发管理', 'ant-design:tool-outlined', NULL, '', NULL, NULL, '12', '/development', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('9000001', '9000001', 'Qrtz', '定时器管理', NULL, 0, '/development/qrtz/index', NULL, '9000', '12', '/qrtz', 0, 1, 0, 'development:qrtz:manage', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('9000002', '9000002', 'DataEntity', '数据实体', NULL, 0, '/development/data/entity/index', NULL, '9000', '12', '/data/entity', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('9000003', '9000003', 'DataObj', '数据对象', NULL, 0, '/development/data/obj/index', NULL, '9000', '12', '/data/obj', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('9000004', '9000004', 'CustomList', '自定义列表', NULL, 0, '/development/custom/list/index', NULL, '9000', '12', '/custom/list', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('9000005', '9000005', 'CustomSelector', '自定义选择器', NULL, 0, '/development/custom/selector/index', NULL, '9000', '12', '/custom/selector', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('9000008', '9000008', 'CustomPage', '自定义页面', NULL, 0, '/development/custom/page/index', NULL, '9000', '12', '/custom/page', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` VALUES ('9001', '9001', 'SmartWork', '便捷办公', 'ant-design:read-outlined', NULL, '', NULL, NULL, '13', '/smart-work', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` VALUES ('9001001', '9001001', 'FileBox', '文件收纳箱', NULL, 0, '/smart-work/file-box/index', NULL, '9001', '13', '/file-box', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); + +-- ---------------------------- +-- Table structure for sys_menu_collect +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu_collect`; +CREATE TABLE `sys_menu_collect` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID', + `menu_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `user_id, menu_id`(`user_id`, `menu_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单收藏' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_menu_collect +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_notice +-- ---------------------------- +DROP TABLE IF EXISTS `sys_notice`; +CREATE TABLE `sys_notice` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题', + `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '内容', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `published` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否发布', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `readed_num` int(11) NOT NULL DEFAULT 0 COMMENT '已读人数', + `un_read_num` int(11) NOT NULL DEFAULT 0 COMMENT '未读人数', + `publish_time` datetime NULL DEFAULT NULL COMMENT '发布时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统通知' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_notice +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_notice_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_notice_log`; +CREATE TABLE `sys_notice_log` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `notice_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题', + `user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID', + `readed` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否已读', + `read_time` datetime NULL DEFAULT NULL COMMENT '已读时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `notice_id`(`notice_id`, `user_id`) USING BTREE, + INDEX `user_id`(`user_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统通知记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_notice_log +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_parameter +-- ---------------------------- +DROP TABLE IF EXISTS `sys_parameter`; +CREATE TABLE `sys_parameter` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `pm_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '键', + `pm_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '值', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `pm_key`(`pm_key`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统参数' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_parameter +-- ---------------------------- +INSERT INTO `sys_parameter` VALUES (1, 'tx-map.key', 'OLJBZ-ZFJK6-QWUSK-MB7XT-6UTN2-AWBSY', '腾讯地图Key', '系统管理员', '1', '2022-05-22 04:18:59', '系统管理员', '1', '2022-05-22 04:18:59'); +INSERT INTO `sys_parameter` VALUES (2, 'tx-map.secret', 'secret', '腾讯地图Secret', '系统管理员', '1', '2022-05-22 04:18:59', '系统管理员', '1', '2022-05-22 04:18:59'); +INSERT INTO `sys_parameter` VALUES (3, 'excel-import.max-size', '2000', 'Excel导入最大条数', '系统管理员', '1', '2022-06-10 21:39:32', '系统管理员', '1', '2022-06-10 21:39:32'); +INSERT INTO `sys_parameter` VALUES (8, 'mail', '{\n \"pass\":\"123456\",\n \"sslEnable\":true,\n \"timeOut\":30000,\n \"port\":25,\n \"host\":\"smtp.xingyun.com\",\n \"connectTimeOut\":1000,\n \"from\":\"test@xingyun.com\",\n \"user\":\"test\"\n}', '邮件配置', '系统管理员', '1', '2023-03-14 21:13:44', '系统管理员', '1', '2023-03-14 21:13:44'); +INSERT INTO `sys_parameter` VALUES (9, 'upload.type', 'LOCAL', '上传类型,分为LOCAL、OSS、COS、OBS。LOCAL:服务器本地存储。OSS:阿里云对象存储。COS:腾讯云对象存储。OBS:华为云对象存储', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 10:38:10'); +INSERT INTO `sys_parameter` VALUES (10, 'upload.oss.config', '{\"customUrl\":\"\",\"endpoint\":\"yourEndpoint\",\"internalEndPoint\":\"\",\"accessKeyId\":\"yourAccessKeyId\",\"accessKeySecret\":\"yourAccessKeySecret\",\"bucketName\":\"yourBucketName\"}', '阿里云对象存储配置信息,upload.type=OSS时生效,注意:当服务器与OSS同一地域时,建议填写internalEndPoint,此值表示内网endpoint,在上传时会优先使用内网endpoint。customUrl为自定义域名(需带协议)为空代表不使用自定义域名,示例值:https://www.lframework.com。其他参数均在阿里云控台获取。', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 10:38:10'); +INSERT INTO `sys_parameter` VALUES (11, 'upload.obs.config', '{\"customUrl\":\"\",\"endpoint\":\"yourEndpoint\",\"ak\":\"yourAccessKeyId\",\"sk\":\"yourAccessKeySecret\",\"bucketName\":\"yourBucketName\"}', '华为云对象存储配置信息,upload.type=OBS时生效。customUrl为自定义域名(需带协议)为空代表不使用自定义域名,示例值:https://www.lframework.com。其他参数均在华为云控台获取。', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 10:38:10'); +INSERT INTO `sys_parameter` VALUES (12, 'upload.cos.config', '{\"customUrl\":\"yourCustomUrl\",\"region\":\"yourRegion\",\"secretId\":\"yourSecretId\",\"secretKey\":\"yourSecretKey\",\"bucketName\":\"yourBucketName\"}', '腾讯云对象存储配置信息,upload.type=COS时生效。customUrl为下载文件时的域名,如果使用自定义域名,示例值:https://www.lframework.com,如果不使用自定义域名,那么就填写COS的访问域名。其他参数均在腾讯云控台获取。', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 14:48:02'); + +-- ---------------------------- +-- Table structure for sys_position +-- ---------------------------- +DROP TABLE IF EXISTS `sys_position`; +CREATE TABLE `sys_position` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '岗位编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '岗位名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '岗位' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_position +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role`; +CREATE TABLE `sys_role` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `permission` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO `sys_role` VALUES ('1', '001', '系统管理员', 'admin', 1, '系统管理员', '系统管理员', '1', '2021-05-08 18:04:41', '系统管理员', '1', '2021-05-08 18:04:45'); + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_menu`; +CREATE TABLE `sys_role_menu` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `role_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色ID', + `menu_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `role_id, menu_id`(`role_id`, `menu_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色与菜单关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名', + `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', + `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱', + `telephone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `gender` tinyint(3) NOT NULL DEFAULT 0 COMMENT '性别 0-未知 1-男 2-女', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态 1-在用 0停用', + `lock_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '锁定状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + UNIQUE INDEX `username`(`username`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO `sys_user` VALUES ('1', '001', '系统管理员', 'admin', '$2a$10$IJtHluhnhAYkgvM4PdKuZek5PWbtuxtjB9pB.twZdxg/qrlR4s4q6', 'xingyun@lframework.com', '17600000001', 0, 1, 0, '', '系统管理员', '1', '2021-04-22 22:00:27', '系统管理员', '1', '2023-03-09 13:30:44'); + +-- ---------------------------- +-- Table structure for sys_user_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_dept`; +CREATE TABLE `sys_user_dept` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID', + `dept_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '部门ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `user_id`(`user_id`, `dept_id`) USING BTREE, + INDEX `dept_id`(`dept_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户与部门关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_dept +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_user_position +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_position`; +CREATE TABLE `sys_user_position` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID', + `position_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '岗位ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `user_id`(`user_id`, `position_id`) USING BTREE, + INDEX `position_id`(`position_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户与岗位关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_position +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_role`; +CREATE TABLE `sys_user_role` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID', + `role_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `user_id, role_id`(`user_id`, `role_id`) USING BTREE, + INDEX `role_id`(`role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户与角色关系表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_role +-- ---------------------------- +INSERT INTO `sys_user_role` VALUES ('1', '1', '1'); + +-- ---------------------------- +-- Table structure for sys_user_telephone +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_telephone`; +CREATE TABLE `sys_user_telephone` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `telephone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号', + `user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `telephone`(`telephone`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户绑定手机号表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_telephone +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_logistics_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_logistics_sheet`; +CREATE TABLE `tbl_logistics_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据号', + `logistics_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '物流单号', + `logistics_company_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '物流公司ID', + `sender_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '寄件人姓名', + `sender_telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '寄件人联系电话', + `sender_province_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '寄件人省', + `sender_city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '寄件人市', + `sender_district_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '寄件人区', + `sender_address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '寄件人地址', + `receiver_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收件人姓名', + `receiver_telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收件人联系电话', + `receiver_province_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收件人省', + `receiver_city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收件人市', + `receiver_district_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收件人区', + `receiver_address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收件人地址', + `total_weight` decimal(16, 2) NULL DEFAULT NULL COMMENT '总重量(kg)', + `total_volume` decimal(16, 2) NULL DEFAULT NULL COMMENT '总体积(cm3)', + `total_amount` decimal(16, 2) NULL DEFAULT NULL COMMENT '物流费', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `delivery_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发货人', + `delivery_time` datetime NULL DEFAULT NULL COMMENT '发货时间', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `logistics_no`(`logistics_no`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '物流单' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tbl_logistics_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_logistics_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_logistics_sheet_detail`; +CREATE TABLE `tbl_logistics_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '物流单ID', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX ```biz_id```(`biz_id`, `biz_type`) USING BTREE, + INDEX `sheet_id`(`sheet_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '物流单明细' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tbl_logistics_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_order_chart +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_order_chart`; +CREATE TABLE `tbl_order_chart` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `total_amount` decimal(24, 2) NOT NULL COMMENT '单据总金额', + `create_time` datetime NOT NULL COMMENT '创建时间', + `create_date` varchar(19) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建日期', + `create_hour` varchar(13) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建时间(小时)', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `create_date`(`create_date`) USING BTREE, + INDEX `create_hour`(`create_hour`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单图表数据' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_order_chart +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_order_pay_type +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_order_pay_type`; +CREATE TABLE `tbl_order_pay_type` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单ID', + `pay_type_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '支付方式ID', + `pay_amount` decimal(24, 2) NOT NULL COMMENT '支付金额', + `text` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '支付内容', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单支付方式' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_order_pay_type +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_order_time_line +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_order_time_line`; +CREATE TABLE `tbl_order_time_line` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '描述内容', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '单据时间轴' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_order_time_line +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_pre_take_stock_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_pre_take_stock_sheet`; +CREATE TABLE `tbl_pre_take_stock_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `take_status` tinyint(3) NOT NULL COMMENT '盘点状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存预先盘点单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_pre_take_stock_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_pre_take_stock_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_pre_take_stock_sheet_detail`; +CREATE TABLE `tbl_pre_take_stock_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '预先盘点单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `first_num` int(11) NULL DEFAULT NULL COMMENT '初盘数量', + `second_num` int(11) NULL DEFAULT NULL COMMENT '复盘数量', + `rand_num` int(11) NULL DEFAULT NULL COMMENT '抽盘数量', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存预先盘点单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_pre_take_stock_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_product_stock +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_product_stock`; +CREATE TABLE `tbl_product_stock` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL DEFAULT 0 COMMENT '库存数量', + `tax_price` decimal(24, 6) NOT NULL COMMENT '含税价格', + `tax_amount` decimal(24, 2) NOT NULL COMMENT '含税金额', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `product_id`(`product_id`, `sc_id`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品库存' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_product_stock +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_product_stock_log +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_product_stock_log`; +CREATE TABLE `tbl_product_stock_log` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `ori_tax_price` decimal(24, 6) NOT NULL COMMENT '原含税成本价', + `cur_tax_price` decimal(24, 6) NOT NULL COMMENT '现含税成本价', + `ori_stock_num` int(11) NOT NULL, + `cur_stock_num` int(11) NOT NULL, + `stock_num` int(11) NOT NULL DEFAULT 0 COMMENT '库存数量', + `tax_amount` decimal(24, 2) NOT NULL COMMENT '含税金额', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `biz_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '业务单据ID', + `biz_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '业务单据号', + `biz_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '业务单据明细ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品库存变动记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_product_stock_log +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_purchase_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_config`; +CREATE TABLE `tbl_purchase_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `receive_require_purchase` tinyint(1) NOT NULL DEFAULT 0 COMMENT '采购收货单是否关联采购订单', + `receive_multiple_relate_purchase` tinyint(1) NOT NULL DEFAULT 0 COMMENT '采购收货单是否多次关联采购订单', + `purchase_return_require_receive` tinyint(1) NOT NULL DEFAULT 0 COMMENT '采购退货单是否关联采购收货单', + `purchase_return_multiple_relate_receive` tinyint(1) NOT NULL DEFAULT 0 COMMENT '采购退货单是否多次关联采购收货单', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购参数设置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_purchase_config +-- ---------------------------- +INSERT INTO `tbl_purchase_config` VALUES ('1', 1, 1, 1, 1); + +-- ---------------------------- +-- Table structure for tbl_purchase_order +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_order`; +CREATE TABLE `tbl_purchase_order` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `purchaser_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '采购员ID', + `expect_arrive_date` date NULL DEFAULT NULL COMMENT '预计到货日期', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '采购数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '采购金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购订单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_purchase_order +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_purchase_order_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_order_detail`; +CREATE TABLE `tbl_purchase_order_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '采购数量', + `tax_price` decimal(16, 2) NOT NULL COMMENT '采购价', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `receive_num` int(11) NOT NULL DEFAULT 0 COMMENT '已收货数量', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购订单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_purchase_order_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_purchase_return +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_return`; +CREATE TABLE `tbl_purchase_return` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `purchaser_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '采购员ID', + `payment_date` date NULL DEFAULT NULL COMMENT '付款日期', + `receive_sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货单ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '退货金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `tx_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) NULL DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE, + INDEX `receive_sheet_id`(`receive_sheet_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购退单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_purchase_return +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_purchase_return_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_return_detail`; +CREATE TABLE `tbl_purchase_return_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `return_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收货单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `return_num` int(11) NOT NULL COMMENT '退货数量', + `tax_price` decimal(16, 2) NOT NULL COMMENT '采购价', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `receive_sheet_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货单明细ID', + PRIMARY KEY (`id`) USING BTREE, + INDEX `return_id`(`return_id`) USING BTREE, + INDEX `receive_sheet_detail_id`(`receive_sheet_detail_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购退单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_purchase_return_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_receive_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_receive_sheet`; +CREATE TABLE `tbl_receive_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `supplier_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '供应商ID', + `purchaser_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '采购员ID', + `payment_date` date NULL DEFAULT NULL COMMENT '付款日期', + `receive_date` date NULL DEFAULT NULL COMMENT '到货日期', + `purchase_order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '采购单ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '收货金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `tx_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) NULL DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `supplier_id`(`supplier_id`) USING BTREE, + INDEX `purchase_order_id`(`purchase_order_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购收货单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_receive_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_receive_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_receive_sheet_detail`; +CREATE TABLE `tbl_receive_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收货单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '采购数量', + `tax_price` decimal(16, 2) NOT NULL COMMENT '采购价', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `purchase_order_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '采购订单明细ID', + `return_num` int(11) NOT NULL DEFAULT 0 COMMENT '已退货数量', + PRIMARY KEY (`id`) USING BTREE, + INDEX `sheet_id`(`sheet_id`) USING BTREE, + INDEX `purchase_order_detail_id`(`purchase_order_detail_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '采购收货单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_receive_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_retail_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_config`; +CREATE TABLE `tbl_retail_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `retail_out_sheet_require_member` tinyint(1) NOT NULL DEFAULT 1 COMMENT '零售出库单上的会员是否必填', + `retail_return_require_out_stock` tinyint(1) NOT NULL DEFAULT 0 COMMENT '零售退货单是否关联零售出库单', + `retail_return_multiple_relate_out_stock` tinyint(1) NOT NULL DEFAULT 0 COMMENT '零售退货单是否多次关联零售出库单', + `retail_return_require_member` tinyint(1) NOT NULL DEFAULT 1 COMMENT '零售退货单上的会员是否必填', + `retail_out_sheet_require_logistics` tinyint(1) NOT NULL DEFAULT 0 COMMENT '零售出库单是否需要发货', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售参数设置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_config +-- ---------------------------- +INSERT INTO `tbl_retail_config` VALUES ('1', 0, 0, 1, 0, 0); + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet`; +CREATE TABLE `tbl_retail_out_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `member_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '会员ID', + `saler_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售员ID', + `payment_date` date NULL DEFAULT NULL COMMENT '付款日期', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '出库金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `member_id`(`member_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售出库单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet_detail`; +CREATE TABLE `tbl_retail_out_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '出库单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `ori_price` decimal(16, 2) NOT NULL COMMENT '原价', + `tax_price` decimal(16, 2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16, 2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `return_num` int(11) NOT NULL DEFAULT 0 COMMENT '已退货数量', + `ori_bundle_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组合商品原始明细ID', + PRIMARY KEY (`id`) USING BTREE, + INDEX `sheet_id`(`sheet_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售出库单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet_detail_bundle +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet_detail_bundle`; +CREATE TABLE `tbl_retail_out_sheet_detail_bundle` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '出库单ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `main_product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '组合商品ID', + `order_num` int(11) NOT NULL DEFAULT 0 COMMENT '组合商品数量', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品ID', + `product_order_num` int(11) NOT NULL COMMENT '单品数量', + `product_ori_price` decimal(16, 2) NOT NULL COMMENT '单品原价', + `product_tax_price` decimal(16, 2) NOT NULL COMMENT '单品含税价格', + `product_tax_rate` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品税率', + `product_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '单品明细ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `product_detail_id`) USING BTREE, + INDEX `detail_id`(`detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售出库单组合商品明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet_detail_bundle +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet_detail_lot +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet_detail_lot`; +CREATE TABLE `tbl_retail_out_sheet_detail_lot` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `return_num` int(11) NOT NULL DEFAULT 0 COMMENT '已退货数量', + `cost_tax_amount` decimal(24, 2) NOT NULL COMMENT '含税成本金额', + `settle_status` tinyint(3) NOT NULL COMMENT '结算状态', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + INDEX `detail_id`(`detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售出库单批次明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet_detail_lot +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_retail_return +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_return`; +CREATE TABLE `tbl_retail_return` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `member_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '会员ID', + `saler_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售员ID', + `payment_date` date NULL DEFAULT NULL COMMENT '付款日期', + `out_sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '出库单ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '退货金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `out_sheet_id`(`out_sheet_id`) USING BTREE, + INDEX `member_id`(`member_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售退单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_return +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_retail_return_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_return_detail`; +CREATE TABLE `tbl_retail_return_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `return_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '退货单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `return_num` int(11) NOT NULL COMMENT '退货数量', + `ori_price` decimal(16, 2) NOT NULL COMMENT '原价', + `tax_price` decimal(16, 2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16, 2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `out_sheet_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '出库单明细ID', + PRIMARY KEY (`id`) USING BTREE, + INDEX `return_id`(`return_id`) USING BTREE, + INDEX `out_sheet_detail_id`(`out_sheet_detail_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '零售退单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_retail_return_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_config`; +CREATE TABLE `tbl_sale_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `out_stock_require_sale` tinyint(1) NOT NULL DEFAULT 0 COMMENT '销售出库单是否关联销售订单', + `out_stock_multiple_relate_sale` tinyint(1) NOT NULL DEFAULT 0 COMMENT '销售出库单是否多次关联销售订单', + `sale_return_require_out_stock` tinyint(1) NOT NULL DEFAULT 0 COMMENT '销售退货单是否关联销售出库单', + `sale_return_multiple_relate_out_stock` tinyint(1) NOT NULL DEFAULT 0 COMMENT '销售退货单是否多次关联销售出库单', + `out_stock_require_logistics` tinyint(1) NOT NULL DEFAULT 0 COMMENT '销售出库单是否需要物流单', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售参数设置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_config +-- ---------------------------- +INSERT INTO `tbl_sale_config` VALUES ('1', 0, 0, 0, 0, 0); + +-- ---------------------------- +-- Table structure for tbl_sale_order +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_order`; +CREATE TABLE `tbl_sale_order` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `saler_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售员ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '销售数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '销售金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售订单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_order +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_order_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_order_detail`; +CREATE TABLE `tbl_sale_order_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '销售数量', + `ori_price` decimal(16, 2) NOT NULL COMMENT '原价', + `tax_price` decimal(16, 2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16, 2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `out_num` int(11) NOT NULL DEFAULT 0 COMMENT '已出库数量', + `ori_bundle_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组合商品原始明细ID', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售订单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_order_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_order_detail_bundle +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_order_detail_bundle`; +CREATE TABLE `tbl_sale_order_detail_bundle` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '销售单ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `main_product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '组合商品ID', + `order_num` int(11) NOT NULL DEFAULT 0 COMMENT '组合商品数量', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品ID', + `product_order_num` int(11) NOT NULL COMMENT '单品数量', + `product_ori_price` decimal(16, 2) NOT NULL COMMENT '单品原价', + `product_tax_price` decimal(16, 2) NOT NULL COMMENT '单品含税价格', + `product_tax_rate` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品税率', + `product_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '单品明细ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `order_id`(`order_id`, `product_detail_id`) USING BTREE, + INDEX `detail_id`(`detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售单组合商品明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_order_detail_bundle +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet`; +CREATE TABLE `tbl_sale_out_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `saler_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售员ID', + `payment_date` date NULL DEFAULT NULL COMMENT '付款日期', + `sale_order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售单ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '出库金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `tx_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) NULL DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE, + INDEX `sale_order_id`(`sale_order_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售出库单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet_detail`; +CREATE TABLE `tbl_sale_out_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '出库单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `ori_price` decimal(16, 2) NOT NULL COMMENT '原价', + `tax_price` decimal(16, 2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16, 2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `sale_order_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售订单明细ID', + `ori_bundle_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组合商品原始明细ID', + `return_num` int(11) NOT NULL DEFAULT 0 COMMENT '已退货数量', + PRIMARY KEY (`id`) USING BTREE, + INDEX `sheet_id`(`sheet_id`) USING BTREE, + INDEX `purchase_order_detail_id`(`sale_order_detail_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售出库单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet_detail_bundle +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet_detail_bundle`; +CREATE TABLE `tbl_sale_out_sheet_detail_bundle` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '出库单ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `main_product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '组合商品ID', + `order_num` int(11) NOT NULL DEFAULT 0 COMMENT '组合商品数量', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品ID', + `product_order_num` int(11) NOT NULL COMMENT '单品数量', + `product_ori_price` decimal(16, 2) NOT NULL COMMENT '单品原价', + `product_tax_price` decimal(16, 2) NOT NULL COMMENT '单品含税价格', + `product_tax_rate` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单品税率', + `product_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '单品明细ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `product_detail_id`) USING BTREE, + INDEX `detail_id`(`detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售出库单组合商品明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet_detail_bundle +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet_detail_lot +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet_detail_lot`; +CREATE TABLE `tbl_sale_out_sheet_detail_lot` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `return_num` int(11) NOT NULL DEFAULT 0 COMMENT '已退货数量', + `cost_tax_amount` decimal(24, 2) NOT NULL COMMENT '含税成本金额', + `settle_status` tinyint(3) NOT NULL COMMENT '结算状态', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + INDEX `detail_id`(`detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售出库单批次明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet_detail_lot +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_return +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_return`; +CREATE TABLE `tbl_sale_return` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `customer_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客户ID', + `saler_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '销售员ID', + `payment_date` date NULL DEFAULT NULL COMMENT '付款日期', + `out_sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '出库单ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT 0 COMMENT '赠品数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '退货金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `tx_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) NULL DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE, + INDEX `customer_id`(`customer_id`) USING BTREE, + INDEX `out_sheet_id`(`out_sheet_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售退单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_return +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sale_return_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_return_detail`; +CREATE TABLE `tbl_sale_return_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `return_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '退货单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `return_num` int(11) NOT NULL COMMENT '退货数量', + `ori_price` decimal(16, 2) NOT NULL COMMENT '原价', + `tax_price` decimal(16, 2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16, 2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否赠品', + `tax_rate` decimal(16, 2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '结算状态', + `out_sheet_detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '出库单明细ID', + PRIMARY KEY (`id`) USING BTREE, + INDEX `return_id`(`return_id`) USING BTREE, + INDEX `out_sheet_detail_id`(`out_sheet_detail_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '销售退单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sale_return_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sc_transfer_order +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sc_transfer_order`; +CREATE TABLE `tbl_sc_transfer_order` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `source_sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '转出仓库ID', + `target_sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '转入仓库ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '调拨数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '调拨成本金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `source_sc_id`(`source_sc_id`) USING BTREE, + INDEX `target_sc_id`(`target_sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库调拨单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sc_transfer_order +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sc_transfer_order_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sc_transfer_order_detail`; +CREATE TABLE `tbl_sc_transfer_order_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '调拨单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `transfer_num` int(11) NOT NULL COMMENT '调拨数量', + `tax_price` decimal(16, 2) NULL DEFAULT NULL COMMENT '成本价', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `receive_num` int(11) NOT NULL DEFAULT 0 COMMENT '已收货数量', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库调拨单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sc_transfer_order_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_sc_transfer_order_detail_receive +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sc_transfer_order_detail_receive`; +CREATE TABLE `tbl_sc_transfer_order_detail_receive` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '调拨单ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `receive_num` int(11) NOT NULL COMMENT '收货数量', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`, `detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库调拨单收货明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_sc_transfer_order_detail_receive +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_shop +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_shop`; +CREATE TABLE `tbl_shop` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `dept_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门ID', + `lng` decimal(16, 6) NULL DEFAULT NULL COMMENT '经度', + `lat` decimal(16, 6) NULL DEFAULT NULL COMMENT '纬度', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态 1-在用 0停用', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '门店' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_shop +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_stock_adjust_reason +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_adjust_reason`; +CREATE TABLE `tbl_stock_adjust_reason` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存调整原因' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_stock_adjust_reason +-- ---------------------------- +INSERT INTO `tbl_stock_adjust_reason` VALUES ('1', '001', '初始化数据', 1, '系统内置', '系统管理员', '1', '2023-04-18 14:04:34', '系统管理员', '1', '2023-04-18 14:04:53'); +INSERT INTO `tbl_stock_adjust_reason` VALUES ('2', '002', '损溢', 1, '系统内置', '系统管理员', '1', '2023-04-18 14:04:34', '系统管理员', '1', '2023-04-18 14:04:53'); +INSERT INTO `tbl_stock_adjust_reason` VALUES ('3', '003', '其他', 1, '系统内置', '系统管理员', '1', '2023-04-18 14:04:34', '系统管理员', '1', '2023-04-18 14:04:53'); + +-- ---------------------------- +-- Table structure for tbl_stock_adjust_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_adjust_sheet`; +CREATE TABLE `tbl_stock_adjust_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `reason_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '调整原因ID', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存调整单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_stock_adjust_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_stock_adjust_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_adjust_sheet_detail`; +CREATE TABLE `tbl_stock_adjust_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL COMMENT '调整库存数量', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存调整单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_stock_adjust_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_stock_cost_adjust_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_cost_adjust_sheet`; +CREATE TABLE `tbl_stock_cost_adjust_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `product_num` int(11) NOT NULL COMMENT '调价品种数', + `diff_amount` decimal(24, 2) NOT NULL COMMENT '库存调价差额', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存成本调整单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_stock_cost_adjust_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_stock_cost_adjust_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_cost_adjust_sheet_detail`; +CREATE TABLE `tbl_stock_cost_adjust_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单据ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL COMMENT '库存数量', + `purchase_price` decimal(16, 2) NOT NULL COMMENT '档案采购价', + `ori_price` decimal(16, 2) NOT NULL COMMENT '调整前成本价', + `price` decimal(16, 2) NOT NULL COMMENT '调整后成本价', + `diff_amount` decimal(24, 2) NOT NULL COMMENT '库存调价差额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存成本调整单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_stock_cost_adjust_sheet_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_take_stock_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_config`; +CREATE TABLE `tbl_take_stock_config` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `show_product` tinyint(1) NOT NULL DEFAULT 0 COMMENT '库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据', + `show_stock` tinyint(1) NOT NULL DEFAULT 0 COMMENT '库存盘点单是否显示盘点任务创建时商品的系统库存数量', + `auto_change_stock` tinyint(1) NOT NULL DEFAULT 0 COMMENT '盘点差异生成时是否自动调整盘点任务中商品的系统库存数量', + `allow_change_num` tinyint(1) NOT NULL DEFAULT 0 COMMENT '盘点差异单中的盘点数量是否允许手动修改', + `cancel_hours` int(11) NOT NULL DEFAULT 24 COMMENT '盘点任务创建后多少小时内内未完成,则自动作废', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存盘点参数设置' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_take_stock_config +-- ---------------------------- +INSERT INTO `tbl_take_stock_config` VALUES ('1', 1, 1, 1, 1, 168); + +-- ---------------------------- +-- Table structure for tbl_take_stock_plan +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_plan`; +CREATE TABLE `tbl_take_stock_plan` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `take_type` tinyint(3) NOT NULL COMMENT '盘点类别', + `biz_id` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '业务ID', + `take_status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '盘点状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存盘点任务' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_take_stock_plan +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_take_stock_plan_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_plan_detail`; +CREATE TABLE `tbl_take_stock_plan_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `plan_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '盘点任务ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL COMMENT '初始库存数量', + `ori_take_num` int(11) NULL DEFAULT NULL COMMENT '盘点数量', + `take_num` int(11) NULL DEFAULT NULL COMMENT '修改后的盘点数量', + `total_out_num` int(11) NOT NULL DEFAULT 0 COMMENT '出项数量', + `total_in_num` int(11) NOT NULL DEFAULT 0 COMMENT '入项数量', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL DEFAULT 0 COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `plan_id`(`plan_id`, `product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存盘点任务明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_take_stock_plan_detail +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_take_stock_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_sheet`; +CREATE TABLE `tbl_take_stock_sheet` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务单据号', + `plan_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '盘点任务ID', + `pre_sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '预先盘点单ID', + `sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库ID', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `plan_id`(`plan_id`) USING BTREE, + INDEX `sc_id`(`sc_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存盘点单' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_take_stock_sheet +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tbl_take_stock_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_sheet_detail`; +CREATE TABLE `tbl_take_stock_sheet_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '盘点单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `take_num` int(11) NOT NULL COMMENT '盘点数量', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sheet_id`(`sheet_id`, `product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存盘点单明细' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of tbl_take_stock_sheet_detail +-- ---------------------------- + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/xingyun-api/src/main/resources/db/migration/platform/V1.0__init.sql b/xingyun-api/src/main/resources/db/migration/platform/V1.0__init.sql new file mode 100644 index 0000000..8fa0426 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/platform/V1.0__init.sql @@ -0,0 +1,313 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for qrtz_blob_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_blob_triggers`; +CREATE TABLE `qrtz_blob_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(190) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + `BLOB_DATA` blob, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_blob_triggers +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_calendars +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_calendars`; +CREATE TABLE `qrtz_calendars` ( + `SCHED_NAME` varchar(120) NOT NULL, + `CALENDAR_NAME` varchar(190) NOT NULL, + `CALENDAR` blob NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_calendars +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_cron_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_cron_triggers`; +CREATE TABLE `qrtz_cron_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(190) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + `CRON_EXPRESSION` varchar(120) NOT NULL, + `TIME_ZONE_ID` varchar(80) DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_cron_triggers +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_fired_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_fired_triggers`; +CREATE TABLE `qrtz_fired_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `ENTRY_ID` varchar(95) NOT NULL, + `TRIGGER_NAME` varchar(190) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + `INSTANCE_NAME` varchar(190) NOT NULL, + `FIRED_TIME` bigint(13) NOT NULL, + `SCHED_TIME` bigint(13) NOT NULL, + `PRIORITY` int(11) NOT NULL, + `STATE` varchar(16) NOT NULL, + `JOB_NAME` varchar(190) DEFAULT NULL, + `JOB_GROUP` varchar(190) DEFAULT NULL, + `IS_NONCONCURRENT` varchar(1) DEFAULT NULL, + `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), + KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), + KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), + KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_fired_triggers +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_job_details +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_job_details`; +CREATE TABLE `qrtz_job_details` ( + `SCHED_NAME` varchar(120) NOT NULL, + `JOB_NAME` varchar(190) NOT NULL, + `JOB_GROUP` varchar(190) NOT NULL, + `DESCRIPTION` varchar(250) DEFAULT NULL, + `JOB_CLASS_NAME` varchar(250) NOT NULL, + `IS_DURABLE` varchar(1) NOT NULL, + `IS_NONCONCURRENT` varchar(1) NOT NULL, + `IS_UPDATE_DATA` varchar(1) NOT NULL, + `REQUESTS_RECOVERY` varchar(1) NOT NULL, + `JOB_DATA` blob, + PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), + KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_job_details +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_locks +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_locks`; +CREATE TABLE `qrtz_locks` ( + `SCHED_NAME` varchar(120) NOT NULL, + `LOCK_NAME` varchar(40) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_locks +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_paused_trigger_grps +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; +CREATE TABLE `qrtz_paused_trigger_grps` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_paused_trigger_grps +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_scheduler_state +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_scheduler_state`; +CREATE TABLE `qrtz_scheduler_state` ( + `SCHED_NAME` varchar(120) NOT NULL, + `INSTANCE_NAME` varchar(190) NOT NULL, + `LAST_CHECKIN_TIME` bigint(13) NOT NULL, + `CHECKIN_INTERVAL` bigint(13) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_scheduler_state +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_simple_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simple_triggers`; +CREATE TABLE `qrtz_simple_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(190) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + `REPEAT_COUNT` bigint(7) NOT NULL, + `REPEAT_INTERVAL` bigint(12) NOT NULL, + `TIMES_TRIGGERED` bigint(10) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_simple_triggers +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_simprop_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simprop_triggers`; +CREATE TABLE `qrtz_simprop_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(190) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + `STR_PROP_1` varchar(512) DEFAULT NULL, + `STR_PROP_2` varchar(512) DEFAULT NULL, + `STR_PROP_3` varchar(512) DEFAULT NULL, + `INT_PROP_1` int(11) DEFAULT NULL, + `INT_PROP_2` int(11) DEFAULT NULL, + `LONG_PROP_1` bigint(20) DEFAULT NULL, + `LONG_PROP_2` bigint(20) DEFAULT NULL, + `DEC_PROP_1` decimal(13,4) DEFAULT NULL, + `DEC_PROP_2` decimal(13,4) DEFAULT NULL, + `BOOL_PROP_1` varchar(1) DEFAULT NULL, + `BOOL_PROP_2` varchar(1) DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_simprop_triggers +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for qrtz_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_triggers`; +CREATE TABLE `qrtz_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(190) NOT NULL, + `TRIGGER_GROUP` varchar(190) NOT NULL, + `JOB_NAME` varchar(190) NOT NULL, + `JOB_GROUP` varchar(190) NOT NULL, + `DESCRIPTION` varchar(250) DEFAULT NULL, + `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, + `PREV_FIRE_TIME` bigint(13) DEFAULT NULL, + `PRIORITY` int(11) DEFAULT NULL, + `TRIGGER_STATE` varchar(16) NOT NULL, + `TRIGGER_TYPE` varchar(8) NOT NULL, + `START_TIME` bigint(13) NOT NULL, + `END_TIME` bigint(13) DEFAULT NULL, + `CALENDAR_NAME` varchar(190) DEFAULT NULL, + `MISFIRE_INSTR` smallint(2) DEFAULT NULL, + `JOB_DATA` blob, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), + KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), + KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), + KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), + KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), + KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), + CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Records of qrtz_triggers +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_open_domain +-- ---------------------------- +DROP TABLE IF EXISTS `sys_open_domain`; +CREATE TABLE `sys_open_domain` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `api_secret` varchar(100) NOT NULL COMMENT 'API秘钥', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `tenant_id` int(11) DEFAULT NULL COMMENT '租户ID', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放域'; + +-- ---------------------------- +-- Records of sys_open_domain +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tenant +-- ---------------------------- +DROP TABLE IF EXISTS `tenant`; +CREATE TABLE `tenant` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(200) NOT NULL COMMENT '名称', + `jdbc_url` varchar(400) NOT NULL COMMENT 'JDBC连接地址', + `jdbc_username` varchar(200) NOT NULL COMMENT 'JDBC用户名', + `jdbc_password` varchar(200) NOT NULL COMMENT 'JDBC密码', + `available` tinyint(1) NOT NULL COMMENT '状态', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8mb4 COMMENT='租户'; + +-- ---------------------------- +-- Records of tenant +-- ---------------------------- +BEGIN; +INSERT INTO `tenant` (`id`, `name`, `jdbc_url`, `jdbc_username`, `jdbc_password`, `available`, `create_time`, `update_time`) VALUES (1000, '测试租户', 'jdbc:mysql://127.0.0.1:3306/xingyun', 'root', '123456', 1, '2022-12-31 22:59:21', '2023-03-13 22:14:07'); +COMMIT; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/xingyun-api/src/main/resources/db/migration/platform/V1.1__sys_module.sql b/xingyun-api/src/main/resources/db/migration/platform/V1.1__sys_module.sql new file mode 100644 index 0000000..f569d31 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/platform/V1.1__sys_module.sql @@ -0,0 +1,61 @@ +DROP TABLE IF EXISTS `sys_module`; +CREATE TABLE `sys_module` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统模块' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_module +-- ---------------------------- +INSERT INTO `sys_module` VALUES (1, '平台管理', '系统平台的核心模块。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (2, '系统管理', '维护企业、系统基础数据,包括部门、岗位、角色、系统菜单和参数等。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (3, '基础信息管理', '维护基础业务数据,包括仓库、客户、供应商、会员等。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (4, '商品中心', '管理商品核心数据。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (5, '采购业务', '管理供应商与企业的采购业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (6, '销售业务', '管理企业与TOB端大客户的销售业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (7, '零售业务', '管理企业与TOC端会员的零售业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (8, '库存管理及调拨', '查询商品库存和进行商品调拨。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (9, '库存盘点', '库存商品盘点。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (10, '库存调整', '商品库存数量和成本调整。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (11, '结算管理', '企业与供应商、客户进行结算。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (12, '开发管理', '系统快捷开发,如管理定时器、数据实体、数据对象、表单生成等。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (13, '便捷办公', '支持文件收纳和在线Excel。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (14, '开放平台', '系统开放平台管理。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); +INSERT INTO `sys_module` VALUES (15, '物流发货', '管理企业物流业务。', '系统管理员', '1', '2023-06-06 10:26:30', '系统管理员', '1', '2023-06-06 10:26:41'); + +DROP TABLE IF EXISTS `sys_module_tenant`; +CREATE TABLE `sys_module_tenant` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `module_id` int(11) NOT NULL COMMENT '模块ID', + `tenant_id` int(11) NOT NULL COMMENT '租户ID', + `expire_time` datetime NOT NULL COMMENT '过期时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `name`(`tenant_id`, `module_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '租户和系统模块关系表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_module_tenant +-- ---------------------------- +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875135', 1, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875136', 2, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875137', 3, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875138', 4, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875139', 5, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875140', 6, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875141', 7, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875142', 8, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875143', 9, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875144', 10, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875145', 11, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875146', 12, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875147', 13, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875148', 14, 1000, '2099-01-01 00:00:00'); +INSERT INTO `sys_module_tenant` VALUES ('1666286094246875149', 15, 1000, '2099-01-01 00:00:00'); \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/platform/V1.2__dynamic_api.sql b/xingyun-api/src/main/resources/db/migration/platform/V1.2__dynamic_api.sql new file mode 100644 index 0000000..479c2db --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/platform/V1.2__dynamic_api.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS `magic_api_file`; +CREATE TABLE `magic_api_file` ( + `file_path` varchar(512) NOT NULL, + `file_content` mediumtext, + PRIMARY KEY (`file_path`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +DROP TABLE IF EXISTS `magic_api_file_backup`; +CREATE TABLE `magic_api_file_backup` ( + `id` varchar(32) NOT NULL COMMENT '原对象ID', + `create_date` bigint(13) NOT NULL COMMENT '备份时间', + `tag` varchar(32) DEFAULT NULL COMMENT '标签', + `type` varchar(32) DEFAULT NULL COMMENT '类型', + `name` varchar(64) DEFAULT NULL COMMENT '原名称', + `content` blob COMMENT '备份内容', + `create_by` varchar(64) DEFAULT NULL COMMENT '操作人', + PRIMARY KEY (`id`,`create_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/platform/V1.3__update_qrtz_details.sql b/xingyun-api/src/main/resources/db/migration/platform/V1.3__update_qrtz_details.sql new file mode 100644 index 0000000..f54b633 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/platform/V1.3__update_qrtz_details.sql @@ -0,0 +1 @@ +UPDATE `qrtz_job_details` SET `JOB_CLASS_NAME` = 'com.lframework.xingyun.template.inner.config.OpLogTimerConfiguration$OpLogClearJob' WHERE `qrtz_job_details`.`SCHED_NAME` = 'quartzScheduler' AND `qrtz_job_details`.`JOB_NAME` = 'OP_LOG_TIMER' AND `qrtz_job_details`.`JOB_GROUP` = 'OP_LOG_TIMER_GROUP'; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/platform/V1.4__v3.sql b/xingyun-api/src/main/resources/db/migration/platform/V1.4__v3.sql new file mode 100644 index 0000000..f598d81 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/platform/V1.4__v3.sql @@ -0,0 +1 @@ +UPDATE `tenant` SET jdbc_password = '24590d72bfb4d71ccbc533570aa9627b' WHERE jdbc_password = '123456'; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.0__init.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.0__init.sql new file mode 100644 index 0000000..4250d19 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.0__init.sql @@ -0,0 +1,6806 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for base_data_customer +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_customer`; +CREATE TABLE `base_data_customer` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `mnemonic_code` varchar(20) NOT NULL COMMENT '助记码', + `contact` varchar(100) DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) DEFAULT NULL COMMENT '电子邮箱', + `zip_code` varchar(20) DEFAULT NULL COMMENT '邮编', + `fax` varchar(100) DEFAULT NULL COMMENT '传真', + `city_id` varchar(32) DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) DEFAULT NULL COMMENT '地址', + `receiver` varchar(100) DEFAULT NULL COMMENT '收货人', + `receive_telephone` varchar(20) DEFAULT NULL COMMENT '收货手机号', + `receive_address` varchar(200) DEFAULT NULL COMMENT '收货地址', + `settle_type` tinyint(3) NOT NULL DEFAULT '1' COMMENT '结算方式', + `credit_code` varchar(100) DEFAULT NULL COMMENT '统一社会信用代码', + `tax_identify_no` varchar(100) DEFAULT NULL COMMENT '纳税人识别号', + `bank_name` varchar(100) DEFAULT NULL COMMENT '开户银行', + `account_name` varchar(100) DEFAULT NULL COMMENT '户名', + `account_no` varchar(100) DEFAULT NULL COMMENT '银行账号', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户'; + +-- ---------------------------- +-- Records of base_data_customer +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_member +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_member`; +CREATE TABLE `base_data_member` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `gender` tinyint(3) NOT NULL DEFAULT '0' COMMENT '性别', + `telephone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) DEFAULT NULL COMMENT '电子邮箱', + `birthday` date DEFAULT NULL COMMENT '出生日期', + `join_day` date NOT NULL COMMENT '入会日期', + `shop_id` varchar(32) DEFAULT NULL COMMENT '所属门店', + `guider_id` varchar(32) DEFAULT NULL COMMENT '所属导购', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + UNIQUE KEY `telephone` (`telephone`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员'; + +-- ---------------------------- +-- Records of base_data_member +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product`; +CREATE TABLE `base_data_product` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(100) NOT NULL COMMENT '名称', + `short_name` varchar(100) DEFAULT NULL COMMENT '简称', + `sku_code` varchar(100) NOT NULL COMMENT 'SKU', + `external_code` varchar(100) DEFAULT NULL COMMENT '外部编号', + `category_id` varchar(32) NOT NULL COMMENT '类目ID', + `brand_id` varchar(32) NOT NULL COMMENT '品牌ID', + `tax_rate` decimal(16,2) NOT NULL COMMENT '进项税率(%)', + `sale_tax_rate` decimal(16,2) NOT NULL COMMENT '销项税率', + `spec` varchar(20) DEFAULT NULL COMMENT '规格', + `unit` varchar(20) DEFAULT NULL COMMENT '单位', + `available` tinyint(1) NOT NULL COMMENT '状态', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`) USING BTREE, + UNIQUE KEY `sku_code` (`sku_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品'; + +-- ---------------------------- +-- Records of base_data_product +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_brand +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_brand`; +CREATE TABLE `base_data_product_brand` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `short_name` varchar(20) DEFAULT '' COMMENT '简称', + `logo` longtext COMMENT 'logo', + `introduction` varchar(400) NOT NULL DEFAULT '' COMMENT '简介', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品品牌'; + +-- ---------------------------- +-- Records of base_data_product_brand +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_category +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_category`; +CREATE TABLE `base_data_product_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(100) NOT NULL COMMENT '名称', + `parent_id` varchar(32) DEFAULT NULL COMMENT '父级ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品类目'; + +-- ---------------------------- +-- Records of base_data_product_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_category_property +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_category_property`; +CREATE TABLE `base_data_product_category_property` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `property_id` varchar(32) NOT NULL COMMENT '商品属性ID', + `category_id` varchar(32) NOT NULL COMMENT '商品类目ID', + PRIMARY KEY (`id`), + UNIQUE KEY `property_id` (`property_id`,`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品类目和商品属性关系表'; + +-- ---------------------------- +-- Records of base_data_product_category_property +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_property +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_property`; +CREATE TABLE `base_data_product_property` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `is_required` tinyint(1) NOT NULL COMMENT '是否必填', + `column_type` tinyint(3) NOT NULL COMMENT '录入类型', + `column_data_type` tinyint(3) DEFAULT NULL COMMENT '数据类型', + `property_type` tinyint(3) NOT NULL COMMENT '属性类别', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品属性'; + +-- ---------------------------- +-- Records of base_data_product_property +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_property_item +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_property_item`; +CREATE TABLE `base_data_product_property_item` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `property_id` varchar(32) NOT NULL COMMENT '属性ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `property_id` (`property_id`,`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品属性值'; + +-- ---------------------------- +-- Records of base_data_product_property_item +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_property_relation +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_property_relation`; +CREATE TABLE `base_data_product_property_relation` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `property_id` varchar(32) NOT NULL COMMENT '商品属性ID', + `property_item_id` varchar(32) DEFAULT NULL COMMENT '属性值ID', + `property_text` varchar(100) DEFAULT NULL COMMENT '商品属性值', + PRIMARY KEY (`id`), + KEY `product_id` (`product_id`,`property_id`,`property_item_id`) USING BTREE, + KEY `property_id` (`property_id`,`property_item_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品和商品属性关系表'; + +-- ---------------------------- +-- Records of base_data_product_property_relation +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_purchase +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_purchase`; +CREATE TABLE `base_data_product_purchase` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `price` decimal(24,2) NOT NULL COMMENT '采购价', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品采购价'; + +-- ---------------------------- +-- Records of base_data_product_purchase +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_retail +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_retail`; +CREATE TABLE `base_data_product_retail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `price` decimal(24,2) NOT NULL COMMENT '零售价', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品零售价'; + +-- ---------------------------- +-- Records of base_data_product_retail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_product_sale +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_product_sale`; +CREATE TABLE `base_data_product_sale` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `price` decimal(24,2) NOT NULL COMMENT '销售价', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品销售价'; + +-- ---------------------------- +-- Records of base_data_product_sale +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_store_center +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_store_center`; +CREATE TABLE `base_data_store_center` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `contact` varchar(100) DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) DEFAULT NULL COMMENT '联系人手机号码', + `city_id` varchar(32) DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) DEFAULT NULL COMMENT '地址', + `people_num` int(11) DEFAULT NULL COMMENT '仓库人数', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='仓库'; + +-- ---------------------------- +-- Records of base_data_store_center +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for base_data_supplier +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_supplier`; +CREATE TABLE `base_data_supplier` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `mnemonic_code` varchar(20) NOT NULL COMMENT '助记码', + `contact` varchar(100) DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) DEFAULT NULL COMMENT '电子邮箱', + `zip_code` varchar(20) DEFAULT NULL COMMENT '邮编', + `fax` varchar(100) DEFAULT NULL COMMENT '传真', + `city_id` varchar(32) DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) DEFAULT NULL COMMENT '地址', + `delivery_address` varchar(200) DEFAULT NULL COMMENT '发货地址', + `delivery_cycle` int(11) DEFAULT NULL COMMENT '发货周期(天)', + `manage_type` tinyint(3) NOT NULL DEFAULT '1' COMMENT '经营方式', + `settle_type` tinyint(3) NOT NULL DEFAULT '1' COMMENT '结算方式', + `credit_code` varchar(100) DEFAULT NULL COMMENT '统一社会信用代码', + `tax_identify_no` varchar(100) DEFAULT NULL COMMENT '纳税人识别号', + `bank_name` varchar(100) DEFAULT NULL COMMENT '开户银行', + `account_name` varchar(100) DEFAULT NULL COMMENT '户名', + `account_no` varchar(100) DEFAULT NULL COMMENT '银行账号', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商'; + +-- ---------------------------- +-- Records of base_data_supplier +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_check_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_check_sheet`; +CREATE TABLE `customer_settle_check_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `total_pay_amount` decimal(24,2) NOT NULL COMMENT '应付金额', + `total_payed_amount` decimal(24,2) NOT NULL COMMENT '已付金额', + `total_discount_amount` decimal(24,2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `customer_id` (`customer_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户对账单'; + +-- ---------------------------- +-- Records of customer_settle_check_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_check_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_check_sheet_detail`; +CREATE TABLE `customer_settle_check_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '对账单ID', + `biz_id` varchar(32) NOT NULL COMMENT '单据ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `calc_type` tinyint(3) NOT NULL COMMENT '计算类型', + `pay_amount` decimal(24,2) NOT NULL COMMENT '应付金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `sheet_id` (`sheet_id`,`biz_id`) USING BTREE, + KEY `biz_id` (`biz_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户对账单明细'; + +-- ---------------------------- +-- Records of customer_settle_check_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_fee_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_fee_sheet`; +CREATE TABLE `customer_settle_fee_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `sheet_type` tinyint(3) NOT NULL COMMENT '单据类型', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `customer_id` (`customer_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户费用单'; + +-- ---------------------------- +-- Records of customer_settle_fee_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_fee_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_fee_sheet_detail`; +CREATE TABLE `customer_settle_fee_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '费用单ID', + `item_id` varchar(32) NOT NULL COMMENT '项目ID', + `amount` decimal(24,2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `sheet_id` (`sheet_id`,`item_id`) USING BTREE, + KEY `item_id` (`item_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户费用单明细'; + +-- ---------------------------- +-- Records of customer_settle_fee_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_pre_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_pre_sheet`; +CREATE TABLE `customer_settle_pre_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `customer_id` (`customer_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户预付款单'; + +-- ---------------------------- +-- Records of customer_settle_pre_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_pre_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_pre_sheet_detail`; +CREATE TABLE `customer_settle_pre_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '预付款单ID', + `item_id` varchar(32) NOT NULL COMMENT '项目ID', + `amount` decimal(24,2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `sheet_id` (`sheet_id`,`item_id`) USING BTREE, + KEY `item_id` (`item_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户预付款单明细'; + +-- ---------------------------- +-- Records of customer_settle_pre_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_sheet`; +CREATE TABLE `customer_settle_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `total_discount_amount` decimal(24,2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `customer_id` (`customer_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户结算单'; + +-- ---------------------------- +-- Records of customer_settle_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for customer_settle_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `customer_settle_sheet_detail`; +CREATE TABLE `customer_settle_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '结算单ID', + `biz_id` varchar(32) NOT NULL COMMENT '单据ID', + `pay_amount` decimal(24,2) NOT NULL COMMENT '实付金额', + `discount_amount` decimal(24,2) NOT NULL COMMENT '优惠金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `sheet_id` (`sheet_id`,`biz_id`) USING BTREE, + KEY `biz_id` (`biz_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户结算单明细'; + +-- ---------------------------- +-- Records of customer_settle_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for dic_city +-- ---------------------------- +DROP TABLE IF EXISTS `dic_city`; +CREATE TABLE `dic_city` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `parent_id` varchar(32) DEFAULT NULL COMMENT '父级ID', + `level` int(11) NOT NULL COMMENT '层级', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `parent_id` (`parent_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='地区字典表'; + +-- ---------------------------- +-- Records of dic_city +-- ---------------------------- +BEGIN; +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('11', '11', '北京市', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1101', '1101', '市辖区', '11', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110101', '110101', '东城区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110102', '110102', '西城区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110105', '110105', '朝阳区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110106', '110106', '丰台区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110107', '110107', '石景山区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110108', '110108', '海淀区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110109', '110109', '门头沟区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110111', '110111', '房山区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110112', '110112', '通州区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110113', '110113', '顺义区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110114', '110114', '昌平区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110115', '110115', '大兴区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110116', '110116', '怀柔区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110117', '110117', '平谷区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110118', '110118', '密云区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('110119', '110119', '延庆区', '1101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('12', '12', '天津市', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1201', '1201', '市辖区', '12', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120101', '120101', '和平区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120102', '120102', '河东区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120103', '120103', '河西区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120104', '120104', '南开区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120105', '120105', '河北区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120106', '120106', '红桥区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120110', '120110', '东丽区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120111', '120111', '西青区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120112', '120112', '津南区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120113', '120113', '北辰区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120114', '120114', '武清区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120115', '120115', '宝坻区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120116', '120116', '滨海新区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120117', '120117', '宁河区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120118', '120118', '静海区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('120119', '120119', '蓟州区', '1201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('13', '13', '河北省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1301', '1301', '石家庄市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130102', '130102', '长安区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130104', '130104', '桥西区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130105', '130105', '新华区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130107', '130107', '井陉矿区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130108', '130108', '裕华区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130109', '130109', '藁城区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130110', '130110', '鹿泉区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130111', '130111', '栾城区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130121', '130121', '井陉县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130123', '130123', '正定县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130125', '130125', '行唐县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130126', '130126', '灵寿县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130127', '130127', '高邑县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130128', '130128', '深泽县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130129', '130129', '赞皇县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130130', '130130', '无极县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130131', '130131', '平山县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130132', '130132', '元氏县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130133', '130133', '赵县', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130171', '130171', '石家庄高新技术产业开发区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130172', '130172', '石家庄循环化工园区', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130181', '130181', '辛集市', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130183', '130183', '晋州市', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130184', '130184', '新乐市', '1301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1302', '1302', '唐山市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130202', '130202', '路南区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130203', '130203', '路北区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130204', '130204', '古冶区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130205', '130205', '开平区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130207', '130207', '丰南区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130208', '130208', '丰润区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130209', '130209', '曹妃甸区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130224', '130224', '滦南县', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130225', '130225', '乐亭县', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130227', '130227', '迁西县', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130229', '130229', '玉田县', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130271', '130271', '河北唐山芦台经济开发区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130272', '130272', '唐山市汉沽管理区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130273', '130273', '唐山高新技术产业开发区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130274', '130274', '河北唐山海港经济开发区', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130281', '130281', '遵化市', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130283', '130283', '迁安市', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130284', '130284', '滦州市', '1302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1303', '1303', '秦皇岛市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130302', '130302', '海港区', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130303', '130303', '山海关区', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130304', '130304', '北戴河区', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130306', '130306', '抚宁区', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130321', '130321', '青龙满族自治县', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130322', '130322', '昌黎县', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130324', '130324', '卢龙县', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130371', '130371', '秦皇岛市经济技术开发区', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130372', '130372', '北戴河新区', '1303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1304', '1304', '邯郸市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130402', '130402', '邯山区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130403', '130403', '丛台区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130404', '130404', '复兴区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130406', '130406', '峰峰矿区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130407', '130407', '肥乡区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130408', '130408', '永年区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130423', '130423', '临漳县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130424', '130424', '成安县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130425', '130425', '大名县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130426', '130426', '涉县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130427', '130427', '磁县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130430', '130430', '邱县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130431', '130431', '鸡泽县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130432', '130432', '广平县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130433', '130433', '馆陶县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130434', '130434', '魏县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130435', '130435', '曲周县', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130471', '130471', '邯郸经济技术开发区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130473', '130473', '邯郸冀南新区', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130481', '130481', '武安市', '1304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1305', '1305', '邢台市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130502', '130502', '襄都区', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130503', '130503', '信都区', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130505', '130505', '任泽区', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130506', '130506', '南和区', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130522', '130522', '临城县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130523', '130523', '内丘县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130524', '130524', '柏乡县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130525', '130525', '隆尧县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130528', '130528', '宁晋县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130529', '130529', '巨鹿县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130530', '130530', '新河县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130531', '130531', '广宗县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130532', '130532', '平乡县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130533', '130533', '威县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130534', '130534', '清河县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130535', '130535', '临西县', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130571', '130571', '河北邢台经济开发区', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130581', '130581', '南宫市', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130582', '130582', '沙河市', '1305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1306', '1306', '保定市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130602', '130602', '竞秀区', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130606', '130606', '莲池区', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130607', '130607', '满城区', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130608', '130608', '清苑区', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130609', '130609', '徐水区', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130623', '130623', '涞水县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130624', '130624', '阜平县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130626', '130626', '定兴县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130627', '130627', '唐县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130628', '130628', '高阳县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130629', '130629', '容城县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130630', '130630', '涞源县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130631', '130631', '望都县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130632', '130632', '安新县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130633', '130633', '易县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130634', '130634', '曲阳县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130635', '130635', '蠡县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130636', '130636', '顺平县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130637', '130637', '博野县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130638', '130638', '雄县', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130671', '130671', '保定高新技术产业开发区', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130672', '130672', '保定白沟新城', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130681', '130681', '涿州市', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130682', '130682', '定州市', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130683', '130683', '安国市', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130684', '130684', '高碑店市', '1306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1307', '1307', '张家口市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130702', '130702', '桥东区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130703', '130703', '桥西区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130705', '130705', '宣化区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130706', '130706', '下花园区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130708', '130708', '万全区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130709', '130709', '崇礼区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130722', '130722', '张北县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130723', '130723', '康保县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130724', '130724', '沽源县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130725', '130725', '尚义县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130726', '130726', '蔚县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130727', '130727', '阳原县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130728', '130728', '怀安县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130730', '130730', '怀来县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130731', '130731', '涿鹿县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130732', '130732', '赤城县', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130771', '130771', '张家口经济开发区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130772', '130772', '张家口市察北管理区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130773', '130773', '张家口市塞北管理区', '1307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1308', '1308', '承德市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130802', '130802', '双桥区', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130803', '130803', '双滦区', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130804', '130804', '鹰手营子矿区', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130821', '130821', '承德县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130822', '130822', '兴隆县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130824', '130824', '滦平县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130825', '130825', '隆化县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130826', '130826', '丰宁满族自治县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130827', '130827', '宽城满族自治县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130828', '130828', '围场满族蒙古族自治县', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130871', '130871', '承德高新技术产业开发区', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130881', '130881', '平泉市', '1308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1309', '1309', '沧州市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130902', '130902', '新华区', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130903', '130903', '运河区', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130921', '130921', '沧县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130922', '130922', '青县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130923', '130923', '东光县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130924', '130924', '海兴县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130925', '130925', '盐山县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130926', '130926', '肃宁县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130927', '130927', '南皮县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130928', '130928', '吴桥县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130929', '130929', '献县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130930', '130930', '孟村回族自治县', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130971', '130971', '河北沧州经济开发区', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130972', '130972', '沧州高新技术产业开发区', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130973', '130973', '沧州渤海新区', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130981', '130981', '泊头市', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130982', '130982', '任丘市', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130983', '130983', '黄骅市', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('130984', '130984', '河间市', '1309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1310', '1310', '廊坊市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131002', '131002', '安次区', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131003', '131003', '广阳区', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131022', '131022', '固安县', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131023', '131023', '永清县', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131024', '131024', '香河县', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131025', '131025', '大城县', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131026', '131026', '文安县', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131028', '131028', '大厂回族自治县', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131071', '131071', '廊坊经济技术开发区', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131081', '131081', '霸州市', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131082', '131082', '三河市', '1310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1311', '1311', '衡水市', '13', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131102', '131102', '桃城区', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131103', '131103', '冀州区', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131121', '131121', '枣强县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131122', '131122', '武邑县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131123', '131123', '武强县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131124', '131124', '饶阳县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131125', '131125', '安平县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131126', '131126', '故城县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131127', '131127', '景县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131128', '131128', '阜城县', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131171', '131171', '河北衡水高新技术产业开发区', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131172', '131172', '衡水滨湖新区', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('131182', '131182', '深州市', '1311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('14', '14', '山西省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1401', '1401', '太原市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140105', '140105', '小店区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140106', '140106', '迎泽区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140107', '140107', '杏花岭区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140108', '140108', '尖草坪区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140109', '140109', '万柏林区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140110', '140110', '晋源区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140121', '140121', '清徐县', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140122', '140122', '阳曲县', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140123', '140123', '娄烦县', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140171', '140171', '山西转型综合改革示范区', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140181', '140181', '古交市', '1401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1402', '1402', '大同市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140212', '140212', '新荣区', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140213', '140213', '平城区', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140214', '140214', '云冈区', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140215', '140215', '云州区', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140221', '140221', '阳高县', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140222', '140222', '天镇县', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140223', '140223', '广灵县', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140224', '140224', '灵丘县', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140225', '140225', '浑源县', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140226', '140226', '左云县', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140271', '140271', '山西大同经济开发区', '1402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1403', '1403', '阳泉市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140302', '140302', '城区', '1403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140303', '140303', '矿区', '1403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140311', '140311', '郊区', '1403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140321', '140321', '平定县', '1403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140322', '140322', '盂县', '1403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1404', '1404', '长治市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140403', '140403', '潞州区', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140404', '140404', '上党区', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140405', '140405', '屯留区', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140406', '140406', '潞城区', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140423', '140423', '襄垣县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140425', '140425', '平顺县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140426', '140426', '黎城县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140427', '140427', '壶关县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140428', '140428', '长子县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140429', '140429', '武乡县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140430', '140430', '沁县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140431', '140431', '沁源县', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140471', '140471', '山西长治高新技术产业园区', '1404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1405', '1405', '晋城市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140502', '140502', '城区', '1405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140521', '140521', '沁水县', '1405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140522', '140522', '阳城县', '1405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140524', '140524', '陵川县', '1405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140525', '140525', '泽州县', '1405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140581', '140581', '高平市', '1405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1406', '1406', '朔州市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140602', '140602', '朔城区', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140603', '140603', '平鲁区', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140621', '140621', '山阴县', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140622', '140622', '应县', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140623', '140623', '右玉县', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140671', '140671', '山西朔州经济开发区', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140681', '140681', '怀仁市', '1406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1407', '1407', '晋中市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140702', '140702', '榆次区', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140703', '140703', '太谷区', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140721', '140721', '榆社县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140722', '140722', '左权县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140723', '140723', '和顺县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140724', '140724', '昔阳县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140725', '140725', '寿阳县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140727', '140727', '祁县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140728', '140728', '平遥县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140729', '140729', '灵石县', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140781', '140781', '介休市', '1407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1408', '1408', '运城市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140802', '140802', '盐湖区', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140821', '140821', '临猗县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140822', '140822', '万荣县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140823', '140823', '闻喜县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140824', '140824', '稷山县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140825', '140825', '新绛县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140826', '140826', '绛县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140827', '140827', '垣曲县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140828', '140828', '夏县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140829', '140829', '平陆县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140830', '140830', '芮城县', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140881', '140881', '永济市', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140882', '140882', '河津市', '1408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1409', '1409', '忻州市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140902', '140902', '忻府区', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140921', '140921', '定襄县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140922', '140922', '五台县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140923', '140923', '代县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140924', '140924', '繁峙县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140925', '140925', '宁武县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140926', '140926', '静乐县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140927', '140927', '神池县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140928', '140928', '五寨县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140929', '140929', '岢岚县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140930', '140930', '河曲县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140931', '140931', '保德县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140932', '140932', '偏关县', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140971', '140971', '五台山风景名胜区', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('140981', '140981', '原平市', '1409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1410', '1410', '临汾市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141002', '141002', '尧都区', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141021', '141021', '曲沃县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141022', '141022', '翼城县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141023', '141023', '襄汾县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141024', '141024', '洪洞县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141025', '141025', '古县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141026', '141026', '安泽县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141027', '141027', '浮山县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141028', '141028', '吉县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141029', '141029', '乡宁县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141030', '141030', '大宁县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141031', '141031', '隰县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141032', '141032', '永和县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141033', '141033', '蒲县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141034', '141034', '汾西县', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141081', '141081', '侯马市', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141082', '141082', '霍州市', '1410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1411', '1411', '吕梁市', '14', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141102', '141102', '离石区', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141121', '141121', '文水县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141122', '141122', '交城县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141123', '141123', '兴县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141124', '141124', '临县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141125', '141125', '柳林县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141126', '141126', '石楼县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141127', '141127', '岚县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141128', '141128', '方山县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141129', '141129', '中阳县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141130', '141130', '交口县', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141181', '141181', '孝义市', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('141182', '141182', '汾阳市', '1411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('15', '15', '内蒙古自治区', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1501', '1501', '呼和浩特市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150102', '150102', '新城区', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150103', '150103', '回民区', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150104', '150104', '玉泉区', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150105', '150105', '赛罕区', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150121', '150121', '土默特左旗', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150122', '150122', '托克托县', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150123', '150123', '和林格尔县', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150124', '150124', '清水河县', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150125', '150125', '武川县', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150172', '150172', '呼和浩特经济技术开发区', '1501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1502', '1502', '包头市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150202', '150202', '东河区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150203', '150203', '昆都仑区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150204', '150204', '青山区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150205', '150205', '石拐区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150206', '150206', '白云鄂博矿区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150207', '150207', '九原区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150221', '150221', '土默特右旗', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150222', '150222', '固阳县', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150223', '150223', '达尔罕茂明安联合旗', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150271', '150271', '包头稀土高新技术产业开发区', '1502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1503', '1503', '乌海市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150302', '150302', '海勃湾区', '1503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150303', '150303', '海南区', '1503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150304', '150304', '乌达区', '1503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1504', '1504', '赤峰市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150402', '150402', '红山区', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150403', '150403', '元宝山区', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150404', '150404', '松山区', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150421', '150421', '阿鲁科尔沁旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150422', '150422', '巴林左旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150423', '150423', '巴林右旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150424', '150424', '林西县', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150425', '150425', '克什克腾旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150426', '150426', '翁牛特旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150428', '150428', '喀喇沁旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150429', '150429', '宁城县', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150430', '150430', '敖汉旗', '1504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1505', '1505', '通辽市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150502', '150502', '科尔沁区', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150521', '150521', '科尔沁左翼中旗', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150522', '150522', '科尔沁左翼后旗', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150523', '150523', '开鲁县', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150524', '150524', '库伦旗', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150525', '150525', '奈曼旗', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150526', '150526', '扎鲁特旗', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150571', '150571', '通辽经济技术开发区', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150581', '150581', '霍林郭勒市', '1505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1506', '1506', '鄂尔多斯市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150602', '150602', '东胜区', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150603', '150603', '康巴什区', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150621', '150621', '达拉特旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150622', '150622', '准格尔旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150623', '150623', '鄂托克前旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150624', '150624', '鄂托克旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150625', '150625', '杭锦旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150626', '150626', '乌审旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150627', '150627', '伊金霍洛旗', '1506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1507', '1507', '呼伦贝尔市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150702', '150702', '海拉尔区', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150703', '150703', '扎赉诺尔区', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150721', '150721', '阿荣旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150722', '150722', '莫力达瓦达斡尔族自治旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150723', '150723', '鄂伦春自治旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150724', '150724', '鄂温克族自治旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150725', '150725', '陈巴尔虎旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150726', '150726', '新巴尔虎左旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150727', '150727', '新巴尔虎右旗', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150781', '150781', '满洲里市', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150782', '150782', '牙克石市', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150783', '150783', '扎兰屯市', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150784', '150784', '额尔古纳市', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150785', '150785', '根河市', '1507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1508', '1508', '巴彦淖尔市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150802', '150802', '临河区', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150821', '150821', '五原县', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150822', '150822', '磴口县', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150823', '150823', '乌拉特前旗', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150824', '150824', '乌拉特中旗', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150825', '150825', '乌拉特后旗', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150826', '150826', '杭锦后旗', '1508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1509', '1509', '乌兰察布市', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150902', '150902', '集宁区', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150921', '150921', '卓资县', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150922', '150922', '化德县', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150923', '150923', '商都县', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150924', '150924', '兴和县', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150925', '150925', '凉城县', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150926', '150926', '察哈尔右翼前旗', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150927', '150927', '察哈尔右翼中旗', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150928', '150928', '察哈尔右翼后旗', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150929', '150929', '四子王旗', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('150981', '150981', '丰镇市', '1509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1522', '1522', '兴安盟', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152201', '152201', '乌兰浩特市', '1522', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152202', '152202', '阿尔山市', '1522', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152221', '152221', '科尔沁右翼前旗', '1522', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152222', '152222', '科尔沁右翼中旗', '1522', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152223', '152223', '扎赉特旗', '1522', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152224', '152224', '突泉县', '1522', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1525', '1525', '锡林郭勒盟', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152501', '152501', '二连浩特市', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152502', '152502', '锡林浩特市', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152522', '152522', '阿巴嘎旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152523', '152523', '苏尼特左旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152524', '152524', '苏尼特右旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152525', '152525', '东乌珠穆沁旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152526', '152526', '西乌珠穆沁旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152527', '152527', '太仆寺旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152528', '152528', '镶黄旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152529', '152529', '正镶白旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152530', '152530', '正蓝旗', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152531', '152531', '多伦县', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152571', '152571', '乌拉盖管委会', '1525', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('1529', '1529', '阿拉善盟', '15', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152921', '152921', '阿拉善左旗', '1529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152922', '152922', '阿拉善右旗', '1529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152923', '152923', '额济纳旗', '1529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('152971', '152971', '内蒙古阿拉善经济开发区', '1529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('21', '21', '辽宁省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2101', '2101', '沈阳市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210102', '210102', '和平区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210103', '210103', '沈河区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210104', '210104', '大东区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210105', '210105', '皇姑区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210106', '210106', '铁西区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210111', '210111', '苏家屯区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210112', '210112', '浑南区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210113', '210113', '沈北新区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210114', '210114', '于洪区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210115', '210115', '辽中区', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210123', '210123', '康平县', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210124', '210124', '法库县', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210181', '210181', '新民市', '2101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2102', '2102', '大连市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210202', '210202', '中山区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210203', '210203', '西岗区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210204', '210204', '沙河口区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210211', '210211', '甘井子区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210212', '210212', '旅顺口区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210213', '210213', '金州区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210214', '210214', '普兰店区', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210224', '210224', '长海县', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210281', '210281', '瓦房店市', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210283', '210283', '庄河市', '2102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2103', '2103', '鞍山市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210302', '210302', '铁东区', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210303', '210303', '铁西区', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210304', '210304', '立山区', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210311', '210311', '千山区', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210321', '210321', '台安县', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210323', '210323', '岫岩满族自治县', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210381', '210381', '海城市', '2103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2104', '2104', '抚顺市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210402', '210402', '新抚区', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210403', '210403', '东洲区', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210404', '210404', '望花区', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210411', '210411', '顺城区', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210421', '210421', '抚顺县', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210422', '210422', '新宾满族自治县', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210423', '210423', '清原满族自治县', '2104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2105', '2105', '本溪市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210502', '210502', '平山区', '2105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210503', '210503', '溪湖区', '2105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210504', '210504', '明山区', '2105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210505', '210505', '南芬区', '2105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210521', '210521', '本溪满族自治县', '2105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210522', '210522', '桓仁满族自治县', '2105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2106', '2106', '丹东市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210602', '210602', '元宝区', '2106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210603', '210603', '振兴区', '2106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210604', '210604', '振安区', '2106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210624', '210624', '宽甸满族自治县', '2106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210681', '210681', '东港市', '2106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210682', '210682', '凤城市', '2106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2107', '2107', '锦州市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210702', '210702', '古塔区', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210703', '210703', '凌河区', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210711', '210711', '太和区', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210726', '210726', '黑山县', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210727', '210727', '义县', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210781', '210781', '凌海市', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210782', '210782', '北镇市', '2107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2108', '2108', '营口市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210802', '210802', '站前区', '2108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210803', '210803', '西市区', '2108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210804', '210804', '鲅鱼圈区', '2108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210811', '210811', '老边区', '2108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210881', '210881', '盖州市', '2108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210882', '210882', '大石桥市', '2108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2109', '2109', '阜新市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210902', '210902', '海州区', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210903', '210903', '新邱区', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210904', '210904', '太平区', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210905', '210905', '清河门区', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210911', '210911', '细河区', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210921', '210921', '阜新蒙古族自治县', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('210922', '210922', '彰武县', '2109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2110', '2110', '辽阳市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211002', '211002', '白塔区', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211003', '211003', '文圣区', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211004', '211004', '宏伟区', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211005', '211005', '弓长岭区', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211011', '211011', '太子河区', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211021', '211021', '辽阳县', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211081', '211081', '灯塔市', '2110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2111', '2111', '盘锦市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211102', '211102', '双台子区', '2111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211103', '211103', '兴隆台区', '2111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211104', '211104', '大洼区', '2111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211122', '211122', '盘山县', '2111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2112', '2112', '铁岭市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211202', '211202', '银州区', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211204', '211204', '清河区', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211221', '211221', '铁岭县', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211223', '211223', '西丰县', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211224', '211224', '昌图县', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211281', '211281', '调兵山市', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211282', '211282', '开原市', '2112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2113', '2113', '朝阳市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211302', '211302', '双塔区', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211303', '211303', '龙城区', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211321', '211321', '朝阳县', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211322', '211322', '建平县', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211324', '211324', '喀喇沁左翼蒙古族自治县', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211381', '211381', '北票市', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211382', '211382', '凌源市', '2113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2114', '2114', '葫芦岛市', '21', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211402', '211402', '连山区', '2114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211403', '211403', '龙港区', '2114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211404', '211404', '南票区', '2114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211421', '211421', '绥中县', '2114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211422', '211422', '建昌县', '2114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('211481', '211481', '兴城市', '2114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('22', '22', '吉林省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2201', '2201', '长春市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220102', '220102', '南关区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220103', '220103', '宽城区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220104', '220104', '朝阳区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220105', '220105', '二道区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220106', '220106', '绿园区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220112', '220112', '双阳区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220113', '220113', '九台区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220122', '220122', '农安县', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220171', '220171', '长春经济技术开发区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220172', '220172', '长春净月高新技术产业开发区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220173', '220173', '长春高新技术产业开发区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220174', '220174', '长春汽车经济技术开发区', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220182', '220182', '榆树市', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220183', '220183', '德惠市', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220184', '220184', '公主岭市', '2201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2202', '2202', '吉林市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220202', '220202', '昌邑区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220203', '220203', '龙潭区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220204', '220204', '船营区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220211', '220211', '丰满区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220221', '220221', '永吉县', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220271', '220271', '吉林经济开发区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220272', '220272', '吉林高新技术产业开发区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220273', '220273', '吉林中国新加坡食品区', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220281', '220281', '蛟河市', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220282', '220282', '桦甸市', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220283', '220283', '舒兰市', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220284', '220284', '磐石市', '2202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2203', '2203', '四平市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220302', '220302', '铁西区', '2203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220303', '220303', '铁东区', '2203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220322', '220322', '梨树县', '2203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220323', '220323', '伊通满族自治县', '2203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220382', '220382', '双辽市', '2203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2204', '2204', '辽源市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220402', '220402', '龙山区', '2204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220403', '220403', '西安区', '2204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220421', '220421', '东丰县', '2204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220422', '220422', '东辽县', '2204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2205', '2205', '通化市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220502', '220502', '东昌区', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220503', '220503', '二道江区', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220521', '220521', '通化县', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220523', '220523', '辉南县', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220524', '220524', '柳河县', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220581', '220581', '梅河口市', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220582', '220582', '集安市', '2205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2206', '2206', '白山市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220602', '220602', '浑江区', '2206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220605', '220605', '江源区', '2206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220621', '220621', '抚松县', '2206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220622', '220622', '靖宇县', '2206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220623', '220623', '长白朝鲜族自治县', '2206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220681', '220681', '临江市', '2206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2207', '2207', '松原市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220702', '220702', '宁江区', '2207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220721', '220721', '前郭尔罗斯蒙古族自治县', '2207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220722', '220722', '长岭县', '2207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220723', '220723', '乾安县', '2207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220771', '220771', '吉林松原经济开发区', '2207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220781', '220781', '扶余市', '2207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2208', '2208', '白城市', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220802', '220802', '洮北区', '2208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220821', '220821', '镇赉县', '2208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220822', '220822', '通榆县', '2208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220871', '220871', '吉林白城经济开发区', '2208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220881', '220881', '洮南市', '2208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('220882', '220882', '大安市', '2208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2224', '2224', '延边朝鲜族自治州', '22', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222401', '222401', '延吉市', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222402', '222402', '图们市', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222403', '222403', '敦化市', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222404', '222404', '珲春市', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222405', '222405', '龙井市', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222406', '222406', '和龙市', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222424', '222424', '汪清县', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('222426', '222426', '安图县', '2224', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('23', '23', '黑龙江省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2301', '2301', '哈尔滨市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230102', '230102', '道里区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230103', '230103', '南岗区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230104', '230104', '道外区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230108', '230108', '平房区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230109', '230109', '松北区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230110', '230110', '香坊区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230111', '230111', '呼兰区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230112', '230112', '阿城区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230113', '230113', '双城区', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230123', '230123', '依兰县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230124', '230124', '方正县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230125', '230125', '宾县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230126', '230126', '巴彦县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230127', '230127', '木兰县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230128', '230128', '通河县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230129', '230129', '延寿县', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230183', '230183', '尚志市', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230184', '230184', '五常市', '2301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2302', '2302', '齐齐哈尔市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230202', '230202', '龙沙区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230203', '230203', '建华区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230204', '230204', '铁锋区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230205', '230205', '昂昂溪区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230206', '230206', '富拉尔基区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230207', '230207', '碾子山区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230208', '230208', '梅里斯达斡尔族区', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230221', '230221', '龙江县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230223', '230223', '依安县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230224', '230224', '泰来县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230225', '230225', '甘南县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230227', '230227', '富裕县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230229', '230229', '克山县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230230', '230230', '克东县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230231', '230231', '拜泉县', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230281', '230281', '讷河市', '2302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2303', '2303', '鸡西市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230302', '230302', '鸡冠区', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230303', '230303', '恒山区', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230304', '230304', '滴道区', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230305', '230305', '梨树区', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230306', '230306', '城子河区', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230307', '230307', '麻山区', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230321', '230321', '鸡东县', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230381', '230381', '虎林市', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230382', '230382', '密山市', '2303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2304', '2304', '鹤岗市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230402', '230402', '向阳区', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230403', '230403', '工农区', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230404', '230404', '南山区', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230405', '230405', '兴安区', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230406', '230406', '东山区', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230407', '230407', '兴山区', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230421', '230421', '萝北县', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230422', '230422', '绥滨县', '2304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2305', '2305', '双鸭山市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230502', '230502', '尖山区', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230503', '230503', '岭东区', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230505', '230505', '四方台区', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230506', '230506', '宝山区', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230521', '230521', '集贤县', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230522', '230522', '友谊县', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230523', '230523', '宝清县', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230524', '230524', '饶河县', '2305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2306', '2306', '大庆市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230602', '230602', '萨尔图区', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230603', '230603', '龙凤区', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230604', '230604', '让胡路区', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230605', '230605', '红岗区', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230606', '230606', '大同区', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230621', '230621', '肇州县', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230622', '230622', '肇源县', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230623', '230623', '林甸县', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230624', '230624', '杜尔伯特蒙古族自治县', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230671', '230671', '大庆高新技术产业开发区', '2306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2307', '2307', '伊春市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230717', '230717', '伊美区', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230718', '230718', '乌翠区', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230719', '230719', '友好区', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230722', '230722', '嘉荫县', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230723', '230723', '汤旺县', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230724', '230724', '丰林县', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230725', '230725', '大箐山县', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230726', '230726', '南岔县', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230751', '230751', '金林区', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230781', '230781', '铁力市', '2307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2308', '2308', '佳木斯市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230803', '230803', '向阳区', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230804', '230804', '前进区', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230805', '230805', '东风区', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230811', '230811', '郊区', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230822', '230822', '桦南县', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230826', '230826', '桦川县', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230828', '230828', '汤原县', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230881', '230881', '同江市', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230882', '230882', '富锦市', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230883', '230883', '抚远市', '2308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2309', '2309', '七台河市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230902', '230902', '新兴区', '2309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230903', '230903', '桃山区', '2309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230904', '230904', '茄子河区', '2309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('230921', '230921', '勃利县', '2309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2310', '2310', '牡丹江市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231002', '231002', '东安区', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231003', '231003', '阳明区', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231004', '231004', '爱民区', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231005', '231005', '西安区', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231025', '231025', '林口县', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231071', '231071', '牡丹江经济技术开发区', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231081', '231081', '绥芬河市', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231083', '231083', '海林市', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231084', '231084', '宁安市', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231085', '231085', '穆棱市', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231086', '231086', '东宁市', '2310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2311', '2311', '黑河市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231102', '231102', '爱辉区', '2311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231123', '231123', '逊克县', '2311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231124', '231124', '孙吴县', '2311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231181', '231181', '北安市', '2311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231182', '231182', '五大连池市', '2311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231183', '231183', '嫩江市', '2311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2312', '2312', '绥化市', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231202', '231202', '北林区', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231221', '231221', '望奎县', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231222', '231222', '兰西县', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231223', '231223', '青冈县', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231224', '231224', '庆安县', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231225', '231225', '明水县', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231226', '231226', '绥棱县', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231281', '231281', '安达市', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231282', '231282', '肇东市', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('231283', '231283', '海伦市', '2312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('2327', '2327', '大兴安岭地区', '23', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232701', '232701', '漠河市', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232721', '232721', '呼玛县', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232722', '232722', '塔河县', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232761', '232761', '加格达奇区', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232762', '232762', '松岭区', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232763', '232763', '新林区', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('232764', '232764', '呼中区', '2327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('31', '31', '上海市', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3101', '3101', '市辖区', '31', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310101', '310101', '黄浦区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310104', '310104', '徐汇区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310105', '310105', '长宁区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310106', '310106', '静安区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310107', '310107', '普陀区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310109', '310109', '虹口区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310110', '310110', '杨浦区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310112', '310112', '闵行区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310113', '310113', '宝山区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310114', '310114', '嘉定区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310115', '310115', '浦东新区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310116', '310116', '金山区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310117', '310117', '松江区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310118', '310118', '青浦区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310120', '310120', '奉贤区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('310151', '310151', '崇明区', '3101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('32', '32', '江苏省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3201', '3201', '南京市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320102', '320102', '玄武区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320104', '320104', '秦淮区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320105', '320105', '建邺区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320106', '320106', '鼓楼区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320111', '320111', '浦口区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320113', '320113', '栖霞区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320114', '320114', '雨花台区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320115', '320115', '江宁区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320116', '320116', '六合区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320117', '320117', '溧水区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320118', '320118', '高淳区', '3201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3202', '3202', '无锡市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320205', '320205', '锡山区', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320206', '320206', '惠山区', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320211', '320211', '滨湖区', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320213', '320213', '梁溪区', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320214', '320214', '新吴区', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320281', '320281', '江阴市', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320282', '320282', '宜兴市', '3202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3203', '3203', '徐州市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320302', '320302', '鼓楼区', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320303', '320303', '云龙区', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320305', '320305', '贾汪区', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320311', '320311', '泉山区', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320312', '320312', '铜山区', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320321', '320321', '丰县', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320322', '320322', '沛县', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320324', '320324', '睢宁县', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320371', '320371', '徐州经济技术开发区', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320381', '320381', '新沂市', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320382', '320382', '邳州市', '3203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3204', '3204', '常州市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320402', '320402', '天宁区', '3204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320404', '320404', '钟楼区', '3204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320411', '320411', '新北区', '3204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320412', '320412', '武进区', '3204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320413', '320413', '金坛区', '3204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320481', '320481', '溧阳市', '3204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3205', '3205', '苏州市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320505', '320505', '虎丘区', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320506', '320506', '吴中区', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320507', '320507', '相城区', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320508', '320508', '姑苏区', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320509', '320509', '吴江区', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320571', '320571', '苏州工业园区', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320581', '320581', '常熟市', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320582', '320582', '张家港市', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320583', '320583', '昆山市', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320585', '320585', '太仓市', '3205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3206', '3206', '南通市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320602', '320602', '崇川区', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320611', '320611', '港闸区', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320612', '320612', '通州区', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320623', '320623', '如东县', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320671', '320671', '南通经济技术开发区', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320681', '320681', '启东市', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320682', '320682', '如皋市', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320684', '320684', '海门市', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320685', '320685', '海安市', '3206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3207', '3207', '连云港市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320703', '320703', '连云区', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320706', '320706', '海州区', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320707', '320707', '赣榆区', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320722', '320722', '东海县', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320723', '320723', '灌云县', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320724', '320724', '灌南县', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320771', '320771', '连云港经济技术开发区', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320772', '320772', '连云港高新技术产业开发区', '3207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3208', '3208', '淮安市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320803', '320803', '淮安区', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320804', '320804', '淮阴区', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320812', '320812', '清江浦区', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320813', '320813', '洪泽区', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320826', '320826', '涟水县', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320830', '320830', '盱眙县', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320831', '320831', '金湖县', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320871', '320871', '淮安经济技术开发区', '3208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3209', '3209', '盐城市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320902', '320902', '亭湖区', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320903', '320903', '盐都区', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320904', '320904', '大丰区', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320921', '320921', '响水县', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320922', '320922', '滨海县', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320923', '320923', '阜宁县', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320924', '320924', '射阳县', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320925', '320925', '建湖县', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320971', '320971', '盐城经济技术开发区', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('320981', '320981', '东台市', '3209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3210', '3210', '扬州市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321002', '321002', '广陵区', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321003', '321003', '邗江区', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321012', '321012', '江都区', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321023', '321023', '宝应县', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321071', '321071', '扬州经济技术开发区', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321081', '321081', '仪征市', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321084', '321084', '高邮市', '3210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3211', '3211', '镇江市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321102', '321102', '京口区', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321111', '321111', '润州区', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321112', '321112', '丹徒区', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321171', '321171', '镇江新区', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321181', '321181', '丹阳市', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321182', '321182', '扬中市', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321183', '321183', '句容市', '3211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3212', '3212', '泰州市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321202', '321202', '海陵区', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321203', '321203', '高港区', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321204', '321204', '姜堰区', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321271', '321271', '泰州医药高新技术产业开发区', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321281', '321281', '兴化市', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321282', '321282', '靖江市', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321283', '321283', '泰兴市', '3212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3213', '3213', '宿迁市', '32', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321302', '321302', '宿城区', '3213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321311', '321311', '宿豫区', '3213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321322', '321322', '沭阳县', '3213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321323', '321323', '泗阳县', '3213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321324', '321324', '泗洪县', '3213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('321371', '321371', '宿迁经济技术开发区', '3213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('33', '33', '浙江省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3301', '3301', '杭州市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330102', '330102', '上城区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330103', '330103', '下城区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330104', '330104', '江干区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330105', '330105', '拱墅区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330106', '330106', '西湖区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330108', '330108', '滨江区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330109', '330109', '萧山区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330110', '330110', '余杭区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330111', '330111', '富阳区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330112', '330112', '临安区', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330122', '330122', '桐庐县', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330127', '330127', '淳安县', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330182', '330182', '建德市', '3301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3302', '3302', '宁波市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330203', '330203', '海曙区', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330205', '330205', '江北区', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330206', '330206', '北仑区', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330211', '330211', '镇海区', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330212', '330212', '鄞州区', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330213', '330213', '奉化区', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330225', '330225', '象山县', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330226', '330226', '宁海县', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330281', '330281', '余姚市', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330282', '330282', '慈溪市', '3302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3303', '3303', '温州市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330302', '330302', '鹿城区', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330303', '330303', '龙湾区', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330304', '330304', '瓯海区', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330305', '330305', '洞头区', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330324', '330324', '永嘉县', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330326', '330326', '平阳县', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330327', '330327', '苍南县', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330328', '330328', '文成县', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330329', '330329', '泰顺县', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330371', '330371', '温州经济技术开发区', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330381', '330381', '瑞安市', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330382', '330382', '乐清市', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330383', '330383', '龙港市', '3303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3304', '3304', '嘉兴市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330402', '330402', '南湖区', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330411', '330411', '秀洲区', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330421', '330421', '嘉善县', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330424', '330424', '海盐县', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330481', '330481', '海宁市', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330482', '330482', '平湖市', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330483', '330483', '桐乡市', '3304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3305', '3305', '湖州市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330502', '330502', '吴兴区', '3305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330503', '330503', '南浔区', '3305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330521', '330521', '德清县', '3305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330522', '330522', '长兴县', '3305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330523', '330523', '安吉县', '3305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3306', '3306', '绍兴市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330602', '330602', '越城区', '3306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330603', '330603', '柯桥区', '3306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330604', '330604', '上虞区', '3306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330624', '330624', '新昌县', '3306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330681', '330681', '诸暨市', '3306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330683', '330683', '嵊州市', '3306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3307', '3307', '金华市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330702', '330702', '婺城区', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330703', '330703', '金东区', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330723', '330723', '武义县', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330726', '330726', '浦江县', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330727', '330727', '磐安县', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330781', '330781', '兰溪市', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330782', '330782', '义乌市', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330783', '330783', '东阳市', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330784', '330784', '永康市', '3307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3308', '3308', '衢州市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330802', '330802', '柯城区', '3308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330803', '330803', '衢江区', '3308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330822', '330822', '常山县', '3308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330824', '330824', '开化县', '3308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330825', '330825', '龙游县', '3308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330881', '330881', '江山市', '3308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3309', '3309', '舟山市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330902', '330902', '定海区', '3309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330903', '330903', '普陀区', '3309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330921', '330921', '岱山县', '3309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('330922', '330922', '嵊泗县', '3309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3310', '3310', '台州市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331002', '331002', '椒江区', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331003', '331003', '黄岩区', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331004', '331004', '路桥区', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331022', '331022', '三门县', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331023', '331023', '天台县', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331024', '331024', '仙居县', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331081', '331081', '温岭市', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331082', '331082', '临海市', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331083', '331083', '玉环市', '3310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3311', '3311', '丽水市', '33', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331102', '331102', '莲都区', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331121', '331121', '青田县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331122', '331122', '缙云县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331123', '331123', '遂昌县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331124', '331124', '松阳县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331125', '331125', '云和县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331126', '331126', '庆元县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331127', '331127', '景宁畲族自治县', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('331181', '331181', '龙泉市', '3311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('34', '34', '安徽省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3401', '3401', '合肥市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340102', '340102', '瑶海区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340103', '340103', '庐阳区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340104', '340104', '蜀山区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340111', '340111', '包河区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340121', '340121', '长丰县', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340122', '340122', '肥东县', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340123', '340123', '肥西县', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340124', '340124', '庐江县', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340171', '340171', '合肥高新技术产业开发区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340172', '340172', '合肥经济技术开发区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340173', '340173', '合肥新站高新技术产业开发区', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340181', '340181', '巢湖市', '3401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3402', '3402', '芜湖市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340202', '340202', '镜湖区', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340203', '340203', '弋江区', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340207', '340207', '鸠江区', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340208', '340208', '三山区', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340221', '340221', '芜湖县', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340222', '340222', '繁昌县', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340223', '340223', '南陵县', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340271', '340271', '芜湖经济技术开发区', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340272', '340272', '安徽芜湖长江大桥经济开发区', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340281', '340281', '无为市', '3402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3403', '3403', '蚌埠市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340302', '340302', '龙子湖区', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340303', '340303', '蚌山区', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340304', '340304', '禹会区', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340311', '340311', '淮上区', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340321', '340321', '怀远县', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340322', '340322', '五河县', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340323', '340323', '固镇县', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340371', '340371', '蚌埠市高新技术开发区', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340372', '340372', '蚌埠市经济开发区', '3403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3404', '3404', '淮南市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340402', '340402', '大通区', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340403', '340403', '田家庵区', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340404', '340404', '谢家集区', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340405', '340405', '八公山区', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340406', '340406', '潘集区', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340421', '340421', '凤台县', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340422', '340422', '寿县', '3404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3405', '3405', '马鞍山市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340503', '340503', '花山区', '3405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340504', '340504', '雨山区', '3405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340506', '340506', '博望区', '3405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340521', '340521', '当涂县', '3405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340522', '340522', '含山县', '3405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340523', '340523', '和县', '3405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3406', '3406', '淮北市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340602', '340602', '杜集区', '3406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340603', '340603', '相山区', '3406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340604', '340604', '烈山区', '3406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340621', '340621', '濉溪县', '3406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3407', '3407', '铜陵市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340705', '340705', '铜官区', '3407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340706', '340706', '义安区', '3407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340711', '340711', '郊区', '3407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340722', '340722', '枞阳县', '3407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3408', '3408', '安庆市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340802', '340802', '迎江区', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340803', '340803', '大观区', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340811', '340811', '宜秀区', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340822', '340822', '怀宁县', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340825', '340825', '太湖县', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340826', '340826', '宿松县', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340827', '340827', '望江县', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340828', '340828', '岳西县', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340871', '340871', '安徽安庆经济开发区', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340881', '340881', '桐城市', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('340882', '340882', '潜山市', '3408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3410', '3410', '黄山市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341002', '341002', '屯溪区', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341003', '341003', '黄山区', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341004', '341004', '徽州区', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341021', '341021', '歙县', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341022', '341022', '休宁县', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341023', '341023', '黟县', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341024', '341024', '祁门县', '3410', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3411', '3411', '滁州市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341102', '341102', '琅琊区', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341103', '341103', '南谯区', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341122', '341122', '来安县', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341124', '341124', '全椒县', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341125', '341125', '定远县', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341126', '341126', '凤阳县', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341171', '341171', '苏滁现代产业园', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341172', '341172', '滁州经济技术开发区', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341181', '341181', '天长市', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341182', '341182', '明光市', '3411', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3412', '3412', '阜阳市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341202', '341202', '颍州区', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341203', '341203', '颍东区', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341204', '341204', '颍泉区', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341221', '341221', '临泉县', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341222', '341222', '太和县', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341225', '341225', '阜南县', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341226', '341226', '颍上县', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341271', '341271', '阜阳合肥现代产业园区', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341272', '341272', '阜阳经济技术开发区', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341282', '341282', '界首市', '3412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3413', '3413', '宿州市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341302', '341302', '埇桥区', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341321', '341321', '砀山县', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341322', '341322', '萧县', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341323', '341323', '灵璧县', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341324', '341324', '泗县', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341371', '341371', '宿州马鞍山现代产业园区', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341372', '341372', '宿州经济技术开发区', '3413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3415', '3415', '六安市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341502', '341502', '金安区', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341503', '341503', '裕安区', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341504', '341504', '叶集区', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341522', '341522', '霍邱县', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341523', '341523', '舒城县', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341524', '341524', '金寨县', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341525', '341525', '霍山县', '3415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3416', '3416', '亳州市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341602', '341602', '谯城区', '3416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341621', '341621', '涡阳县', '3416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341622', '341622', '蒙城县', '3416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341623', '341623', '利辛县', '3416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3417', '3417', '池州市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341702', '341702', '贵池区', '3417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341721', '341721', '东至县', '3417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341722', '341722', '石台县', '3417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341723', '341723', '青阳县', '3417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3418', '3418', '宣城市', '34', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341802', '341802', '宣州区', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341821', '341821', '郎溪县', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341823', '341823', '泾县', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341824', '341824', '绩溪县', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341825', '341825', '旌德县', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341871', '341871', '宣城市经济开发区', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341881', '341881', '宁国市', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('341882', '341882', '广德市', '3418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('35', '35', '福建省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3501', '3501', '福州市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350102', '350102', '鼓楼区', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350103', '350103', '台江区', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350104', '350104', '仓山区', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350105', '350105', '马尾区', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350111', '350111', '晋安区', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350112', '350112', '长乐区', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350121', '350121', '闽侯县', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350122', '350122', '连江县', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350123', '350123', '罗源县', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350124', '350124', '闽清县', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350125', '350125', '永泰县', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350128', '350128', '平潭县', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350181', '350181', '福清市', '3501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3502', '3502', '厦门市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350203', '350203', '思明区', '3502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350205', '350205', '海沧区', '3502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350206', '350206', '湖里区', '3502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350211', '350211', '集美区', '3502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350212', '350212', '同安区', '3502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350213', '350213', '翔安区', '3502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3503', '3503', '莆田市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350302', '350302', '城厢区', '3503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350303', '350303', '涵江区', '3503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350304', '350304', '荔城区', '3503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350305', '350305', '秀屿区', '3503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350322', '350322', '仙游县', '3503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3504', '3504', '三明市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350402', '350402', '梅列区', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350403', '350403', '三元区', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350421', '350421', '明溪县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350423', '350423', '清流县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350424', '350424', '宁化县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350425', '350425', '大田县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350426', '350426', '尤溪县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350427', '350427', '沙县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350428', '350428', '将乐县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350429', '350429', '泰宁县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350430', '350430', '建宁县', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350481', '350481', '永安市', '3504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3505', '3505', '泉州市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350502', '350502', '鲤城区', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350503', '350503', '丰泽区', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350504', '350504', '洛江区', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350505', '350505', '泉港区', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350521', '350521', '惠安县', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350524', '350524', '安溪县', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350525', '350525', '永春县', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350526', '350526', '德化县', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350527', '350527', '金门县', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350581', '350581', '石狮市', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350582', '350582', '晋江市', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350583', '350583', '南安市', '3505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3506', '3506', '漳州市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350602', '350602', '芗城区', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350603', '350603', '龙文区', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350622', '350622', '云霄县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350623', '350623', '漳浦县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350624', '350624', '诏安县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350625', '350625', '长泰县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350626', '350626', '东山县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350627', '350627', '南靖县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350628', '350628', '平和县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350629', '350629', '华安县', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350681', '350681', '龙海市', '3506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3507', '3507', '南平市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350702', '350702', '延平区', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350703', '350703', '建阳区', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350721', '350721', '顺昌县', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350722', '350722', '浦城县', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350723', '350723', '光泽县', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350724', '350724', '松溪县', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350725', '350725', '政和县', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350781', '350781', '邵武市', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350782', '350782', '武夷山市', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350783', '350783', '建瓯市', '3507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3508', '3508', '龙岩市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350802', '350802', '新罗区', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350803', '350803', '永定区', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350821', '350821', '长汀县', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350823', '350823', '上杭县', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350824', '350824', '武平县', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350825', '350825', '连城县', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350881', '350881', '漳平市', '3508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3509', '3509', '宁德市', '35', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350902', '350902', '蕉城区', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350921', '350921', '霞浦县', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350922', '350922', '古田县', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350923', '350923', '屏南县', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350924', '350924', '寿宁县', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350925', '350925', '周宁县', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350926', '350926', '柘荣县', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350981', '350981', '福安市', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('350982', '350982', '福鼎市', '3509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('36', '36', '江西省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3601', '3601', '南昌市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360102', '360102', '东湖区', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360103', '360103', '西湖区', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360104', '360104', '青云谱区', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360111', '360111', '青山湖区', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360112', '360112', '新建区', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360113', '360113', '红谷滩区', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360121', '360121', '南昌县', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360123', '360123', '安义县', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360124', '360124', '进贤县', '3601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3602', '3602', '景德镇市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360202', '360202', '昌江区', '3602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360203', '360203', '珠山区', '3602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360222', '360222', '浮梁县', '3602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360281', '360281', '乐平市', '3602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3603', '3603', '萍乡市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360302', '360302', '安源区', '3603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360313', '360313', '湘东区', '3603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360321', '360321', '莲花县', '3603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360322', '360322', '上栗县', '3603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360323', '360323', '芦溪县', '3603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3604', '3604', '九江市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360402', '360402', '濂溪区', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360403', '360403', '浔阳区', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360404', '360404', '柴桑区', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360423', '360423', '武宁县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360424', '360424', '修水县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360425', '360425', '永修县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360426', '360426', '德安县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360428', '360428', '都昌县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360429', '360429', '湖口县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360430', '360430', '彭泽县', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360481', '360481', '瑞昌市', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360482', '360482', '共青城市', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360483', '360483', '庐山市', '3604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3605', '3605', '新余市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360502', '360502', '渝水区', '3605', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360521', '360521', '分宜县', '3605', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3606', '3606', '鹰潭市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360602', '360602', '月湖区', '3606', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360603', '360603', '余江区', '3606', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360681', '360681', '贵溪市', '3606', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3607', '3607', '赣州市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360702', '360702', '章贡区', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360703', '360703', '南康区', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360704', '360704', '赣县区', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360722', '360722', '信丰县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360723', '360723', '大余县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360724', '360724', '上犹县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360725', '360725', '崇义县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360726', '360726', '安远县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360728', '360728', '定南县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360729', '360729', '全南县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360730', '360730', '宁都县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360731', '360731', '于都县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360732', '360732', '兴国县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360733', '360733', '会昌县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360734', '360734', '寻乌县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360735', '360735', '石城县', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360781', '360781', '瑞金市', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360783', '360783', '龙南市', '3607', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3608', '3608', '吉安市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360802', '360802', '吉州区', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360803', '360803', '青原区', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360821', '360821', '吉安县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360822', '360822', '吉水县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360823', '360823', '峡江县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360824', '360824', '新干县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360825', '360825', '永丰县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360826', '360826', '泰和县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360827', '360827', '遂川县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360828', '360828', '万安县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360829', '360829', '安福县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360830', '360830', '永新县', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360881', '360881', '井冈山市', '3608', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3609', '3609', '宜春市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360902', '360902', '袁州区', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360921', '360921', '奉新县', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360922', '360922', '万载县', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360923', '360923', '上高县', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360924', '360924', '宜丰县', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360925', '360925', '靖安县', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360926', '360926', '铜鼓县', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360981', '360981', '丰城市', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360982', '360982', '樟树市', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('360983', '360983', '高安市', '3609', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3610', '3610', '抚州市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361002', '361002', '临川区', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361003', '361003', '东乡区', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361021', '361021', '南城县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361022', '361022', '黎川县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361023', '361023', '南丰县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361024', '361024', '崇仁县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361025', '361025', '乐安县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361026', '361026', '宜黄县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361027', '361027', '金溪县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361028', '361028', '资溪县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361030', '361030', '广昌县', '3610', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3611', '3611', '上饶市', '36', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361102', '361102', '信州区', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361103', '361103', '广丰区', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361104', '361104', '广信区', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361123', '361123', '玉山县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361124', '361124', '铅山县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361125', '361125', '横峰县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361126', '361126', '弋阳县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361127', '361127', '余干县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361128', '361128', '鄱阳县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361129', '361129', '万年县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361130', '361130', '婺源县', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('361181', '361181', '德兴市', '3611', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('37', '37', '山东省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3701', '3701', '济南市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370102', '370102', '历下区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370103', '370103', '市中区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370104', '370104', '槐荫区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370105', '370105', '天桥区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370112', '370112', '历城区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370113', '370113', '长清区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370114', '370114', '章丘区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370115', '370115', '济阳区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370116', '370116', '莱芜区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370117', '370117', '钢城区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370124', '370124', '平阴县', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370126', '370126', '商河县', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370171', '370171', '济南高新技术产业开发区', '3701', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3702', '3702', '青岛市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370202', '370202', '市南区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370203', '370203', '市北区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370211', '370211', '黄岛区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370212', '370212', '崂山区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370213', '370213', '李沧区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370214', '370214', '城阳区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370215', '370215', '即墨区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370271', '370271', '青岛高新技术产业开发区', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370281', '370281', '胶州市', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370283', '370283', '平度市', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370285', '370285', '莱西市', '3702', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3703', '3703', '淄博市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370302', '370302', '淄川区', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370303', '370303', '张店区', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370304', '370304', '博山区', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370305', '370305', '临淄区', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370306', '370306', '周村区', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370321', '370321', '桓台县', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370322', '370322', '高青县', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370323', '370323', '沂源县', '3703', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3704', '3704', '枣庄市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370402', '370402', '市中区', '3704', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370403', '370403', '薛城区', '3704', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370404', '370404', '峄城区', '3704', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370405', '370405', '台儿庄区', '3704', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370406', '370406', '山亭区', '3704', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370481', '370481', '滕州市', '3704', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3705', '3705', '东营市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370502', '370502', '东营区', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370503', '370503', '河口区', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370505', '370505', '垦利区', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370522', '370522', '利津县', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370523', '370523', '广饶县', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370571', '370571', '东营经济技术开发区', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370572', '370572', '东营港经济开发区', '3705', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3706', '3706', '烟台市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370602', '370602', '芝罘区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370611', '370611', '福山区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370612', '370612', '牟平区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370613', '370613', '莱山区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370614', '370614', '蓬莱区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370671', '370671', '烟台高新技术产业开发区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370672', '370672', '烟台经济技术开发区', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370681', '370681', '龙口市', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370682', '370682', '莱阳市', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370683', '370683', '莱州市', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370685', '370685', '招远市', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370686', '370686', '栖霞市', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370687', '370687', '海阳市', '3706', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3707', '3707', '潍坊市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370702', '370702', '潍城区', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370703', '370703', '寒亭区', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370704', '370704', '坊子区', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370705', '370705', '奎文区', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370724', '370724', '临朐县', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370725', '370725', '昌乐县', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370772', '370772', '潍坊滨海经济技术开发区', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370781', '370781', '青州市', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370782', '370782', '诸城市', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370783', '370783', '寿光市', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370784', '370784', '安丘市', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370785', '370785', '高密市', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370786', '370786', '昌邑市', '3707', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3708', '3708', '济宁市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370811', '370811', '任城区', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370812', '370812', '兖州区', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370826', '370826', '微山县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370827', '370827', '鱼台县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370828', '370828', '金乡县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370829', '370829', '嘉祥县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370830', '370830', '汶上县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370831', '370831', '泗水县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370832', '370832', '梁山县', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370871', '370871', '济宁高新技术产业开发区', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370881', '370881', '曲阜市', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370883', '370883', '邹城市', '3708', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3709', '3709', '泰安市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370902', '370902', '泰山区', '3709', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370911', '370911', '岱岳区', '3709', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370921', '370921', '宁阳县', '3709', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370923', '370923', '东平县', '3709', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370982', '370982', '新泰市', '3709', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('370983', '370983', '肥城市', '3709', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3710', '3710', '威海市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371002', '371002', '环翠区', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371003', '371003', '文登区', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371071', '371071', '威海火炬高技术产业开发区', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371072', '371072', '威海经济技术开发区', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371073', '371073', '威海临港经济技术开发区', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371082', '371082', '荣成市', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371083', '371083', '乳山市', '3710', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3711', '3711', '日照市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371102', '371102', '东港区', '3711', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371103', '371103', '岚山区', '3711', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371121', '371121', '五莲县', '3711', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371122', '371122', '莒县', '3711', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371171', '371171', '日照经济技术开发区', '3711', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3713', '3713', '临沂市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371302', '371302', '兰山区', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371311', '371311', '罗庄区', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371312', '371312', '河东区', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371321', '371321', '沂南县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371322', '371322', '郯城县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371323', '371323', '沂水县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371324', '371324', '兰陵县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371325', '371325', '费县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371326', '371326', '平邑县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371327', '371327', '莒南县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371328', '371328', '蒙阴县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371329', '371329', '临沭县', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371371', '371371', '临沂高新技术产业开发区', '3713', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3714', '3714', '德州市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371402', '371402', '德城区', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371403', '371403', '陵城区', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371422', '371422', '宁津县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371423', '371423', '庆云县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371424', '371424', '临邑县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371425', '371425', '齐河县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371426', '371426', '平原县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371427', '371427', '夏津县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371428', '371428', '武城县', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371471', '371471', '德州经济技术开发区', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371472', '371472', '德州运河经济开发区', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371481', '371481', '乐陵市', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371482', '371482', '禹城市', '3714', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3715', '3715', '聊城市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371502', '371502', '东昌府区', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371503', '371503', '茌平区', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371521', '371521', '阳谷县', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371522', '371522', '莘县', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371524', '371524', '东阿县', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371525', '371525', '冠县', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371526', '371526', '高唐县', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371581', '371581', '临清市', '3715', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3716', '3716', '滨州市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371602', '371602', '滨城区', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371603', '371603', '沾化区', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371621', '371621', '惠民县', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371622', '371622', '阳信县', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371623', '371623', '无棣县', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371625', '371625', '博兴县', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371681', '371681', '邹平市', '3716', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('3717', '3717', '菏泽市', '37', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371702', '371702', '牡丹区', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371703', '371703', '定陶区', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371721', '371721', '曹县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371722', '371722', '单县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371723', '371723', '成武县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371724', '371724', '巨野县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371725', '371725', '郓城县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371726', '371726', '鄄城县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371728', '371728', '东明县', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371771', '371771', '菏泽经济技术开发区', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('371772', '371772', '菏泽高新技术开发区', '3717', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('41', '41', '河南省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4101', '4101', '郑州市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410102', '410102', '中原区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410103', '410103', '二七区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410104', '410104', '管城回族区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410105', '410105', '金水区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410106', '410106', '上街区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410108', '410108', '惠济区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410122', '410122', '中牟县', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410171', '410171', '郑州经济技术开发区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410172', '410172', '郑州高新技术产业开发区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410173', '410173', '郑州航空港经济综合实验区', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410181', '410181', '巩义市', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410182', '410182', '荥阳市', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410183', '410183', '新密市', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410184', '410184', '新郑市', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410185', '410185', '登封市', '4101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4102', '4102', '开封市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410202', '410202', '龙亭区', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410203', '410203', '顺河回族区', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410204', '410204', '鼓楼区', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410205', '410205', '禹王台区', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410212', '410212', '祥符区', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410221', '410221', '杞县', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410222', '410222', '通许县', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410223', '410223', '尉氏县', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410225', '410225', '兰考县', '4102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4103', '4103', '洛阳市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410302', '410302', '老城区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410303', '410303', '西工区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410304', '410304', '瀍河回族区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410305', '410305', '涧西区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410306', '410306', '吉利区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410311', '410311', '洛龙区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410322', '410322', '孟津县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410323', '410323', '新安县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410324', '410324', '栾川县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410325', '410325', '嵩县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410326', '410326', '汝阳县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410327', '410327', '宜阳县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410328', '410328', '洛宁县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410329', '410329', '伊川县', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410371', '410371', '洛阳高新技术产业开发区', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410381', '410381', '偃师市', '4103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4104', '4104', '平顶山市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410402', '410402', '新华区', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410403', '410403', '卫东区', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410404', '410404', '石龙区', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410411', '410411', '湛河区', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410421', '410421', '宝丰县', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410422', '410422', '叶县', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410423', '410423', '鲁山县', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410425', '410425', '郏县', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410471', '410471', '平顶山高新技术产业开发区', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410472', '410472', '平顶山市城乡一体化示范区', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410481', '410481', '舞钢市', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410482', '410482', '汝州市', '4104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4105', '4105', '安阳市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410502', '410502', '文峰区', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410503', '410503', '北关区', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410505', '410505', '殷都区', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410506', '410506', '龙安区', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410522', '410522', '安阳县', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410523', '410523', '汤阴县', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410526', '410526', '滑县', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410527', '410527', '内黄县', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410571', '410571', '安阳高新技术产业开发区', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410581', '410581', '林州市', '4105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4106', '4106', '鹤壁市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410602', '410602', '鹤山区', '4106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410603', '410603', '山城区', '4106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410611', '410611', '淇滨区', '4106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410621', '410621', '浚县', '4106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410622', '410622', '淇县', '4106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410671', '410671', '鹤壁经济技术开发区', '4106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4107', '4107', '新乡市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410702', '410702', '红旗区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410703', '410703', '卫滨区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410704', '410704', '凤泉区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410711', '410711', '牧野区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410721', '410721', '新乡县', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410724', '410724', '获嘉县', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410725', '410725', '原阳县', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410726', '410726', '延津县', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410727', '410727', '封丘县', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410771', '410771', '新乡高新技术产业开发区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410772', '410772', '新乡经济技术开发区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410773', '410773', '新乡市平原城乡一体化示范区', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410781', '410781', '卫辉市', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410782', '410782', '辉县市', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410783', '410783', '长垣市', '4107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4108', '4108', '焦作市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410802', '410802', '解放区', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410803', '410803', '中站区', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410804', '410804', '马村区', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410811', '410811', '山阳区', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410821', '410821', '修武县', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410822', '410822', '博爱县', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410823', '410823', '武陟县', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410825', '410825', '温县', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410871', '410871', '焦作城乡一体化示范区', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410882', '410882', '沁阳市', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410883', '410883', '孟州市', '4108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4109', '4109', '濮阳市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410902', '410902', '华龙区', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410922', '410922', '清丰县', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410923', '410923', '南乐县', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410926', '410926', '范县', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410927', '410927', '台前县', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410928', '410928', '濮阳县', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410971', '410971', '河南濮阳工业园区', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('410972', '410972', '濮阳经济技术开发区', '4109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4110', '4110', '许昌市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411002', '411002', '魏都区', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411003', '411003', '建安区', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411024', '411024', '鄢陵县', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411025', '411025', '襄城县', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411071', '411071', '许昌经济技术开发区', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411081', '411081', '禹州市', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411082', '411082', '长葛市', '4110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4111', '4111', '漯河市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411102', '411102', '源汇区', '4111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411103', '411103', '郾城区', '4111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411104', '411104', '召陵区', '4111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411121', '411121', '舞阳县', '4111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411122', '411122', '临颍县', '4111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411171', '411171', '漯河经济技术开发区', '4111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4112', '4112', '三门峡市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411202', '411202', '湖滨区', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411203', '411203', '陕州区', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411221', '411221', '渑池县', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411224', '411224', '卢氏县', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411271', '411271', '河南三门峡经济开发区', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411281', '411281', '义马市', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411282', '411282', '灵宝市', '4112', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4113', '4113', '南阳市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411302', '411302', '宛城区', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411303', '411303', '卧龙区', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411321', '411321', '南召县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411322', '411322', '方城县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411323', '411323', '西峡县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411324', '411324', '镇平县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411325', '411325', '内乡县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411326', '411326', '淅川县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411327', '411327', '社旗县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411328', '411328', '唐河县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411329', '411329', '新野县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411330', '411330', '桐柏县', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411371', '411371', '南阳高新技术产业开发区', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411372', '411372', '南阳市城乡一体化示范区', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411381', '411381', '邓州市', '4113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4114', '4114', '商丘市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411402', '411402', '梁园区', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411403', '411403', '睢阳区', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411421', '411421', '民权县', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411422', '411422', '睢县', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411423', '411423', '宁陵县', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411424', '411424', '柘城县', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411425', '411425', '虞城县', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411426', '411426', '夏邑县', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411471', '411471', '豫东综合物流产业聚集区', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411472', '411472', '河南商丘经济开发区', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411481', '411481', '永城市', '4114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4115', '4115', '信阳市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411502', '411502', '浉河区', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411503', '411503', '平桥区', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411521', '411521', '罗山县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411522', '411522', '光山县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411523', '411523', '新县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411524', '411524', '商城县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411525', '411525', '固始县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411526', '411526', '潢川县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411527', '411527', '淮滨县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411528', '411528', '息县', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411571', '411571', '信阳高新技术产业开发区', '4115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4116', '4116', '周口市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411602', '411602', '川汇区', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411603', '411603', '淮阳区', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411621', '411621', '扶沟县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411622', '411622', '西华县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411623', '411623', '商水县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411624', '411624', '沈丘县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411625', '411625', '郸城县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411627', '411627', '太康县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411628', '411628', '鹿邑县', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411671', '411671', '河南周口经济开发区', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411681', '411681', '项城市', '4116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4117', '4117', '驻马店市', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411702', '411702', '驿城区', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411721', '411721', '西平县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411722', '411722', '上蔡县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411723', '411723', '平舆县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411724', '411724', '正阳县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411725', '411725', '确山县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411726', '411726', '泌阳县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411727', '411727', '汝南县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411728', '411728', '遂平县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411729', '411729', '新蔡县', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('411771', '411771', '河南驻马店经济开发区', '4117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4190', '4190', '省直辖县级行政区划', '41', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('419001', '419001', '济源市', '4190', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('42', '42', '湖北省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4201', '4201', '武汉市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420102', '420102', '江岸区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420103', '420103', '江汉区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420104', '420104', '硚口区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420105', '420105', '汉阳区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420106', '420106', '武昌区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420107', '420107', '青山区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420111', '420111', '洪山区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420112', '420112', '东西湖区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420113', '420113', '汉南区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420114', '420114', '蔡甸区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420115', '420115', '江夏区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420116', '420116', '黄陂区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420117', '420117', '新洲区', '4201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4202', '4202', '黄石市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420202', '420202', '黄石港区', '4202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420203', '420203', '西塞山区', '4202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420204', '420204', '下陆区', '4202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420205', '420205', '铁山区', '4202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420222', '420222', '阳新县', '4202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420281', '420281', '大冶市', '4202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4203', '4203', '十堰市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420302', '420302', '茅箭区', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420303', '420303', '张湾区', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420304', '420304', '郧阳区', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420322', '420322', '郧西县', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420323', '420323', '竹山县', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420324', '420324', '竹溪县', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420325', '420325', '房县', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420381', '420381', '丹江口市', '4203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4205', '4205', '宜昌市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420502', '420502', '西陵区', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420503', '420503', '伍家岗区', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420504', '420504', '点军区', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420505', '420505', '猇亭区', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420506', '420506', '夷陵区', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420525', '420525', '远安县', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420526', '420526', '兴山县', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420527', '420527', '秭归县', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420528', '420528', '长阳土家族自治县', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420529', '420529', '五峰土家族自治县', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420581', '420581', '宜都市', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420582', '420582', '当阳市', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420583', '420583', '枝江市', '4205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4206', '4206', '襄阳市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420602', '420602', '襄城区', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420606', '420606', '樊城区', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420607', '420607', '襄州区', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420624', '420624', '南漳县', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420625', '420625', '谷城县', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420626', '420626', '保康县', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420682', '420682', '老河口市', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420683', '420683', '枣阳市', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420684', '420684', '宜城市', '4206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4207', '4207', '鄂州市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420702', '420702', '梁子湖区', '4207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420703', '420703', '华容区', '4207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420704', '420704', '鄂城区', '4207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4208', '4208', '荆门市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420802', '420802', '东宝区', '4208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420804', '420804', '掇刀区', '4208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420822', '420822', '沙洋县', '4208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420881', '420881', '钟祥市', '4208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420882', '420882', '京山市', '4208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4209', '4209', '孝感市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420902', '420902', '孝南区', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420921', '420921', '孝昌县', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420922', '420922', '大悟县', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420923', '420923', '云梦县', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420981', '420981', '应城市', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420982', '420982', '安陆市', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('420984', '420984', '汉川市', '4209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4210', '4210', '荆州市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421002', '421002', '沙市区', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421003', '421003', '荆州区', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421022', '421022', '公安县', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421023', '421023', '监利县', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421024', '421024', '江陵县', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421071', '421071', '荆州经济技术开发区', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421081', '421081', '石首市', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421083', '421083', '洪湖市', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421087', '421087', '松滋市', '4210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4211', '4211', '黄冈市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421102', '421102', '黄州区', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421121', '421121', '团风县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421122', '421122', '红安县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421123', '421123', '罗田县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421124', '421124', '英山县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421125', '421125', '浠水县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421126', '421126', '蕲春县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421127', '421127', '黄梅县', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421171', '421171', '龙感湖管理区', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421181', '421181', '麻城市', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421182', '421182', '武穴市', '4211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4212', '4212', '咸宁市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421202', '421202', '咸安区', '4212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421221', '421221', '嘉鱼县', '4212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421222', '421222', '通城县', '4212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421223', '421223', '崇阳县', '4212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421224', '421224', '通山县', '4212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421281', '421281', '赤壁市', '4212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4213', '4213', '随州市', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421303', '421303', '曾都区', '4213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421321', '421321', '随县', '4213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('421381', '421381', '广水市', '4213', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4228', '4228', '恩施土家族苗族自治州', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422801', '422801', '恩施市', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422802', '422802', '利川市', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422822', '422822', '建始县', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422823', '422823', '巴东县', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422825', '422825', '宣恩县', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422826', '422826', '咸丰县', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422827', '422827', '来凤县', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('422828', '422828', '鹤峰县', '4228', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4290', '4290', '省直辖县级行政区划', '42', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('429004', '429004', '仙桃市', '4290', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('429005', '429005', '潜江市', '4290', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('429006', '429006', '天门市', '4290', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('429021', '429021', '神农架林区', '4290', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('43', '43', '湖南省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4301', '4301', '长沙市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430102', '430102', '芙蓉区', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430103', '430103', '天心区', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430104', '430104', '岳麓区', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430105', '430105', '开福区', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430111', '430111', '雨花区', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430112', '430112', '望城区', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430121', '430121', '长沙县', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430181', '430181', '浏阳市', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430182', '430182', '宁乡市', '4301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4302', '4302', '株洲市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430202', '430202', '荷塘区', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430203', '430203', '芦淞区', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430204', '430204', '石峰区', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430211', '430211', '天元区', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430212', '430212', '渌口区', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430223', '430223', '攸县', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430224', '430224', '茶陵县', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430225', '430225', '炎陵县', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430271', '430271', '云龙示范区', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430281', '430281', '醴陵市', '4302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4303', '4303', '湘潭市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430302', '430302', '雨湖区', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430304', '430304', '岳塘区', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430321', '430321', '湘潭县', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430371', '430371', '湖南湘潭高新技术产业园区', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430372', '430372', '湘潭昭山示范区', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430373', '430373', '湘潭九华示范区', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430381', '430381', '湘乡市', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430382', '430382', '韶山市', '4303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4304', '4304', '衡阳市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430405', '430405', '珠晖区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430406', '430406', '雁峰区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430407', '430407', '石鼓区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430408', '430408', '蒸湘区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430412', '430412', '南岳区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430421', '430421', '衡阳县', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430422', '430422', '衡南县', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430423', '430423', '衡山县', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430424', '430424', '衡东县', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430426', '430426', '祁东县', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430471', '430471', '衡阳综合保税区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430472', '430472', '湖南衡阳高新技术产业园区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430473', '430473', '湖南衡阳松木经济开发区', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430481', '430481', '耒阳市', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430482', '430482', '常宁市', '4304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4305', '4305', '邵阳市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430502', '430502', '双清区', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430503', '430503', '大祥区', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430511', '430511', '北塔区', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430522', '430522', '新邵县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430523', '430523', '邵阳县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430524', '430524', '隆回县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430525', '430525', '洞口县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430527', '430527', '绥宁县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430528', '430528', '新宁县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430529', '430529', '城步苗族自治县', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430581', '430581', '武冈市', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430582', '430582', '邵东市', '4305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4306', '4306', '岳阳市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430602', '430602', '岳阳楼区', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430603', '430603', '云溪区', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430611', '430611', '君山区', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430621', '430621', '岳阳县', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430623', '430623', '华容县', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430624', '430624', '湘阴县', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430626', '430626', '平江县', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430671', '430671', '岳阳市屈原管理区', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430681', '430681', '汨罗市', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430682', '430682', '临湘市', '4306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4307', '4307', '常德市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430702', '430702', '武陵区', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430703', '430703', '鼎城区', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430721', '430721', '安乡县', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430722', '430722', '汉寿县', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430723', '430723', '澧县', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430724', '430724', '临澧县', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430725', '430725', '桃源县', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430726', '430726', '石门县', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430771', '430771', '常德市西洞庭管理区', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430781', '430781', '津市市', '4307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4308', '4308', '张家界市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430802', '430802', '永定区', '4308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430811', '430811', '武陵源区', '4308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430821', '430821', '慈利县', '4308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430822', '430822', '桑植县', '4308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4309', '4309', '益阳市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430902', '430902', '资阳区', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430903', '430903', '赫山区', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430921', '430921', '南县', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430922', '430922', '桃江县', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430923', '430923', '安化县', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430971', '430971', '益阳市大通湖管理区', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430972', '430972', '湖南益阳高新技术产业园区', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('430981', '430981', '沅江市', '4309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4310', '4310', '郴州市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431002', '431002', '北湖区', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431003', '431003', '苏仙区', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431021', '431021', '桂阳县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431022', '431022', '宜章县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431023', '431023', '永兴县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431024', '431024', '嘉禾县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431025', '431025', '临武县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431026', '431026', '汝城县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431027', '431027', '桂东县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431028', '431028', '安仁县', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431081', '431081', '资兴市', '4310', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4311', '4311', '永州市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431102', '431102', '零陵区', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431103', '431103', '冷水滩区', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431121', '431121', '祁阳县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431122', '431122', '东安县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431123', '431123', '双牌县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431124', '431124', '道县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431125', '431125', '江永县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431126', '431126', '宁远县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431127', '431127', '蓝山县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431128', '431128', '新田县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431129', '431129', '江华瑶族自治县', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431171', '431171', '永州经济技术开发区', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431172', '431172', '永州市金洞管理区', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431173', '431173', '永州市回龙圩管理区', '4311', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4312', '4312', '怀化市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431202', '431202', '鹤城区', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431221', '431221', '中方县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431222', '431222', '沅陵县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431223', '431223', '辰溪县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431224', '431224', '溆浦县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431225', '431225', '会同县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431226', '431226', '麻阳苗族自治县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431227', '431227', '新晃侗族自治县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431228', '431228', '芷江侗族自治县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431229', '431229', '靖州苗族侗族自治县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431230', '431230', '通道侗族自治县', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431271', '431271', '怀化市洪江管理区', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431281', '431281', '洪江市', '4312', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4313', '4313', '娄底市', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431302', '431302', '娄星区', '4313', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431321', '431321', '双峰县', '4313', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431322', '431322', '新化县', '4313', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431381', '431381', '冷水江市', '4313', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('431382', '431382', '涟源市', '4313', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4331', '4331', '湘西土家族苗族自治州', '43', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433101', '433101', '吉首市', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433122', '433122', '泸溪县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433123', '433123', '凤凰县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433124', '433124', '花垣县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433125', '433125', '保靖县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433126', '433126', '古丈县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433127', '433127', '永顺县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('433130', '433130', '龙山县', '4331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('44', '44', '广东省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4401', '4401', '广州市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440103', '440103', '荔湾区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440104', '440104', '越秀区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440105', '440105', '海珠区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440106', '440106', '天河区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440111', '440111', '白云区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440112', '440112', '黄埔区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440113', '440113', '番禺区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440114', '440114', '花都区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440115', '440115', '南沙区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440117', '440117', '从化区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440118', '440118', '增城区', '4401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4402', '4402', '韶关市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440203', '440203', '武江区', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440204', '440204', '浈江区', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440205', '440205', '曲江区', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440222', '440222', '始兴县', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440224', '440224', '仁化县', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440229', '440229', '翁源县', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440232', '440232', '乳源瑶族自治县', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440233', '440233', '新丰县', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440281', '440281', '乐昌市', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440282', '440282', '南雄市', '4402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4403', '4403', '深圳市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440303', '440303', '罗湖区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440304', '440304', '福田区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440305', '440305', '南山区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440306', '440306', '宝安区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440307', '440307', '龙岗区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440308', '440308', '盐田区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440309', '440309', '龙华区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440310', '440310', '坪山区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440311', '440311', '光明区', '4403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4404', '4404', '珠海市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440402', '440402', '香洲区', '4404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440403', '440403', '斗门区', '4404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440404', '440404', '金湾区', '4404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4405', '4405', '汕头市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440507', '440507', '龙湖区', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440511', '440511', '金平区', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440512', '440512', '濠江区', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440513', '440513', '潮阳区', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440514', '440514', '潮南区', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440515', '440515', '澄海区', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440523', '440523', '南澳县', '4405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4406', '4406', '佛山市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440604', '440604', '禅城区', '4406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440605', '440605', '南海区', '4406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440606', '440606', '顺德区', '4406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440607', '440607', '三水区', '4406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440608', '440608', '高明区', '4406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4407', '4407', '江门市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440703', '440703', '蓬江区', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440704', '440704', '江海区', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440705', '440705', '新会区', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440781', '440781', '台山市', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440783', '440783', '开平市', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440784', '440784', '鹤山市', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440785', '440785', '恩平市', '4407', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4408', '4408', '湛江市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440802', '440802', '赤坎区', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440803', '440803', '霞山区', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440804', '440804', '坡头区', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440811', '440811', '麻章区', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440823', '440823', '遂溪县', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440825', '440825', '徐闻县', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440881', '440881', '廉江市', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440882', '440882', '雷州市', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440883', '440883', '吴川市', '4408', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4409', '4409', '茂名市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440902', '440902', '茂南区', '4409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440904', '440904', '电白区', '4409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440981', '440981', '高州市', '4409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440982', '440982', '化州市', '4409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('440983', '440983', '信宜市', '4409', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4412', '4412', '肇庆市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441202', '441202', '端州区', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441203', '441203', '鼎湖区', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441204', '441204', '高要区', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441223', '441223', '广宁县', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441224', '441224', '怀集县', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441225', '441225', '封开县', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441226', '441226', '德庆县', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441284', '441284', '四会市', '4412', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4413', '4413', '惠州市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441302', '441302', '惠城区', '4413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441303', '441303', '惠阳区', '4413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441322', '441322', '博罗县', '4413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441323', '441323', '惠东县', '4413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441324', '441324', '龙门县', '4413', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4414', '4414', '梅州市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441402', '441402', '梅江区', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441403', '441403', '梅县区', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441422', '441422', '大埔县', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441423', '441423', '丰顺县', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441424', '441424', '五华县', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441426', '441426', '平远县', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441427', '441427', '蕉岭县', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441481', '441481', '兴宁市', '4414', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4415', '4415', '汕尾市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441502', '441502', '城区', '4415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441521', '441521', '海丰县', '4415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441523', '441523', '陆河县', '4415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441581', '441581', '陆丰市', '4415', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4416', '4416', '河源市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441602', '441602', '源城区', '4416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441621', '441621', '紫金县', '4416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441622', '441622', '龙川县', '4416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441623', '441623', '连平县', '4416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441624', '441624', '和平县', '4416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441625', '441625', '东源县', '4416', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4417', '4417', '阳江市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441702', '441702', '江城区', '4417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441704', '441704', '阳东区', '4417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441721', '441721', '阳西县', '4417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441781', '441781', '阳春市', '4417', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4418', '4418', '清远市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441802', '441802', '清城区', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441803', '441803', '清新区', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441821', '441821', '佛冈县', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441823', '441823', '阳山县', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441825', '441825', '连山壮族瑶族自治县', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441826', '441826', '连南瑶族自治县', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441881', '441881', '英德市', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441882', '441882', '连州市', '4418', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4419', '4419', '东莞市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900003', '441900003', '东城街道', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900004', '441900004', '南城街道', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900005', '441900005', '万江街道', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900006', '441900006', '莞城街道', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900101', '441900101', '石碣镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900102', '441900102', '石龙镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900103', '441900103', '茶山镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900104', '441900104', '石排镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900105', '441900105', '企石镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900106', '441900106', '横沥镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900107', '441900107', '桥头镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900108', '441900108', '谢岗镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900109', '441900109', '东坑镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900110', '441900110', '常平镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900111', '441900111', '寮步镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900112', '441900112', '樟木头镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900113', '441900113', '大朗镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900114', '441900114', '黄江镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900115', '441900115', '清溪镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900116', '441900116', '塘厦镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900117', '441900117', '凤岗镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900118', '441900118', '大岭山镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900119', '441900119', '长安镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900121', '441900121', '虎门镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900122', '441900122', '厚街镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900123', '441900123', '沙田镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900124', '441900124', '道滘镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900125', '441900125', '洪梅镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900126', '441900126', '麻涌镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900127', '441900127', '望牛墩镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900128', '441900128', '中堂镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900129', '441900129', '高埗镇', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900401', '441900401', '松山湖', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900402', '441900402', '东莞港', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('441900403', '441900403', '东莞生态园', '4419', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4420', '4420', '中山市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000001', '442000001', '石岐街道', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000002', '442000002', '东区街道', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000003', '442000003', '中山港街道', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000004', '442000004', '西区街道', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000005', '442000005', '南区街道', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000006', '442000006', '五桂山街道', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000100', '442000100', '小榄镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000101', '442000101', '黄圃镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000102', '442000102', '民众镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000103', '442000103', '东凤镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000104', '442000104', '东升镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000105', '442000105', '古镇镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000106', '442000106', '沙溪镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000107', '442000107', '坦洲镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000108', '442000108', '港口镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000109', '442000109', '三角镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000110', '442000110', '横栏镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000111', '442000111', '南头镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000112', '442000112', '阜沙镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000113', '442000113', '南朗镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000114', '442000114', '三乡镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000115', '442000115', '板芙镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000116', '442000116', '大涌镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('442000117', '442000117', '神湾镇', '4420', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4451', '4451', '潮州市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445102', '445102', '湘桥区', '4451', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445103', '445103', '潮安区', '4451', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445122', '445122', '饶平县', '4451', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4452', '4452', '揭阳市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445202', '445202', '榕城区', '4452', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445203', '445203', '揭东区', '4452', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445222', '445222', '揭西县', '4452', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445224', '445224', '惠来县', '4452', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445281', '445281', '普宁市', '4452', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4453', '4453', '云浮市', '44', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445302', '445302', '云城区', '4453', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445303', '445303', '云安区', '4453', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445321', '445321', '新兴县', '4453', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445322', '445322', '郁南县', '4453', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('445381', '445381', '罗定市', '4453', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('45', '45', '广西壮族自治区', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4501', '4501', '南宁市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450102', '450102', '兴宁区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450103', '450103', '青秀区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450105', '450105', '江南区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450107', '450107', '西乡塘区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450108', '450108', '良庆区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450109', '450109', '邕宁区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450110', '450110', '武鸣区', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450123', '450123', '隆安县', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450124', '450124', '马山县', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450125', '450125', '上林县', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450126', '450126', '宾阳县', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450127', '450127', '横县', '4501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4502', '4502', '柳州市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450202', '450202', '城中区', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450203', '450203', '鱼峰区', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450204', '450204', '柳南区', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450205', '450205', '柳北区', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450206', '450206', '柳江区', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450222', '450222', '柳城县', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450223', '450223', '鹿寨县', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450224', '450224', '融安县', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450225', '450225', '融水苗族自治县', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450226', '450226', '三江侗族自治县', '4502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4503', '4503', '桂林市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450302', '450302', '秀峰区', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450303', '450303', '叠彩区', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450304', '450304', '象山区', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450305', '450305', '七星区', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450311', '450311', '雁山区', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450312', '450312', '临桂区', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450321', '450321', '阳朔县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450323', '450323', '灵川县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450324', '450324', '全州县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450325', '450325', '兴安县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450326', '450326', '永福县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450327', '450327', '灌阳县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450328', '450328', '龙胜各族自治县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450329', '450329', '资源县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450330', '450330', '平乐县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450332', '450332', '恭城瑶族自治县', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450381', '450381', '荔浦市', '4503', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4504', '4504', '梧州市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450403', '450403', '万秀区', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450405', '450405', '长洲区', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450406', '450406', '龙圩区', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450421', '450421', '苍梧县', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450422', '450422', '藤县', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450423', '450423', '蒙山县', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450481', '450481', '岑溪市', '4504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4505', '4505', '北海市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450502', '450502', '海城区', '4505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450503', '450503', '银海区', '4505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450512', '450512', '铁山港区', '4505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450521', '450521', '合浦县', '4505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4506', '4506', '防城港市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450602', '450602', '港口区', '4506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450603', '450603', '防城区', '4506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450621', '450621', '上思县', '4506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450681', '450681', '东兴市', '4506', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4507', '4507', '钦州市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450702', '450702', '钦南区', '4507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450703', '450703', '钦北区', '4507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450721', '450721', '灵山县', '4507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450722', '450722', '浦北县', '4507', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4508', '4508', '贵港市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450802', '450802', '港北区', '4508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450803', '450803', '港南区', '4508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450804', '450804', '覃塘区', '4508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450821', '450821', '平南县', '4508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450881', '450881', '桂平市', '4508', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4509', '4509', '玉林市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450902', '450902', '玉州区', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450903', '450903', '福绵区', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450921', '450921', '容县', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450922', '450922', '陆川县', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450923', '450923', '博白县', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450924', '450924', '兴业县', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('450981', '450981', '北流市', '4509', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4510', '4510', '百色市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451002', '451002', '右江区', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451003', '451003', '田阳区', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451022', '451022', '田东县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451024', '451024', '德保县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451026', '451026', '那坡县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451027', '451027', '凌云县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451028', '451028', '乐业县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451029', '451029', '田林县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451030', '451030', '西林县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451031', '451031', '隆林各族自治县', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451081', '451081', '靖西市', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451082', '451082', '平果市', '4510', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4511', '4511', '贺州市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451102', '451102', '八步区', '4511', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451103', '451103', '平桂区', '4511', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451121', '451121', '昭平县', '4511', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451122', '451122', '钟山县', '4511', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451123', '451123', '富川瑶族自治县', '4511', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4512', '4512', '河池市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451202', '451202', '金城江区', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451203', '451203', '宜州区', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451221', '451221', '南丹县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451222', '451222', '天峨县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451223', '451223', '凤山县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451224', '451224', '东兰县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451225', '451225', '罗城仫佬族自治县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451226', '451226', '环江毛南族自治县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451227', '451227', '巴马瑶族自治县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451228', '451228', '都安瑶族自治县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451229', '451229', '大化瑶族自治县', '4512', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4513', '4513', '来宾市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451302', '451302', '兴宾区', '4513', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451321', '451321', '忻城县', '4513', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451322', '451322', '象州县', '4513', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451323', '451323', '武宣县', '4513', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451324', '451324', '金秀瑶族自治县', '4513', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451381', '451381', '合山市', '4513', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4514', '4514', '崇左市', '45', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451402', '451402', '江州区', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451421', '451421', '扶绥县', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451422', '451422', '宁明县', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451423', '451423', '龙州县', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451424', '451424', '大新县', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451425', '451425', '天等县', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('451481', '451481', '凭祥市', '4514', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('46', '46', '海南省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4601', '4601', '海口市', '46', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460105', '460105', '秀英区', '4601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460106', '460106', '龙华区', '4601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460107', '460107', '琼山区', '4601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460108', '460108', '美兰区', '4601', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4602', '4602', '三亚市', '46', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460202', '460202', '海棠区', '4602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460203', '460203', '吉阳区', '4602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460204', '460204', '天涯区', '4602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460205', '460205', '崖州区', '4602', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4603', '4603', '三沙市', '46', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460321', '460321', '西沙群岛', '4603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460322', '460322', '南沙群岛', '4603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460323', '460323', '中沙群岛的岛礁及其海域', '4603', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4604', '4604', '儋州市', '46', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400100', '460400100', '那大镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400101', '460400101', '和庆镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400102', '460400102', '南丰镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400103', '460400103', '大成镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400104', '460400104', '雅星镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400105', '460400105', '兰洋镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400106', '460400106', '光村镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400107', '460400107', '木棠镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400108', '460400108', '海头镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400109', '460400109', '峨蔓镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400111', '460400111', '王五镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400112', '460400112', '白马井镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400113', '460400113', '中和镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400114', '460400114', '排浦镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400115', '460400115', '东成镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400116', '460400116', '新州镇', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400499', '460400499', '洋浦经济开发区', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('460400500', '460400500', '华南热作学院', '4604', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('4690', '4690', '省直辖县级行政区划', '46', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469001', '469001', '五指山市', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469002', '469002', '琼海市', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469005', '469005', '文昌市', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469006', '469006', '万宁市', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469007', '469007', '东方市', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469021', '469021', '定安县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469022', '469022', '屯昌县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469023', '469023', '澄迈县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469024', '469024', '临高县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469025', '469025', '白沙黎族自治县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469026', '469026', '昌江黎族自治县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469027', '469027', '乐东黎族自治县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469028', '469028', '陵水黎族自治县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469029', '469029', '保亭黎族苗族自治县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('469030', '469030', '琼中黎族苗族自治县', '4690', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('50', '50', '重庆市', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5001', '5001', '市辖区', '50', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500101', '500101', '万州区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500102', '500102', '涪陵区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500103', '500103', '渝中区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500104', '500104', '大渡口区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500105', '500105', '江北区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500106', '500106', '沙坪坝区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500107', '500107', '九龙坡区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500108', '500108', '南岸区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500109', '500109', '北碚区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500110', '500110', '綦江区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500111', '500111', '大足区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500112', '500112', '渝北区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500113', '500113', '巴南区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500114', '500114', '黔江区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500115', '500115', '长寿区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500116', '500116', '江津区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500117', '500117', '合川区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500118', '500118', '永川区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500119', '500119', '南川区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500120', '500120', '璧山区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500151', '500151', '铜梁区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500152', '500152', '潼南区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500153', '500153', '荣昌区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500154', '500154', '开州区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500155', '500155', '梁平区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500156', '500156', '武隆区', '5001', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5002', '5002', '县', '50', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500229', '500229', '城口县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500230', '500230', '丰都县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500231', '500231', '垫江县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500233', '500233', '忠县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500235', '500235', '云阳县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500236', '500236', '奉节县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500237', '500237', '巫山县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500238', '500238', '巫溪县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500240', '500240', '石柱土家族自治县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500241', '500241', '秀山土家族苗族自治县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500242', '500242', '酉阳土家族苗族自治县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('500243', '500243', '彭水苗族土家族自治县', '5002', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('51', '51', '四川省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5101', '5101', '成都市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510104', '510104', '锦江区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510105', '510105', '青羊区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510106', '510106', '金牛区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510107', '510107', '武侯区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510108', '510108', '成华区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510112', '510112', '龙泉驿区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510113', '510113', '青白江区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510114', '510114', '新都区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510115', '510115', '温江区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510116', '510116', '双流区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510117', '510117', '郫都区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510118', '510118', '新津区', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510121', '510121', '金堂县', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510129', '510129', '大邑县', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510131', '510131', '蒲江县', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510181', '510181', '都江堰市', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510182', '510182', '彭州市', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510183', '510183', '邛崃市', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510184', '510184', '崇州市', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510185', '510185', '简阳市', '5101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5103', '5103', '自贡市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510302', '510302', '自流井区', '5103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510303', '510303', '贡井区', '5103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510304', '510304', '大安区', '5103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510311', '510311', '沿滩区', '5103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510321', '510321', '荣县', '5103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510322', '510322', '富顺县', '5103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5104', '5104', '攀枝花市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510402', '510402', '东区', '5104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510403', '510403', '西区', '5104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510411', '510411', '仁和区', '5104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510421', '510421', '米易县', '5104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510422', '510422', '盐边县', '5104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5105', '5105', '泸州市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510502', '510502', '江阳区', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510503', '510503', '纳溪区', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510504', '510504', '龙马潭区', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510521', '510521', '泸县', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510522', '510522', '合江县', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510524', '510524', '叙永县', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510525', '510525', '古蔺县', '5105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5106', '5106', '德阳市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510603', '510603', '旌阳区', '5106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510604', '510604', '罗江区', '5106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510623', '510623', '中江县', '5106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510681', '510681', '广汉市', '5106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510682', '510682', '什邡市', '5106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510683', '510683', '绵竹市', '5106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5107', '5107', '绵阳市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510703', '510703', '涪城区', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510704', '510704', '游仙区', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510705', '510705', '安州区', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510722', '510722', '三台县', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510723', '510723', '盐亭县', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510725', '510725', '梓潼县', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510726', '510726', '北川羌族自治县', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510727', '510727', '平武县', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510781', '510781', '江油市', '5107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5108', '5108', '广元市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510802', '510802', '利州区', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510811', '510811', '昭化区', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510812', '510812', '朝天区', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510821', '510821', '旺苍县', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510822', '510822', '青川县', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510823', '510823', '剑阁县', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510824', '510824', '苍溪县', '5108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5109', '5109', '遂宁市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510903', '510903', '船山区', '5109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510904', '510904', '安居区', '5109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510921', '510921', '蓬溪县', '5109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510923', '510923', '大英县', '5109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('510981', '510981', '射洪市', '5109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5110', '5110', '内江市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511002', '511002', '市中区', '5110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511011', '511011', '东兴区', '5110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511024', '511024', '威远县', '5110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511025', '511025', '资中县', '5110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511071', '511071', '内江经济开发区', '5110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511083', '511083', '隆昌市', '5110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5111', '5111', '乐山市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511102', '511102', '市中区', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511111', '511111', '沙湾区', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511112', '511112', '五通桥区', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511113', '511113', '金口河区', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511123', '511123', '犍为县', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511124', '511124', '井研县', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511126', '511126', '夹江县', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511129', '511129', '沐川县', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511132', '511132', '峨边彝族自治县', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511133', '511133', '马边彝族自治县', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511181', '511181', '峨眉山市', '5111', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5113', '5113', '南充市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511302', '511302', '顺庆区', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511303', '511303', '高坪区', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511304', '511304', '嘉陵区', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511321', '511321', '南部县', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511322', '511322', '营山县', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511323', '511323', '蓬安县', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511324', '511324', '仪陇县', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511325', '511325', '西充县', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511381', '511381', '阆中市', '5113', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5114', '5114', '眉山市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511402', '511402', '东坡区', '5114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511403', '511403', '彭山区', '5114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511421', '511421', '仁寿县', '5114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511423', '511423', '洪雅县', '5114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511424', '511424', '丹棱县', '5114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511425', '511425', '青神县', '5114', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5115', '5115', '宜宾市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511502', '511502', '翠屏区', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511503', '511503', '南溪区', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511504', '511504', '叙州区', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511523', '511523', '江安县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511524', '511524', '长宁县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511525', '511525', '高县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511526', '511526', '珙县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511527', '511527', '筠连县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511528', '511528', '兴文县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511529', '511529', '屏山县', '5115', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5116', '5116', '广安市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511602', '511602', '广安区', '5116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511603', '511603', '前锋区', '5116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511621', '511621', '岳池县', '5116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511622', '511622', '武胜县', '5116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511623', '511623', '邻水县', '5116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511681', '511681', '华蓥市', '5116', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5117', '5117', '达州市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511702', '511702', '通川区', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511703', '511703', '达川区', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511722', '511722', '宣汉县', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511723', '511723', '开江县', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511724', '511724', '大竹县', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511725', '511725', '渠县', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511771', '511771', '达州经济开发区', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511781', '511781', '万源市', '5117', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5118', '5118', '雅安市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511802', '511802', '雨城区', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511803', '511803', '名山区', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511822', '511822', '荥经县', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511823', '511823', '汉源县', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511824', '511824', '石棉县', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511825', '511825', '天全县', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511826', '511826', '芦山县', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511827', '511827', '宝兴县', '5118', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5119', '5119', '巴中市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511902', '511902', '巴州区', '5119', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511903', '511903', '恩阳区', '5119', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511921', '511921', '通江县', '5119', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511922', '511922', '南江县', '5119', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511923', '511923', '平昌县', '5119', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('511971', '511971', '巴中经济开发区', '5119', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5120', '5120', '资阳市', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('512002', '512002', '雁江区', '5120', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('512021', '512021', '安岳县', '5120', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('512022', '512022', '乐至县', '5120', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5132', '5132', '阿坝藏族羌族自治州', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513201', '513201', '马尔康市', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513221', '513221', '汶川县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513222', '513222', '理县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513223', '513223', '茂县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513224', '513224', '松潘县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513225', '513225', '九寨沟县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513226', '513226', '金川县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513227', '513227', '小金县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513228', '513228', '黑水县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513230', '513230', '壤塘县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513231', '513231', '阿坝县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513232', '513232', '若尔盖县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513233', '513233', '红原县', '5132', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5133', '5133', '甘孜藏族自治州', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513301', '513301', '康定市', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513322', '513322', '泸定县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513323', '513323', '丹巴县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513324', '513324', '九龙县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513325', '513325', '雅江县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513326', '513326', '道孚县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513327', '513327', '炉霍县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513328', '513328', '甘孜县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513329', '513329', '新龙县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513330', '513330', '德格县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513331', '513331', '白玉县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513332', '513332', '石渠县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513333', '513333', '色达县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513334', '513334', '理塘县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513335', '513335', '巴塘县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513336', '513336', '乡城县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513337', '513337', '稻城县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513338', '513338', '得荣县', '5133', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5134', '5134', '凉山彝族自治州', '51', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513401', '513401', '西昌市', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513422', '513422', '木里藏族自治县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513423', '513423', '盐源县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513424', '513424', '德昌县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513425', '513425', '会理县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513426', '513426', '会东县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513427', '513427', '宁南县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513428', '513428', '普格县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513429', '513429', '布拖县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513430', '513430', '金阳县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513431', '513431', '昭觉县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513432', '513432', '喜德县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513433', '513433', '冕宁县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513434', '513434', '越西县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513435', '513435', '甘洛县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513436', '513436', '美姑县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('513437', '513437', '雷波县', '5134', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('52', '52', '贵州省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5201', '5201', '贵阳市', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520102', '520102', '南明区', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520103', '520103', '云岩区', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520111', '520111', '花溪区', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520112', '520112', '乌当区', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520113', '520113', '白云区', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520115', '520115', '观山湖区', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520121', '520121', '开阳县', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520122', '520122', '息烽县', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520123', '520123', '修文县', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520181', '520181', '清镇市', '5201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5202', '5202', '六盘水市', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520201', '520201', '钟山区', '5202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520203', '520203', '六枝特区', '5202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520221', '520221', '水城县', '5202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520281', '520281', '盘州市', '5202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5203', '5203', '遵义市', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520302', '520302', '红花岗区', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520303', '520303', '汇川区', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520304', '520304', '播州区', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520322', '520322', '桐梓县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520323', '520323', '绥阳县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520324', '520324', '正安县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520325', '520325', '道真仡佬族苗族自治县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520326', '520326', '务川仡佬族苗族自治县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520327', '520327', '凤冈县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520328', '520328', '湄潭县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520329', '520329', '余庆县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520330', '520330', '习水县', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520381', '520381', '赤水市', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520382', '520382', '仁怀市', '5203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5204', '5204', '安顺市', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520402', '520402', '西秀区', '5204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520403', '520403', '平坝区', '5204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520422', '520422', '普定县', '5204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520423', '520423', '镇宁布依族苗族自治县', '5204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520424', '520424', '关岭布依族苗族自治县', '5204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520425', '520425', '紫云苗族布依族自治县', '5204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5205', '5205', '毕节市', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520502', '520502', '七星关区', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520521', '520521', '大方县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520522', '520522', '黔西县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520523', '520523', '金沙县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520524', '520524', '织金县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520525', '520525', '纳雍县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520526', '520526', '威宁彝族回族苗族自治县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520527', '520527', '赫章县', '5205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5206', '5206', '铜仁市', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520602', '520602', '碧江区', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520603', '520603', '万山区', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520621', '520621', '江口县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520622', '520622', '玉屏侗族自治县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520623', '520623', '石阡县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520624', '520624', '思南县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520625', '520625', '印江土家族苗族自治县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520626', '520626', '德江县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520627', '520627', '沿河土家族自治县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('520628', '520628', '松桃苗族自治县', '5206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5223', '5223', '黔西南布依族苗族自治州', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522301', '522301', '兴义市', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522302', '522302', '兴仁市', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522323', '522323', '普安县', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522324', '522324', '晴隆县', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522325', '522325', '贞丰县', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522326', '522326', '望谟县', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522327', '522327', '册亨县', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522328', '522328', '安龙县', '5223', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5226', '5226', '黔东南苗族侗族自治州', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522601', '522601', '凯里市', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522622', '522622', '黄平县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522623', '522623', '施秉县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522624', '522624', '三穗县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522625', '522625', '镇远县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522626', '522626', '岑巩县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522627', '522627', '天柱县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522628', '522628', '锦屏县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522629', '522629', '剑河县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522630', '522630', '台江县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522631', '522631', '黎平县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522632', '522632', '榕江县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522633', '522633', '从江县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522634', '522634', '雷山县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522635', '522635', '麻江县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522636', '522636', '丹寨县', '5226', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5227', '5227', '黔南布依族苗族自治州', '52', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522701', '522701', '都匀市', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522702', '522702', '福泉市', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522722', '522722', '荔波县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522723', '522723', '贵定县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522725', '522725', '瓮安县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522726', '522726', '独山县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522727', '522727', '平塘县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522728', '522728', '罗甸县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522729', '522729', '长顺县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522730', '522730', '龙里县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522731', '522731', '惠水县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('522732', '522732', '三都水族自治县', '5227', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('53', '53', '云南省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5301', '5301', '昆明市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530102', '530102', '五华区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530103', '530103', '盘龙区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530111', '530111', '官渡区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530112', '530112', '西山区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530113', '530113', '东川区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530114', '530114', '呈贡区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530115', '530115', '晋宁区', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530124', '530124', '富民县', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530125', '530125', '宜良县', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530126', '530126', '石林彝族自治县', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530127', '530127', '嵩明县', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530128', '530128', '禄劝彝族苗族自治县', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530129', '530129', '寻甸回族彝族自治县', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530181', '530181', '安宁市', '5301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5303', '5303', '曲靖市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530302', '530302', '麒麟区', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530303', '530303', '沾益区', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530304', '530304', '马龙区', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530322', '530322', '陆良县', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530323', '530323', '师宗县', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530324', '530324', '罗平县', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530325', '530325', '富源县', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530326', '530326', '会泽县', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530381', '530381', '宣威市', '5303', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5304', '5304', '玉溪市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530402', '530402', '红塔区', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530403', '530403', '江川区', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530423', '530423', '通海县', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530424', '530424', '华宁县', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530425', '530425', '易门县', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530426', '530426', '峨山彝族自治县', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530427', '530427', '新平彝族傣族自治县', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530428', '530428', '元江哈尼族彝族傣族自治县', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530481', '530481', '澄江市', '5304', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5305', '5305', '保山市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530502', '530502', '隆阳区', '5305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530521', '530521', '施甸县', '5305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530523', '530523', '龙陵县', '5305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530524', '530524', '昌宁县', '5305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530581', '530581', '腾冲市', '5305', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5306', '5306', '昭通市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530602', '530602', '昭阳区', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530621', '530621', '鲁甸县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530622', '530622', '巧家县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530623', '530623', '盐津县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530624', '530624', '大关县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530625', '530625', '永善县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530626', '530626', '绥江县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530627', '530627', '镇雄县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530628', '530628', '彝良县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530629', '530629', '威信县', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530681', '530681', '水富市', '5306', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5307', '5307', '丽江市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530702', '530702', '古城区', '5307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530721', '530721', '玉龙纳西族自治县', '5307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530722', '530722', '永胜县', '5307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530723', '530723', '华坪县', '5307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530724', '530724', '宁蒗彝族自治县', '5307', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5308', '5308', '普洱市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530802', '530802', '思茅区', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530821', '530821', '宁洱哈尼族彝族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530822', '530822', '墨江哈尼族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530823', '530823', '景东彝族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530824', '530824', '景谷傣族彝族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530825', '530825', '镇沅彝族哈尼族拉祜族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530826', '530826', '江城哈尼族彝族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530827', '530827', '孟连傣族拉祜族佤族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530828', '530828', '澜沧拉祜族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530829', '530829', '西盟佤族自治县', '5308', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5309', '5309', '临沧市', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530902', '530902', '临翔区', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530921', '530921', '凤庆县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530922', '530922', '云县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530923', '530923', '永德县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530924', '530924', '镇康县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530925', '530925', '双江拉祜族佤族布朗族傣族自治县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530926', '530926', '耿马傣族佤族自治县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('530927', '530927', '沧源佤族自治县', '5309', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5323', '5323', '楚雄彝族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532301', '532301', '楚雄市', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532322', '532322', '双柏县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532323', '532323', '牟定县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532324', '532324', '南华县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532325', '532325', '姚安县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532326', '532326', '大姚县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532327', '532327', '永仁县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532328', '532328', '元谋县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532329', '532329', '武定县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532331', '532331', '禄丰县', '5323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5325', '5325', '红河哈尼族彝族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532501', '532501', '个旧市', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532502', '532502', '开远市', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532503', '532503', '蒙自市', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532504', '532504', '弥勒市', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532523', '532523', '屏边苗族自治县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532524', '532524', '建水县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532525', '532525', '石屏县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532527', '532527', '泸西县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532528', '532528', '元阳县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532529', '532529', '红河县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532530', '532530', '金平苗族瑶族傣族自治县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532531', '532531', '绿春县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532532', '532532', '河口瑶族自治县', '5325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5326', '5326', '文山壮族苗族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532601', '532601', '文山市', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532622', '532622', '砚山县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532623', '532623', '西畴县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532624', '532624', '麻栗坡县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532625', '532625', '马关县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532626', '532626', '丘北县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532627', '532627', '广南县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532628', '532628', '富宁县', '5326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5328', '5328', '西双版纳傣族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532801', '532801', '景洪市', '5328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532822', '532822', '勐海县', '5328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532823', '532823', '勐腊县', '5328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5329', '5329', '大理白族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532901', '532901', '大理市', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532922', '532922', '漾濞彝族自治县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532923', '532923', '祥云县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532924', '532924', '宾川县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532925', '532925', '弥渡县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532926', '532926', '南涧彝族自治县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532927', '532927', '巍山彝族回族自治县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532928', '532928', '永平县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532929', '532929', '云龙县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532930', '532930', '洱源县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532931', '532931', '剑川县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('532932', '532932', '鹤庆县', '5329', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5331', '5331', '德宏傣族景颇族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533102', '533102', '瑞丽市', '5331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533103', '533103', '芒市', '5331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533122', '533122', '梁河县', '5331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533123', '533123', '盈江县', '5331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533124', '533124', '陇川县', '5331', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5333', '5333', '怒江傈僳族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533301', '533301', '泸水市', '5333', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533323', '533323', '福贡县', '5333', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533324', '533324', '贡山独龙族怒族自治县', '5333', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533325', '533325', '兰坪白族普米族自治县', '5333', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5334', '5334', '迪庆藏族自治州', '53', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533401', '533401', '香格里拉市', '5334', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533422', '533422', '德钦县', '5334', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('533423', '533423', '维西傈僳族自治县', '5334', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('54', '54', '西藏自治区', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5401', '5401', '拉萨市', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540102', '540102', '城关区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540103', '540103', '堆龙德庆区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540104', '540104', '达孜区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540121', '540121', '林周县', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540122', '540122', '当雄县', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540123', '540123', '尼木县', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540124', '540124', '曲水县', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540127', '540127', '墨竹工卡县', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540171', '540171', '格尔木藏青工业园区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540172', '540172', '拉萨经济技术开发区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540173', '540173', '西藏文化旅游创意园区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540174', '540174', '达孜工业园区', '5401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5402', '5402', '日喀则市', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540202', '540202', '桑珠孜区', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540221', '540221', '南木林县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540222', '540222', '江孜县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540223', '540223', '定日县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540224', '540224', '萨迦县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540225', '540225', '拉孜县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540226', '540226', '昂仁县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540227', '540227', '谢通门县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540228', '540228', '白朗县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540229', '540229', '仁布县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540230', '540230', '康马县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540231', '540231', '定结县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540232', '540232', '仲巴县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540233', '540233', '亚东县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540234', '540234', '吉隆县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540235', '540235', '聂拉木县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540236', '540236', '萨嘎县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540237', '540237', '岗巴县', '5402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5403', '5403', '昌都市', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540302', '540302', '卡若区', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540321', '540321', '江达县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540322', '540322', '贡觉县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540323', '540323', '类乌齐县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540324', '540324', '丁青县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540325', '540325', '察雅县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540326', '540326', '八宿县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540327', '540327', '左贡县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540328', '540328', '芒康县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540329', '540329', '洛隆县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540330', '540330', '边坝县', '5403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5404', '5404', '林芝市', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540402', '540402', '巴宜区', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540421', '540421', '工布江达县', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540422', '540422', '米林县', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540423', '540423', '墨脱县', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540424', '540424', '波密县', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540425', '540425', '察隅县', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540426', '540426', '朗县', '5404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5405', '5405', '山南市', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540502', '540502', '乃东区', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540521', '540521', '扎囊县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540522', '540522', '贡嘎县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540523', '540523', '桑日县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540524', '540524', '琼结县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540525', '540525', '曲松县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540526', '540526', '措美县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540527', '540527', '洛扎县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540528', '540528', '加查县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540529', '540529', '隆子县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540530', '540530', '错那县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540531', '540531', '浪卡子县', '5405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5406', '5406', '那曲市', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540602', '540602', '色尼区', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540621', '540621', '嘉黎县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540622', '540622', '比如县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540623', '540623', '聂荣县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540624', '540624', '安多县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540625', '540625', '申扎县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540626', '540626', '索县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540627', '540627', '班戈县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540628', '540628', '巴青县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540629', '540629', '尼玛县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('540630', '540630', '双湖县', '5406', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('5425', '5425', '阿里地区', '54', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542521', '542521', '普兰县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542522', '542522', '札达县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542523', '542523', '噶尔县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542524', '542524', '日土县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542525', '542525', '革吉县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542526', '542526', '改则县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('542527', '542527', '措勤县', '5425', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('61', '61', '陕西省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6101', '6101', '西安市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610102', '610102', '新城区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610103', '610103', '碑林区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610104', '610104', '莲湖区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610111', '610111', '灞桥区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610112', '610112', '未央区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610113', '610113', '雁塔区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610114', '610114', '阎良区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610115', '610115', '临潼区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610116', '610116', '长安区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610117', '610117', '高陵区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610118', '610118', '鄠邑区', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610122', '610122', '蓝田县', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610124', '610124', '周至县', '6101', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6102', '6102', '铜川市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610202', '610202', '王益区', '6102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610203', '610203', '印台区', '6102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610204', '610204', '耀州区', '6102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610222', '610222', '宜君县', '6102', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6103', '6103', '宝鸡市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610302', '610302', '渭滨区', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610303', '610303', '金台区', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610304', '610304', '陈仓区', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610322', '610322', '凤翔县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610323', '610323', '岐山县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610324', '610324', '扶风县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610326', '610326', '眉县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610327', '610327', '陇县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610328', '610328', '千阳县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610329', '610329', '麟游县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610330', '610330', '凤县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610331', '610331', '太白县', '6103', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6104', '6104', '咸阳市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610402', '610402', '秦都区', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610403', '610403', '杨陵区', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610404', '610404', '渭城区', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610422', '610422', '三原县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610423', '610423', '泾阳县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610424', '610424', '乾县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610425', '610425', '礼泉县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610426', '610426', '永寿县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610428', '610428', '长武县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610429', '610429', '旬邑县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610430', '610430', '淳化县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610431', '610431', '武功县', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610481', '610481', '兴平市', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610482', '610482', '彬州市', '6104', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6105', '6105', '渭南市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610502', '610502', '临渭区', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610503', '610503', '华州区', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610522', '610522', '潼关县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610523', '610523', '大荔县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610524', '610524', '合阳县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610525', '610525', '澄城县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610526', '610526', '蒲城县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610527', '610527', '白水县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610528', '610528', '富平县', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610581', '610581', '韩城市', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610582', '610582', '华阴市', '6105', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6106', '6106', '延安市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610602', '610602', '宝塔区', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610603', '610603', '安塞区', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610621', '610621', '延长县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610622', '610622', '延川县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610625', '610625', '志丹县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610626', '610626', '吴起县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610627', '610627', '甘泉县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610628', '610628', '富县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610629', '610629', '洛川县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610630', '610630', '宜川县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610631', '610631', '黄龙县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610632', '610632', '黄陵县', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610681', '610681', '子长市', '6106', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6107', '6107', '汉中市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610702', '610702', '汉台区', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610703', '610703', '南郑区', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610722', '610722', '城固县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610723', '610723', '洋县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610724', '610724', '西乡县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610725', '610725', '勉县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610726', '610726', '宁强县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610727', '610727', '略阳县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610728', '610728', '镇巴县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610729', '610729', '留坝县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610730', '610730', '佛坪县', '6107', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6108', '6108', '榆林市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610802', '610802', '榆阳区', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610803', '610803', '横山区', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610822', '610822', '府谷县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610824', '610824', '靖边县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610825', '610825', '定边县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610826', '610826', '绥德县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610827', '610827', '米脂县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610828', '610828', '佳县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610829', '610829', '吴堡县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610830', '610830', '清涧县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610831', '610831', '子洲县', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610881', '610881', '神木市', '6108', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6109', '6109', '安康市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610902', '610902', '汉滨区', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610921', '610921', '汉阴县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610922', '610922', '石泉县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610923', '610923', '宁陕县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610924', '610924', '紫阳县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610925', '610925', '岚皋县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610926', '610926', '平利县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610927', '610927', '镇坪县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610928', '610928', '旬阳县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('610929', '610929', '白河县', '6109', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6110', '6110', '商洛市', '61', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611002', '611002', '商州区', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611021', '611021', '洛南县', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611022', '611022', '丹凤县', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611023', '611023', '商南县', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611024', '611024', '山阳县', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611025', '611025', '镇安县', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('611026', '611026', '柞水县', '6110', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('62', '62', '甘肃省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6201', '6201', '兰州市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620102', '620102', '城关区', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620103', '620103', '七里河区', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620104', '620104', '西固区', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620105', '620105', '安宁区', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620111', '620111', '红古区', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620121', '620121', '永登县', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620122', '620122', '皋兰县', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620123', '620123', '榆中县', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620171', '620171', '兰州新区', '6201', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6202', '6202', '嘉峪关市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620201001', '620201001', '雄关街道', '6202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620201002', '620201002', '钢城街道', '6202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620201100', '620201100', '新城镇', '6202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620201101', '620201101', '峪泉镇', '6202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620201102', '620201102', '文殊镇', '6202', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6203', '6203', '金昌市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620302', '620302', '金川区', '6203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620321', '620321', '永昌县', '6203', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6204', '6204', '白银市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620402', '620402', '白银区', '6204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620403', '620403', '平川区', '6204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620421', '620421', '靖远县', '6204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620422', '620422', '会宁县', '6204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620423', '620423', '景泰县', '6204', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6205', '6205', '天水市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620502', '620502', '秦州区', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620503', '620503', '麦积区', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620521', '620521', '清水县', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620522', '620522', '秦安县', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620523', '620523', '甘谷县', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620524', '620524', '武山县', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620525', '620525', '张家川回族自治县', '6205', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6206', '6206', '武威市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620602', '620602', '凉州区', '6206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620621', '620621', '民勤县', '6206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620622', '620622', '古浪县', '6206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620623', '620623', '天祝藏族自治县', '6206', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6207', '6207', '张掖市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620702', '620702', '甘州区', '6207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620721', '620721', '肃南裕固族自治县', '6207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620722', '620722', '民乐县', '6207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620723', '620723', '临泽县', '6207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620724', '620724', '高台县', '6207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620725', '620725', '山丹县', '6207', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6208', '6208', '平凉市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620802', '620802', '崆峒区', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620821', '620821', '泾川县', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620822', '620822', '灵台县', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620823', '620823', '崇信县', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620825', '620825', '庄浪县', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620826', '620826', '静宁县', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620881', '620881', '华亭市', '6208', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6209', '6209', '酒泉市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620902', '620902', '肃州区', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620921', '620921', '金塔县', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620922', '620922', '瓜州县', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620923', '620923', '肃北蒙古族自治县', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620924', '620924', '阿克塞哈萨克族自治县', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620981', '620981', '玉门市', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('620982', '620982', '敦煌市', '6209', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6210', '6210', '庆阳市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621002', '621002', '西峰区', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621021', '621021', '庆城县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621022', '621022', '环县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621023', '621023', '华池县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621024', '621024', '合水县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621025', '621025', '正宁县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621026', '621026', '宁县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621027', '621027', '镇原县', '6210', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6211', '6211', '定西市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621102', '621102', '安定区', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621121', '621121', '通渭县', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621122', '621122', '陇西县', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621123', '621123', '渭源县', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621124', '621124', '临洮县', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621125', '621125', '漳县', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621126', '621126', '岷县', '6211', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6212', '6212', '陇南市', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621202', '621202', '武都区', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621221', '621221', '成县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621222', '621222', '文县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621223', '621223', '宕昌县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621224', '621224', '康县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621225', '621225', '西和县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621226', '621226', '礼县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621227', '621227', '徽县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('621228', '621228', '两当县', '6212', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6229', '6229', '临夏回族自治州', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622901', '622901', '临夏市', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622921', '622921', '临夏县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622922', '622922', '康乐县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622923', '622923', '永靖县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622924', '622924', '广河县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622925', '622925', '和政县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622926', '622926', '东乡族自治县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('622927', '622927', '积石山保安族东乡族撒拉族自治县', '6229', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6230', '6230', '甘南藏族自治州', '62', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623001', '623001', '合作市', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623021', '623021', '临潭县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623022', '623022', '卓尼县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623023', '623023', '舟曲县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623024', '623024', '迭部县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623025', '623025', '玛曲县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623026', '623026', '碌曲县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('623027', '623027', '夏河县', '6230', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('63', '63', '青海省', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6301', '6301', '西宁市', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630102', '630102', '城东区', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630103', '630103', '城中区', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630104', '630104', '城西区', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630105', '630105', '城北区', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630106', '630106', '湟中区', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630121', '630121', '大通回族土族自治县', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630123', '630123', '湟源县', '6301', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6302', '6302', '海东市', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630202', '630202', '乐都区', '6302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630203', '630203', '平安区', '6302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630222', '630222', '民和回族土族自治县', '6302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630223', '630223', '互助土族自治县', '6302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630224', '630224', '化隆回族自治县', '6302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('630225', '630225', '循化撒拉族自治县', '6302', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6322', '6322', '海北藏族自治州', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632221', '632221', '门源回族自治县', '6322', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632222', '632222', '祁连县', '6322', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632223', '632223', '海晏县', '6322', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632224', '632224', '刚察县', '6322', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6323', '6323', '黄南藏族自治州', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632321', '632321', '同仁县', '6323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632322', '632322', '尖扎县', '6323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632323', '632323', '泽库县', '6323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632324', '632324', '河南蒙古族自治县', '6323', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6325', '6325', '海南藏族自治州', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632521', '632521', '共和县', '6325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632522', '632522', '同德县', '6325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632523', '632523', '贵德县', '6325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632524', '632524', '兴海县', '6325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632525', '632525', '贵南县', '6325', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6326', '6326', '果洛藏族自治州', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632621', '632621', '玛沁县', '6326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632622', '632622', '班玛县', '6326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632623', '632623', '甘德县', '6326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632624', '632624', '达日县', '6326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632625', '632625', '久治县', '6326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632626', '632626', '玛多县', '6326', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6327', '6327', '玉树藏族自治州', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632701', '632701', '玉树市', '6327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632722', '632722', '杂多县', '6327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632723', '632723', '称多县', '6327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632724', '632724', '治多县', '6327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632725', '632725', '囊谦县', '6327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632726', '632726', '曲麻莱县', '6327', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6328', '6328', '海西蒙古族藏族自治州', '63', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632801', '632801', '格尔木市', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632802', '632802', '德令哈市', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632803', '632803', '茫崖市', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632821', '632821', '乌兰县', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632822', '632822', '都兰县', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632823', '632823', '天峻县', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('632857', '632857', '大柴旦行政委员会', '6328', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('64', '64', '宁夏回族自治区', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6401', '6401', '银川市', '64', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640104', '640104', '兴庆区', '6401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640105', '640105', '西夏区', '6401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640106', '640106', '金凤区', '6401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640121', '640121', '永宁县', '6401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640122', '640122', '贺兰县', '6401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640181', '640181', '灵武市', '6401', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6402', '6402', '石嘴山市', '64', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640202', '640202', '大武口区', '6402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640205', '640205', '惠农区', '6402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640221', '640221', '平罗县', '6402', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6403', '6403', '吴忠市', '64', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640302', '640302', '利通区', '6403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640303', '640303', '红寺堡区', '6403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640323', '640323', '盐池县', '6403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640324', '640324', '同心县', '6403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640381', '640381', '青铜峡市', '6403', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6404', '6404', '固原市', '64', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640402', '640402', '原州区', '6404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640422', '640422', '西吉县', '6404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640423', '640423', '隆德县', '6404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640424', '640424', '泾源县', '6404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640425', '640425', '彭阳县', '6404', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6405', '6405', '中卫市', '64', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640502', '640502', '沙坡头区', '6405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640521', '640521', '中宁县', '6405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('640522', '640522', '海原县', '6405', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('65', '65', '新疆维吾尔自治区', NULL, 1); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6501', '6501', '乌鲁木齐市', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650102', '650102', '天山区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650103', '650103', '沙依巴克区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650104', '650104', '新市区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650105', '650105', '水磨沟区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650106', '650106', '头屯河区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650107', '650107', '达坂城区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650109', '650109', '米东区', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650121', '650121', '乌鲁木齐县', '6501', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6502', '6502', '克拉玛依市', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650202', '650202', '独山子区', '6502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650203', '650203', '克拉玛依区', '6502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650204', '650204', '白碱滩区', '6502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650205', '650205', '乌尔禾区', '6502', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6504', '6504', '吐鲁番市', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650402', '650402', '高昌区', '6504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650421', '650421', '鄯善县', '6504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650422', '650422', '托克逊县', '6504', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6505', '6505', '哈密市', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650502', '650502', '伊州区', '6505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650521', '650521', '巴里坤哈萨克自治县', '6505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('650522', '650522', '伊吾县', '6505', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6523', '6523', '昌吉回族自治州', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652301', '652301', '昌吉市', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652302', '652302', '阜康市', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652323', '652323', '呼图壁县', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652324', '652324', '玛纳斯县', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652325', '652325', '奇台县', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652327', '652327', '吉木萨尔县', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652328', '652328', '木垒哈萨克自治县', '6523', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6527', '6527', '博尔塔拉蒙古自治州', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652701', '652701', '博乐市', '6527', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652702', '652702', '阿拉山口市', '6527', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652722', '652722', '精河县', '6527', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652723', '652723', '温泉县', '6527', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6528', '6528', '巴音郭楞蒙古自治州', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652801', '652801', '库尔勒市', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652822', '652822', '轮台县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652823', '652823', '尉犁县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652824', '652824', '若羌县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652825', '652825', '且末县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652826', '652826', '焉耆回族自治县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652827', '652827', '和静县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652828', '652828', '和硕县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652829', '652829', '博湖县', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652871', '652871', '库尔勒经济技术开发区', '6528', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6529', '6529', '阿克苏地区', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652901', '652901', '阿克苏市', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652902', '652902', '库车市', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652922', '652922', '温宿县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652924', '652924', '沙雅县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652925', '652925', '新和县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652926', '652926', '拜城县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652927', '652927', '乌什县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652928', '652928', '阿瓦提县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('652929', '652929', '柯坪县', '6529', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6530', '6530', '克孜勒苏柯尔克孜自治州', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653001', '653001', '阿图什市', '6530', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653022', '653022', '阿克陶县', '6530', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653023', '653023', '阿合奇县', '6530', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653024', '653024', '乌恰县', '6530', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6531', '6531', '喀什地区', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653101', '653101', '喀什市', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653121', '653121', '疏附县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653122', '653122', '疏勒县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653123', '653123', '英吉沙县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653124', '653124', '泽普县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653125', '653125', '莎车县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653126', '653126', '叶城县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653127', '653127', '麦盖提县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653128', '653128', '岳普湖县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653129', '653129', '伽师县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653130', '653130', '巴楚县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653131', '653131', '塔什库尔干塔吉克自治县', '6531', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6532', '6532', '和田地区', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653201', '653201', '和田市', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653221', '653221', '和田县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653222', '653222', '墨玉县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653223', '653223', '皮山县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653224', '653224', '洛浦县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653225', '653225', '策勒县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653226', '653226', '于田县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('653227', '653227', '民丰县', '6532', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6540', '6540', '伊犁哈萨克自治州', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654002', '654002', '伊宁市', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654003', '654003', '奎屯市', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654004', '654004', '霍尔果斯市', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654021', '654021', '伊宁县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654022', '654022', '察布查尔锡伯自治县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654023', '654023', '霍城县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654024', '654024', '巩留县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654025', '654025', '新源县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654026', '654026', '昭苏县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654027', '654027', '特克斯县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654028', '654028', '尼勒克县', '6540', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6542', '6542', '塔城地区', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654201', '654201', '塔城市', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654202', '654202', '乌苏市', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654221', '654221', '额敏县', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654223', '654223', '沙湾县', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654224', '654224', '托里县', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654225', '654225', '裕民县', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654226', '654226', '和布克赛尔蒙古自治县', '6542', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6543', '6543', '阿勒泰地区', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654301', '654301', '阿勒泰市', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654321', '654321', '布尔津县', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654322', '654322', '富蕴县', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654323', '654323', '福海县', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654324', '654324', '哈巴河县', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654325', '654325', '青河县', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('654326', '654326', '吉木乃县', '6543', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('6590', '6590', '自治区直辖县级行政区划', '65', 2); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659001', '659001', '石河子市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659002', '659002', '阿拉尔市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659003', '659003', '图木舒克市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659004', '659004', '五家渠市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659005', '659005', '北屯市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659006', '659006', '铁门关市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659007', '659007', '双河市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659008', '659008', '可克达拉市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659009', '659009', '昆玉市', '6590', 3); +INSERT INTO `dic_city` (`id`, `code`, `name`, `parent_id`, `level`) VALUES ('659010', '659010', '胡杨河市', '6590', 3); +COMMIT; + +-- ---------------------------- +-- Table structure for gen_create_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_create_column_config`; +CREATE TABLE `gen_create_column_config` ( + `id` varchar(32) NOT NULL, + `required` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否必填', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='新增功能代码生成配置'; + +-- ---------------------------- +-- Records of gen_create_column_config +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_form +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_form`; +CREATE TABLE `gen_custom_form` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `is_dialog` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否对话框表单', + `dialog_tittle` varchar(100) DEFAULT NULL COMMENT '对话框标题', + `dialog_width` varchar(100) DEFAULT '1' COMMENT '对话框宽度', + `form_config` longtext NOT NULL COMMENT '表单配置', + `prefix_submit` longtext COMMENT '前置提交脚本', + `suffix_submit` longtext COMMENT '后置提交脚本', + `require_query` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否需要查询', + `query_bean` longtext COMMENT '查询数据Bean名称', + `handle_bean` longtext COMMENT '操作数据Bean名称', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + KEY `category_id` (`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义对话框'; + +-- ---------------------------- +-- Records of gen_custom_form +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_form_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_form_category`; +CREATE TABLE `gen_custom_form_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表分类'; + +-- ---------------------------- +-- Records of gen_custom_form_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_list +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list`; +CREATE TABLE `gen_custom_list` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `data_obj_id` varchar(32) NOT NULL DEFAULT '1' COMMENT '数据对象ID', + `list_type` tinyint(3) NOT NULL DEFAULT '0' COMMENT '列表类型', + `label_width` int(11) NOT NULL COMMENT '表单Label宽度', + `has_page` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否分页', + `tree_data` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否树形列表', + `id_column` varchar(32) DEFAULT NULL COMMENT 'ID字段', + `id_column_rela_id` varchar(32) DEFAULT NULL COMMENT 'ID字段关联ID', + `tree_pid_column` varchar(32) DEFAULT NULL COMMENT '父级ID字段', + `tree_pid_column_rela_id` varchar(32) DEFAULT NULL COMMENT '父级ID字段关联ID', + `tree_node_column` varchar(32) DEFAULT NULL COMMENT '树形节点字段', + `tree_node_column_rela_id` varchar(32) DEFAULT NULL COMMENT '树形节点字段关联ID', + `tree_children_key` varchar(100) DEFAULT NULL COMMENT '子节点Key值', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `query_prefix_sql` longtext COMMENT '查询前置SQL', + `query_suffix_sql` longtext COMMENT '查询后置SQL', + `suffix_sql` longtext COMMENT '后置SQL', + `allow_export` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否允许导出', + PRIMARY KEY (`id`) USING BTREE, + KEY `category_id` (`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表'; + +-- ---------------------------- +-- Records of gen_custom_list +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_list_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_category`; +CREATE TABLE `gen_custom_list_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表分类'; + +-- ---------------------------- +-- Records of gen_custom_list_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_list_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_detail`; +CREATE TABLE `gen_custom_list_detail` ( + `id` varchar(32) NOT NULL, + `custom_list_id` varchar(32) NOT NULL COMMENT '自定义列表ID', + `rela_id` varchar(32) DEFAULT NULL COMMENT '关联ID', + `data_entity_id` varchar(32) DEFAULT NULL COMMENT '数据实体ID', + `width_type` tinyint(3) NOT NULL COMMENT '宽度类型', + `width` int(11) NOT NULL COMMENT '宽度', + `sortable` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否页面排序', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `type` tinyint(3) NOT NULL COMMENT '类型', + `formatter` longtext COMMENT '格式化脚本', + PRIMARY KEY (`id`) USING BTREE, + KEY `custom_list_id` (`custom_list_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表明细'; + +-- ---------------------------- +-- Records of gen_custom_list_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_list_handle_column +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_handle_column`; +CREATE TABLE `gen_custom_list_handle_column` ( + `id` varchar(32) NOT NULL, + `custom_list_id` varchar(32) NOT NULL COMMENT '自定义列表ID', + `name` varchar(32) NOT NULL COMMENT '显示名称', + `view_type` varchar(20) NOT NULL COMMENT '显示类型', + `btn_type` tinyint(3) NOT NULL COMMENT '按钮类型', + `btn_config` longtext COMMENT '按钮配置', + `request_param` longtext COMMENT '请求参数', + `icon` varchar(100) DEFAULT NULL COMMENT '图标', + `width` int(11) NOT NULL COMMENT '宽度', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表工具栏'; + +-- ---------------------------- +-- Records of gen_custom_list_handle_column +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_list_query_params +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_query_params`; +CREATE TABLE `gen_custom_list_query_params` ( + `id` varchar(32) NOT NULL, + `custom_list_id` varchar(32) NOT NULL COMMENT '自定义列表ID', + `rela_id` varchar(32) NOT NULL COMMENT '关联ID', + `data_entity_id` varchar(32) NOT NULL COMMENT '数据实体ID', + `front_show` tinyint(1) NOT NULL DEFAULT '1' COMMENT '前端显示', + `query_type` tinyint(3) NOT NULL COMMENT '查询类型', + `form_width` int(11) NOT NULL DEFAULT '6' COMMENT '表单宽度', + `default_value` longtext COMMENT '默认值', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `type` tinyint(3) NOT NULL COMMENT '类型', + PRIMARY KEY (`id`) USING BTREE, + KEY `custom_list_id` (`custom_list_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表查询参数'; + +-- ---------------------------- +-- Records of gen_custom_list_query_params +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_list_toolbar +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_list_toolbar`; +CREATE TABLE `gen_custom_list_toolbar` ( + `id` varchar(32) NOT NULL, + `custom_list_id` varchar(32) NOT NULL COMMENT '自定义列表ID', + `name` varchar(32) NOT NULL COMMENT '显示名称', + `view_type` varchar(20) NOT NULL COMMENT '显示类型', + `btn_type` tinyint(3) NOT NULL COMMENT '按钮类型', + `btn_config` longtext COMMENT '按钮配置', + `request_param` longtext COMMENT '请求参数', + `icon` varchar(100) DEFAULT NULL COMMENT '图标', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义列表工具栏'; + +-- ---------------------------- +-- Records of gen_custom_list_toolbar +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_selector +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_selector`; +CREATE TABLE `gen_custom_selector` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `custom_list_id` varchar(32) NOT NULL DEFAULT '1' COMMENT '数据对象ID', + `dialog_tittle` varchar(100) DEFAULT NULL COMMENT '对话框标题', + `dialog_width` varchar(100) NOT NULL DEFAULT '1' COMMENT '对话框宽度', + `placeholder` varchar(100) DEFAULT NULL COMMENT '占位符', + `id_column` varchar(32) DEFAULT NULL COMMENT 'ID字段', + `id_column_rela_id` varchar(32) DEFAULT NULL COMMENT 'ID字段关联ID', + `name_column` varchar(32) DEFAULT NULL COMMENT '名称ID字段', + `name_column_rela_id` varchar(32) DEFAULT NULL COMMENT '名称ID字段关联ID', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + KEY `category_id` (`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义对话框'; + +-- ---------------------------- +-- Records of gen_custom_selector +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_custom_selector_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_custom_selector_category`; +CREATE TABLE `gen_custom_selector_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义对话框分类'; + +-- ---------------------------- +-- Records of gen_custom_selector_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_entity +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_entity`; +CREATE TABLE `gen_data_entity` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `gen_status` tinyint(3) NOT NULL DEFAULT '1' COMMENT '状态', + `table_schema` varchar(64) NOT NULL COMMENT '数据表所属的数据库名', + `table_name` varchar(64) NOT NULL COMMENT '数据库表名', + `engine` varchar(64) DEFAULT NULL COMMENT '数据库引擎', + `table_collation` varchar(32) DEFAULT NULL COMMENT '字符校验编码集', + `table_comment` varchar(2048) NOT NULL COMMENT '备注', + `convert_type` tinyint(3) NOT NULL COMMENT '转换方式', + PRIMARY KEY (`id`) USING BTREE, + KEY `category_id` (`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据实体'; + +-- ---------------------------- +-- Records of gen_data_entity +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_entity_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_entity_category`; +CREATE TABLE `gen_data_entity_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据实体分类'; + +-- ---------------------------- +-- Records of gen_data_entity_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_entity_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_entity_detail`; +CREATE TABLE `gen_data_entity_detail` ( + `id` varchar(32) NOT NULL, + `entity_id` varchar(32) NOT NULL COMMENT '实体ID', + `name` varchar(64) NOT NULL COMMENT '字段显示名称', + `column_name` varchar(64) NOT NULL COMMENT '字段名称', + `is_key` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否主键', + `data_type` tinyint(3) NOT NULL COMMENT '数据类型', + `column_order` int(11) NOT NULL COMMENT '排序编号', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `view_type` tinyint(3) NOT NULL COMMENT '显示类型', + `data_dic_id` varchar(32) DEFAULT NULL COMMENT '数据字典ID', + `custom_selector_id` varchar(32) DEFAULT NULL COMMENT '自定义选择器ID', + `fix_enum` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否内置枚举', + `enum_back` varchar(200) DEFAULT NULL COMMENT '后端枚举名', + `enum_front` varchar(200) DEFAULT NULL COMMENT '前端枚举名', + `regular_expression` varchar(200) DEFAULT NULL COMMENT '正则表达式', + `is_order` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否排序字段', + `order_type` varchar(20) DEFAULT NULL COMMENT '排序类型', + `len` bigint(20) DEFAULT NULL COMMENT '长度', + `decimals` int(11) DEFAULT NULL COMMENT '小数位数', + `db_column_name` varchar(64) NOT NULL COMMENT '字段名', + `db_data_type` varchar(64) NOT NULL DEFAULT '' COMMENT '字段数据类型', + `is_nullable` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否允许为空', + `column_default` longtext COMMENT '默认值', + `ordinal_position` bigint(21) unsigned NOT NULL DEFAULT '0' COMMENT '字段排序', + `column_comment` varchar(1024) NOT NULL DEFAULT '' COMMENT '字段备注', + `db_len` bigint(20) DEFAULT NULL COMMENT '长度', + `db_decimals` int(11) DEFAULT NULL COMMENT '小数位数', + PRIMARY KEY (`id`) USING BTREE, + KEY `entity_id` (`entity_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据实体明细'; + +-- ---------------------------- +-- Records of gen_data_entity_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_obj +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj`; +CREATE TABLE `gen_data_obj` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `main_table_id` varchar(32) NOT NULL DEFAULT '1' COMMENT '主表ID', + `main_table_alias` varchar(200) NOT NULL COMMENT '主表别名', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + KEY `category_id` (`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据对象'; + +-- ---------------------------- +-- Records of gen_data_obj +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_obj_category +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj_category`; +CREATE TABLE `gen_data_obj_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据实体分类'; + +-- ---------------------------- +-- Records of gen_data_obj_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_obj_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj_detail`; +CREATE TABLE `gen_data_obj_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `data_obj_id` varchar(32) NOT NULL COMMENT '数据对象ID', + `main_table_detail_ids` longtext NOT NULL COMMENT '主表字段', + `rela_type` tinyint(3) NOT NULL COMMENT '关联类型', + `rela_mode` tinyint(3) NOT NULL COMMENT '关联方式', + `sub_table_id` varchar(32) NOT NULL COMMENT '子表ID', + `sub_table_alias` varchar(200) NOT NULL COMMENT '子表别名', + `sub_table_detail_ids` longtext NOT NULL COMMENT '子表字段', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`), + KEY `data_obj_id` (`data_obj_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据对象明细'; + +-- ---------------------------- +-- Records of gen_data_obj_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_data_obj_query_detail +-- ---------------------------- +DROP TABLE IF EXISTS `gen_data_obj_query_detail`; +CREATE TABLE `gen_data_obj_query_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `data_obj_id` varchar(32) NOT NULL COMMENT '数据对象ID', + `custom_name` varchar(200) NOT NULL COMMENT '显示名称', + `custom_sql` longtext NOT NULL COMMENT '自定义SQL', + `custom_alias` varchar(200) NOT NULL COMMENT '自定义别名', + `data_type` tinyint(3) NOT NULL COMMENT '数据类型', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`), + KEY `data_obj_id` (`data_obj_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据对象自定义查询明细'; + +-- ---------------------------- +-- Records of gen_data_obj_query_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_detail_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_detail_column_config`; +CREATE TABLE `gen_detail_column_config` ( + `id` varchar(32) NOT NULL, + `span` int(11) NOT NULL COMMENT '列宽', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='详情功能代码生成配置'; + +-- ---------------------------- +-- Records of gen_detail_column_config +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_generate_info +-- ---------------------------- +DROP TABLE IF EXISTS `gen_generate_info`; +CREATE TABLE `gen_generate_info` ( + `id` varchar(32) NOT NULL, + `template_type` tinyint(3) NOT NULL COMMENT '生成模板类型', + `package_name` varchar(200) NOT NULL COMMENT '包名', + `module_name` varchar(200) NOT NULL COMMENT '模块名', + `biz_name` varchar(200) NOT NULL COMMENT '业务名', + `class_name` varchar(200) NOT NULL COMMENT '类名', + `parent_menu_id` varchar(32) DEFAULT NULL COMMENT '父级菜单ID', + `key_type` tinyint(3) NOT NULL COMMENT '主键类型', + `author` varchar(100) DEFAULT NULL COMMENT '作者', + `class_description` varchar(200) NOT NULL COMMENT '类描述', + `menu_code` varchar(20) NOT NULL COMMENT '本级菜单编号', + `menu_name` varchar(200) NOT NULL COMMENT '本级菜单名称', + `detail_span` int(11) NOT NULL COMMENT '详情页Span总数量', + `is_cache` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否应用缓存', + `has_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否内置删除功能', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='代码生成基本信息'; + +-- ---------------------------- +-- Records of gen_generate_info +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_query_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_query_column_config`; +CREATE TABLE `gen_query_column_config` ( + `id` varchar(32) NOT NULL, + `width_type` tinyint(3) NOT NULL COMMENT '宽度类型', + `width` int(11) NOT NULL COMMENT '宽度', + `sortable` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否页面排序', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='查询功能代码生成配置'; + +-- ---------------------------- +-- Records of gen_query_column_config +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_query_params_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_query_params_column_config`; +CREATE TABLE `gen_query_params_column_config` ( + `id` varchar(32) NOT NULL, + `query_type` tinyint(3) NOT NULL COMMENT '查询类型', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='查询参数功能代码生成配置'; + +-- ---------------------------- +-- Records of gen_query_params_column_config +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_simple_table +-- ---------------------------- +DROP TABLE IF EXISTS `gen_simple_table`; +CREATE TABLE `gen_simple_table` ( + `id` varchar(32) NOT NULL, + `table_schema` varchar(64) NOT NULL COMMENT '数据表所属的数据库名', + `table_name` varchar(64) NOT NULL COMMENT '数据库表名', + `engine` varchar(64) DEFAULT NULL COMMENT '数据库引擎', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `table_collation` varchar(32) DEFAULT NULL COMMENT '字符校验编码集', + `table_comment` varchar(2048) NOT NULL COMMENT '备注', + `convert_type` tinyint(3) NOT NULL COMMENT '转换方式', + PRIMARY KEY (`id`), + KEY `table_schema` (`table_schema`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库单表'; + +-- ---------------------------- +-- Records of gen_simple_table +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_simple_table_column +-- ---------------------------- +DROP TABLE IF EXISTS `gen_simple_table_column`; +CREATE TABLE `gen_simple_table_column` ( + `id` varchar(32) NOT NULL, + `table_id` varchar(32) NOT NULL, + `column_name` varchar(64) NOT NULL COMMENT '字段名', + `data_type` varchar(64) NOT NULL DEFAULT '' COMMENT '字段数据类型', + `is_nullable` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否允许为空', + `is_key` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否主键', + `column_default` longtext COMMENT '默认值', + `ordinal_position` bigint(21) unsigned NOT NULL DEFAULT '0' COMMENT '字段排序', + `column_comment` varchar(1024) NOT NULL DEFAULT '' COMMENT '字段备注', + `len` bigint(20) DEFAULT NULL COMMENT '长度', + `decimals` int(11) DEFAULT NULL COMMENT '小数位数', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库单表列信息'; + +-- ---------------------------- +-- Records of gen_simple_table_column +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for gen_update_column_config +-- ---------------------------- +DROP TABLE IF EXISTS `gen_update_column_config`; +CREATE TABLE `gen_update_column_config` ( + `id` varchar(32) NOT NULL, + `required` tinyint(1) NOT NULL DEFAULT '0', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='修改功能代码生成配置'; + +-- ---------------------------- +-- Records of gen_update_column_config +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for op_logs +-- ---------------------------- +DROP TABLE IF EXISTS `op_logs`; +CREATE TABLE `op_logs` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(200) NOT NULL COMMENT '日志名称', + `log_type` tinyint(3) NOT NULL COMMENT '类别', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `extra` longtext COMMENT '补充信息', + `ip` varchar(100) NOT NULL COMMENT 'IP地址', + PRIMARY KEY (`id`), + KEY `create_by` (`create_by`), + KEY `create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志'; + +-- ---------------------------- +-- Records of op_logs +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for recursion_mapping +-- ---------------------------- +DROP TABLE IF EXISTS `recursion_mapping`; +CREATE TABLE `recursion_mapping` ( + `id` varchar(32) NOT NULL, + `node_id` varchar(32) NOT NULL COMMENT '节点ID', + `node_type` tinyint(3) NOT NULL COMMENT '节点类型', + `path` longtext COMMENT '从顶点到当前结点的路径,用,分割', + `level` int(11) NOT NULL COMMENT '节点层级', + PRIMARY KEY (`id`), + UNIQUE KEY `node_id` (`node_id`,`node_type`) USING BTREE, + KEY `node_type` (`node_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='树形数据节点关系表'; + +-- ---------------------------- +-- Records of recursion_mapping +-- ---------------------------- +BEGIN; +INSERT INTO `recursion_mapping` (`id`, `node_id`, `node_type`, `path`, `level`) VALUES ('1', '2', 1, NULL, 1); +INSERT INTO `recursion_mapping` (`id`, `node_id`, `node_type`, `path`, `level`) VALUES ('2', '4', 1, '2', 2); +INSERT INTO `recursion_mapping` (`id`, `node_id`, `node_type`, `path`, `level`) VALUES ('3', '3', 1, '1', 2); +INSERT INTO `recursion_mapping` (`id`, `node_id`, `node_type`, `path`, `level`) VALUES ('4', '1', 1, NULL, 1); +COMMIT; + +-- ---------------------------- +-- Table structure for settle_check_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_check_sheet`; +CREATE TABLE `settle_check_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `total_pay_amount` decimal(24,2) NOT NULL COMMENT '应付金额', + `total_payed_amount` decimal(24,2) NOT NULL COMMENT '已付金额', + `total_discount_amount` decimal(24,2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `supplier_id` (`supplier_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商对账单'; + +-- ---------------------------- +-- Records of settle_check_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_check_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_check_sheet_detail`; +CREATE TABLE `settle_check_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '对账单ID', + `biz_id` varchar(32) NOT NULL COMMENT '单据ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `calc_type` tinyint(3) NOT NULL COMMENT '计算类型', + `pay_amount` decimal(24,2) NOT NULL COMMENT '应付金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`biz_id`), + KEY `biz_id` (`biz_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商对账单明细'; + +-- ---------------------------- +-- Records of settle_check_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_fee_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_fee_sheet`; +CREATE TABLE `settle_fee_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `sheet_type` tinyint(3) NOT NULL COMMENT '单据类型', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `supplier_id` (`supplier_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商费用单'; + +-- ---------------------------- +-- Records of settle_fee_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_fee_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_fee_sheet_detail`; +CREATE TABLE `settle_fee_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '费用单ID', + `item_id` varchar(32) NOT NULL COMMENT '项目ID', + `amount` decimal(24,2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`item_id`), + KEY `item_id` (`item_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商费用单明细'; + +-- ---------------------------- +-- Records of settle_fee_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_in_item +-- ---------------------------- +DROP TABLE IF EXISTS `settle_in_item`; +CREATE TABLE `settle_in_item` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收入项目'; + +-- ---------------------------- +-- Records of settle_in_item +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_out_item +-- ---------------------------- +DROP TABLE IF EXISTS `settle_out_item`; +CREATE TABLE `settle_out_item` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支出项目'; + +-- ---------------------------- +-- Records of settle_out_item +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_pre_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_pre_sheet`; +CREATE TABLE `settle_pre_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `supplier_id` (`supplier_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商预付款单'; + +-- ---------------------------- +-- Records of settle_pre_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_pre_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_pre_sheet_detail`; +CREATE TABLE `settle_pre_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '预付款单ID', + `item_id` varchar(32) NOT NULL COMMENT '项目ID', + `amount` decimal(24,2) NOT NULL COMMENT '金额', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`item_id`), + KEY `item_id` (`item_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商预付款单明细'; + +-- ---------------------------- +-- Records of settle_pre_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `settle_sheet`; +CREATE TABLE `settle_sheet` ( + `id` varchar(32) NOT NULL, + `code` varchar(32) NOT NULL COMMENT '单号', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '总金额', + `total_discount_amount` decimal(24,2) NOT NULL COMMENT '已优惠金额', + `start_date` date NOT NULL COMMENT '起始日期', + `end_date` date NOT NULL COMMENT '截止日期', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `supplier_id` (`supplier_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商结算单'; + +-- ---------------------------- +-- Records of settle_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for settle_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `settle_sheet_detail`; +CREATE TABLE `settle_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '结算单ID', + `biz_id` varchar(32) NOT NULL COMMENT '单据ID', + `pay_amount` decimal(24,2) NOT NULL COMMENT '实付金额', + `discount_amount` decimal(24,2) NOT NULL COMMENT '优惠金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`biz_id`), + KEY `biz_id` (`biz_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商结算单明细'; + +-- ---------------------------- +-- Records of settle_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sw_file_box +-- ---------------------------- +DROP TABLE IF EXISTS `sw_file_box`; +CREATE TABLE `sw_file_box` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(200) NOT NULL COMMENT '名称', + `url` longtext NOT NULL COMMENT 'Url', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件收纳箱'; + +-- ---------------------------- +-- Records of sw_file_box +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sw_online_excel +-- ---------------------------- +DROP TABLE IF EXISTS `sw_online_excel`; +CREATE TABLE `sw_online_excel` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `name` varchar(200) NOT NULL COMMENT '名称', + `content` longtext NOT NULL COMMENT '内容', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1-在用 0停用', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='在线Excel'; + +-- ---------------------------- +-- Records of sw_online_excel +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_data_dic +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_dic`; +CREATE TABLE `sys_data_dic` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + UNIQUE KEY `name` (`name`), + KEY `category_id` (`category_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典'; + +-- ---------------------------- +-- Records of sys_data_dic +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_data_dic_category +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_dic_category`; +CREATE TABLE `sys_data_dic_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典分类'; + +-- ---------------------------- +-- Records of sys_data_dic_category +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_data_dic_item +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_dic_item`; +CREATE TABLE `sys_data_dic_item` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `dic_id` varchar(32) NOT NULL COMMENT '字典ID', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `dic_id` (`dic_id`,`code`), + UNIQUE KEY `dic_id_2` (`dic_id`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典'; + +-- ---------------------------- +-- Records of sys_data_dic_item +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dept`; +CREATE TABLE `sys_dept` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(100) NOT NULL COMMENT '名称', + `short_name` varchar(20) NOT NULL COMMENT '简称', + `parent_id` varchar(32) DEFAULT NULL COMMENT '父级ID', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + UNIQUE KEY `name` (`name`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='部门'; + +-- ---------------------------- +-- Records of sys_dept +-- ---------------------------- +BEGIN; +INSERT INTO `sys_dept` (`id`, `code`, `name`, `short_name`, `parent_id`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1', '001', '销售中心', '销售中心', NULL, 1, '', '系统管理员', '1', '2022-01-13 00:37:06', '系统管理员', '1', '2022-01-13 00:37:06'); +INSERT INTO `sys_dept` (`id`, `code`, `name`, `short_name`, `parent_id`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2', '002', '研发中心', '研发中心', NULL, 1, '', '系统管理员', '1', '2022-01-13 00:37:17', '系统管理员', '1', '2022-01-13 00:37:17'); +INSERT INTO `sys_dept` (`id`, `code`, `name`, `short_name`, `parent_id`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3', '001001', '销售部', '销售部', '1', 1, '', '系统管理员', '1', '2022-01-13 00:38:03', '系统管理员', '1', '2022-01-13 00:38:03'); +INSERT INTO `sys_dept` (`id`, `code`, `name`, `short_name`, `parent_id`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4', '002001', '研发部', '研发部', '2', 1, '', '系统管理员', '1', '2022-01-13 00:38:15', '系统管理员', '1', '2022-01-13 00:38:15'); +COMMIT; + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu`; +CREATE TABLE `sys_menu` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(200) DEFAULT NULL COMMENT '名称(前端使用)', + `title` varchar(20) NOT NULL COMMENT '标题', + `icon` varchar(200) DEFAULT NULL COMMENT '图标', + `component_type` tinyint(3) DEFAULT NULL COMMENT '组件类型(前端使用)', + `component` varchar(200) DEFAULT NULL COMMENT '组件(前端使用)', + `request_param` longtext COMMENT '自定义请求参数', + `parent_id` varchar(32) DEFAULT NULL COMMENT '父级ID', + `path` varchar(200) DEFAULT NULL COMMENT '路由路径(前端使用)', + `no_cache` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否缓存(前端使用)', + `display` tinyint(3) NOT NULL COMMENT '类型 0-目录 1-菜单 2-功能', + `hidden` tinyint(1) DEFAULT '0' COMMENT '是否隐藏(前端使用)', + `permission` varchar(200) DEFAULT NULL COMMENT '权限', + `is_special` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否特殊菜单', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + KEY `code` (`code`,`name`,`title`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单'; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +BEGIN; +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('0001', '0001', 'Xingyun', '星云工作台', 'a-menu', NULL, '', NULL, NULL, '/xingyun', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000', '1000', 'System', '系统管理', 'a-menu', NULL, '', NULL, '0001', '/system', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000001', '1000001', 'Menu', '菜单管理', NULL, 0, '/system/menu/index', NULL, '1000', '/menu', 0, 1, 0, 'system:menu:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000001001', '1000001001', '', '新增菜单', NULL, 0, '', NULL, '1000001', '', 0, 2, 0, 'system:menu:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000001002', '1000001002', '', '修改菜单', NULL, 0, '', NULL, '1000001', '', 0, 2, 0, 'system:menu:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000001003', '1000001003', '', '删除菜单', NULL, 0, '', NULL, '1000001', '', 0, 2, 0, 'system:menu:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000002', '1000002', 'Dept', '部门管理', NULL, 0, '/system/dept/index', NULL, '1000', '/dept', 0, 1, 0, 'system:dept:query', 1, 1, '', '系统管理员', '1', '2021-07-05 01:09:27', '系统管理员', '1', '2021-07-05 01:09:27'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000002001', '1000002001', '', '新增部门', NULL, 0, '', NULL, '1000002', '', 0, 2, 0, 'system:dept:add', 1, 1, '', '系统管理员', '1', '2021-06-27 01:33:31', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000002002', '1000002002', '', '修改部门', NULL, 0, '', NULL, '1000002', '', 0, 2, 0, 'system:dept:modify', 1, 1, '', '系统管理员', '1', '2021-06-27 01:33:47', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000003', '1000003', 'Position', '岗位管理', NULL, 0, '/system/position/index', NULL, '1000', '/position', 0, 1, 0, 'system:position:query', 1, 1, '', '系统管理员', '1', '2021-07-01 23:26:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000003001', '1000003001', '', '新增岗位', NULL, 0, '', NULL, '1000003', '', 0, 2, 0, 'system:position:add', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000003002', '1000003002', '', '修改岗位', NULL, 0, '', NULL, '1000003', '', 0, 2, 0, 'system:position:modify', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000004', '1000004', 'Role', '角色管理', NULL, 0, '/system/role/index', NULL, '1000', '/role', 0, 1, 0, 'system:role:query', 1, 1, '', '系统管理员', '1', '2021-07-04 00:35:49', '系统管理员', '1', '2021-07-04 00:35:49'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000004001', '1000004001', '', '新增角色', NULL, 0, '', NULL, '1000004', '', 0, 2, 0, 'system:role:add', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000004002', '1000004002', '', '修改角色', NULL, 0, '', NULL, '1000004', '', 0, 2, 0, 'system:role:modify', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000004003', '1000004003', '', '角色授权', NULL, 0, '', NULL, '1000004', '', 0, 2, 0, 'system:role:permission', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000005', '1000005', 'User', '用户管理', NULL, 0, '/system/user/index', NULL, '1000', '/user', 0, 1, 0, 'system:user:query', 1, 1, '', '系统管理员', '1', '2021-07-05 01:08:40', '系统管理员', '1', '2021-07-05 01:08:40'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000005001', '1000005001', '', '新增用户', NULL, 0, '', NULL, '1000005', '', 0, 2, 0, 'system:user:add', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:17', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000005002', '1000005002', '', '修改用户', NULL, 0, '', NULL, '1000005', '', 0, 2, 0, 'system:user:modify', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000005003', '1000005003', '', '用户授权', NULL, 0, '', NULL, '1000005', '', 0, 2, 0, 'system:user:permission', 1, 1, '', '系统管理员', '1', '2021-06-30 00:32:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000006', '1000006', 'Oplog', '操作日志', NULL, 0, '/system/oplog/index', NULL, '1000', '/oplog', 0, 1, 0, 'system:oplog:query', 1, 1, '', '系统管理员', '1', '2021-07-05 01:08:40', '系统管理员', '1', '2021-07-05 01:08:40'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000007', '1000007', 'SysParameter', '系统参数', NULL, 0, '/system/parameter/index', NULL, '1000', '/parameter', 0, 1, 0, 'system:parameter:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000007001', '1000007001', '', '新增系统参数', NULL, 0, '', NULL, '1000007', '', 0, 2, 0, 'system:parameter:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000007002', '1000007002', '', '修改系统参数', NULL, 0, '', NULL, '1000007', '', 0, 2, 0, 'system:parameter:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000007003', '1000007003', '', '删除系统参数', NULL, 0, '', NULL, '1000007', '', 0, 2, 0, 'system:parameter:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000008', '1000008', 'PublishSysNotice', '发布系统通知', NULL, 0, '/system/notice/publish', NULL, '1000', '/system/notice/publish', 0, 1, 0, 'system:notice:publish', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000008001', '1000008001', '', '新增系统通知', NULL, 0, '', NULL, '1000008', '', 0, 2, 0, 'system:notice:add', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000008002', '1000008002', '', '修改系统通知', NULL, 0, '', NULL, '1000008', '', 0, 2, 0, 'system:notice:modify', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000009', '1000009', 'SysNotice', '系统通知', NULL, 0, '/system/notice/index', NULL, '1000', '/system/notice', 0, 1, 0, 'system:notice:query', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010', '1000010', 'SysDataDic', '数据字典', NULL, 0, '/system/dic/index', NULL, '1000', '/dic', 0, 1, 0, 'system:dic:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010001', '1000010001', '', '新增数据字典', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010002', '1000010002', '', '修改数据字典', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010003', '1000010003', '', '删除数据字典', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010004', '1000010004', '', '新增数据字典分类', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic-category:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010005', '1000010005', '', '修改数据字典分类', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic-category:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010006', '1000010006', '', '删除数据字典分类', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic-category:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010007', '1000010007', '', '新增数据字典值', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010008', '1000010008', '', '修改数据字典值', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000010009', '1000010009', '', '删除数据字典值', NULL, 0, '', NULL, '1000010', '', 0, 2, 0, 'system:dic-item:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000011', '1000011', 'SysTenant', '租户管理', NULL, 0, '/system/tenant/index', NULL, '1000', '/system/tenant', 0, 1, 0, 'system:tenant:query', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000011001', '1000011001', '', '新增租户', NULL, 0, '', NULL, '1000011', '', 0, 2, 0, 'system:tenant:add', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000011002', '1000011002', '', '修改租户', NULL, 0, '', NULL, '1000011', '', 0, 2, 0, 'system:tenant:modify', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000012', '1000012', 'OpenDomain', '开放域', 'a-menu', 0, '/system/open-domain/index', NULL, '1000', '/open-domain', 0, 1, 0, 'system:open-domain:config', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000', '2000', 'BaseData', '基础信息管理', 'a-menu', NULL, '', NULL, '0001', '/base-data', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000002', '2000002', 'StoreCenterInfo', '仓库信息', NULL, 0, '/base-data/store-center/index', NULL, '2000', '/store-center', 0, 1, 0, 'base-data:store-center:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000002001', '2000002001', '', '新增仓库', NULL, 0, '', NULL, '2000002', '', 0, 2, 0, 'base-data:store-center:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000002002', '2000002002', '', '修改仓库', NULL, 0, '', NULL, '2000002', '', 0, 2, 0, 'base-data:store-center:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000002003', '2000002003', '', '导入仓库', NULL, 0, '', NULL, '2000002', '', 0, 2, 0, 'base-data:store-center:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000004', '2000004', 'Customer', '客户信息', NULL, 0, '/base-data/customer/index', NULL, '2000', '/customer', 0, 1, 0, 'base-data:customer:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000004001', '2000004001', '', '新增客户', NULL, 0, '', NULL, '2000004', '', 0, 2, 0, 'base-data:customer:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000004002', '2000004002', '', '修改客户', NULL, 0, '', NULL, '2000004', '', 0, 2, 0, 'base-data:customer:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000004003', '2000004003', '', '导入客户', NULL, 0, '', NULL, '2000004', '', 0, 2, 0, 'base-data:customer:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000005', '2000005', 'Supplier', '供应商信息', NULL, 0, '/base-data/supplier/index', NULL, '2000', '/supplier', 0, 1, 0, 'base-data:supplier:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000005001', '2000005001', '', '新增供应商', NULL, 0, '', NULL, '2000005', '', 0, 2, 0, 'base-data:supplier:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000005002', '2000005002', '', '修改供应商', NULL, 0, '', NULL, '2000005', '', 0, 2, 0, 'base-data:supplier:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000005003', '2000005003', '', '导入供应商', NULL, 0, '', NULL, '2000005', '', 0, 2, 0, 'base-data:supplier:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000006', '2000006', 'Member', '会员信息', NULL, 0, '/base-data/member/index', NULL, '2000', '/member', 0, 1, 0, 'base-data:member:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000006001', '2000006001', '', '新增会员', NULL, 0, '', NULL, '2000006', '', 0, 2, 0, 'base-data:member:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000006002', '2000006002', '', '修改会员', NULL, 0, '', NULL, '2000006', '', 0, 2, 0, 'base-data:member:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000006003', '2000006003', '', '导入会员', NULL, 0, '', NULL, '2000006', '', 0, 2, 0, 'base-data:member:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000007', '2000007', 'Shop', '门店信息', NULL, 0, '/base-data/shop/index', NULL, '2000', '/shop', 0, 1, 0, 'base-data:shop:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000007001', '2000007001', '', '新增门店', NULL, 0, '', NULL, '2000007', '', 0, 2, 0, 'base-data:shop:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000007002', '2000007002', '', '修改门店', NULL, 0, '', NULL, '2000007', '', 0, 2, 0, 'base-data:shop:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000007003', '2000007003', '', '导入门店', NULL, 0, '', NULL, '2000007', '', 0, 2, 0, 'base-data:shop:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001', '2001', 'Product', '商品中心', 'a-menu', NULL, '', NULL, '0001', '/product', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001001', '2001001', 'ProductCategory', '商品类目', NULL, 0, '/base-data/product/category/index', NULL, '2001', '/category', 0, 1, 0, 'base-data:product:category:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001001001', '2001001001', '', '新增类目', NULL, 0, '', NULL, '2001001', '', 0, 2, 0, 'base-data:product:category:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001001002', '2001001002', '', '修改类目', NULL, 0, '', NULL, '2001001', '', 0, 2, 0, 'base-data:product:category:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001001003', '2001001003', '', '导入类目', NULL, 0, '', NULL, '2001001', '', 0, 2, 0, 'base-data:product:category:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001002', '2001002', 'ProductBrand', '商品品牌', NULL, 0, '/base-data/product/brand/index', NULL, '2001', '/brand', 0, 1, 0, 'base-data:product:brand:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001002001', '2001002001', '', '新增品牌', NULL, 0, '', NULL, '2001002', '', 0, 2, 0, 'base-data:product:brand:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001002002', '2001002002', '', '修改品牌', NULL, 0, '', NULL, '2001002', '', 0, 2, 0, 'base-data:product:brand:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001002003', '2001002003', '', '导入品牌', NULL, 0, '', NULL, '2001002', '', 0, 2, 0, 'base-data:product:brand:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001003', '2001003', 'ProductSalePropGroup', '商品销售属性组', NULL, 0, '/base-data/product/saleprop/index', NULL, '2001', '/spec', 0, 1, 0, 'base-data:product:saleprop-group:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001003001', '2001003001', '', '新增销售属性组', NULL, 0, '', NULL, '2001003', '', 0, 2, 0, 'base-data:product:saleprop-group:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001003002', '2001003002', '', '修改销售属性组', NULL, 0, '', NULL, '2001003', '', 0, 2, 0, 'base-data:product:saleprop-group:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001003003', '2001003003', '', '查询销售属性', NULL, 0, '', NULL, '2001003', '', 0, 2, 0, 'base-data:product:saleprop-item:query', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001003004', '2001003004', '', '新增销售属性', NULL, 0, '', NULL, '2001003', '', 0, 2, 0, 'base-data:product:saleprop-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001003005', '2001003005', '', '修改销售属性', NULL, 0, '', NULL, '2001003', '', 0, 2, 0, 'base-data:product:saleprop-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001004', '2001004', 'ProductProperty', '商品属性', NULL, 0, '/base-data/product/property/index', NULL, '2001', '/property', 0, 1, 0, 'base-data:product:property:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001004001', '2001004001', '', '新增属性', NULL, 0, '', NULL, '2001004', '', 0, 2, 0, 'base-data:product:property:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001004002', '2001004002', '', '修改属性', NULL, 0, '', NULL, '2001004', '', 0, 2, 0, 'base-data:product:property:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001004003', '2001004003', '', '查询属性值', NULL, 0, '', NULL, '2001004', '', 0, 2, 0, 'base-data:product:property-item:query', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001004004', '2001004004', '', '新增属性值', NULL, 0, '', NULL, '2001004', '', 0, 2, 0, 'base-data:product:property-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001004005', '2001004005', '', '修改属性值', NULL, 0, '', NULL, '2001004', '', 0, 2, 0, 'base-data:product:property-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001005', '2001005', 'ProductInfo', '商品管理', NULL, 0, '/base-data/product/info/index', NULL, '2001', '/info', 0, 1, 0, 'base-data:product:info:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001005001', '2001005001', '', '新增商品', NULL, 0, '', NULL, '2001005', '', 0, 2, 0, 'base-data:product:info:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001005002', '2001005002', '', '修改商品', NULL, 0, '', NULL, '2001005', '', 0, 2, 0, 'base-data:product:info:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001005003', '2001005003', '', '导入商品', NULL, 0, '', NULL, '2001005', '', 0, 2, 0, 'base-data:product:info:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001006', '2001006', 'ProductPoly', '商品SPU', NULL, 0, '/base-data/product/poly/index', NULL, '2001', '/poly', 0, 1, 0, 'base-data:product:poly:query', 1, 1, '', '系统管理员', '1', '2021-07-06 17:01:00', '系统管理员', '1', '2021-07-06 17:01:00'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001006001', '2001006001', '', '新增商品SPU', NULL, 0, '', NULL, '2001006', '', 0, 2, 0, 'base-data:product:poly:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001006002', '2001006002', '', '修改商品SPU', NULL, 0, '', NULL, '2001006', '', 0, 2, 0, 'base-data:product:poly:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2001006003', '2001006003', '', '导入商品SPU', NULL, 0, '', NULL, '2001006', '', 0, 2, 0, 'base-data:product:poly:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002', '2002', 'Purchase', '采购管理', 'a-menu', NULL, '', NULL, '0001', '/purchase', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002001', '2002001', 'PurchaseConfig', '采购参数设置', NULL, 0, '/sc/purchase/config/index', NULL, '2002', '/config', 1, 1, 0, 'purchase:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002', '2002002', 'PurchaseOrder', '采购订单管理', NULL, 0, '/sc/purchase/order/index', NULL, '2002', '/order', 0, 1, 0, 'purchase:order:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002001', '2002002001', '', '新增采购订单', NULL, 0, '', NULL, '2002002', '', 0, 2, 0, 'purchase:order:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002002', '2002002002', '', '修改采购订单', NULL, 0, '', NULL, '2002002', '', 0, 2, 0, 'purchase:order:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002003', '2002002003', '', '删除采购订单', NULL, 0, '', NULL, '2002002', '', 0, 2, 0, 'purchase:order:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002004', '2002002004', '', '审核采购订单', NULL, 0, '', NULL, '2002002', '', 0, 2, 0, 'purchase:order:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002005', '2002002005', '', '导出采购订单', NULL, 0, '', NULL, '2002002', '', 0, 2, 0, 'purchase:order:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002002006', '2002002006', '', '导入采购订单', NULL, 0, '', NULL, '2002002', '', 0, 2, 0, 'purchase:order:import', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003', '2002003', 'ReceiveSheet', '采购收货管理', NULL, 0, '/sc/purchase/receive/index', NULL, '2002', '/receive', 0, 1, 0, 'purchase:receive:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003001', '2002003001', '', '新增采购收货单', NULL, 0, '', NULL, '2002003', '', 0, 2, 0, 'purchase:receive:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003002', '2002003002', '', '修改采购收货单', NULL, 0, '', NULL, '2002003', '', 0, 2, 0, 'purchase:receive:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003003', '2002003003', '', '删除采购收货单', NULL, 0, '', NULL, '2002003', '', 0, 2, 0, 'purchase:receive:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003004', '2002003004', '', '审核采购收货单', NULL, 0, '', NULL, '2002003', '', 0, 2, 0, 'purchase:receive:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003005', '2002003005', '', '导出采购收货单', NULL, 0, '', NULL, '2002003', '', 0, 2, 0, 'purchase:receive:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002003006', '2002003006', '', '导入采购收货单', NULL, 0, '', NULL, '2002003', '', 0, 2, 0, 'purchase:receive:import', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002004', '2002004', 'PurchaseReturn', '采购退货管理', NULL, 0, '/sc/purchase/return/index', NULL, '2002', '/return', 0, 1, 0, 'purchase:return:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002004001', '2002004001', '', '新增采购退货单', NULL, 0, '', NULL, '2002004', '', 0, 2, 0, 'purchase:return:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002004002', '2002004002', '', '修改采购退货单', NULL, 0, '', NULL, '2002004', '', 0, 2, 0, 'purchase:return:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002004003', '2002004003', '', '删除采购退货单', NULL, 0, '', NULL, '2002004', '', 0, 2, 0, 'purchase:return:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002004004', '2002004004', '', '审核采购退货单', NULL, 0, '', NULL, '2002004', '', 0, 2, 0, 'purchase:return:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2002004005', '2002004005', '', '导出采购退货单', NULL, 0, '', NULL, '2002004', '', 0, 2, 0, 'purchase:return:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003', '2003', 'Sale', '销售管理', 'a-menu', NULL, '', NULL, '0001', '/sale', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003001', '2003001', 'SaleConfig', '销售参数设置', NULL, 0, '/sc/sale/config/index', NULL, '2003', '/config', 1, 1, 0, 'sale:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003002', '2003002', 'SaleOrder', '销售订单管理', NULL, 0, '/sc/sale/order/index', NULL, '2003', '/order', 0, 1, 0, 'sale:order:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003002001', '2003002001', '', '新增销售订单', NULL, 0, '', NULL, '2003002', '', 0, 2, 0, 'sale:order:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003002002', '2003002002', '', '修改销售订单', NULL, 0, '', NULL, '2003002', '', 0, 2, 0, 'sale:order:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003002003', '2003002003', '', '删除销售订单', NULL, 0, '', NULL, '2003002', '', 0, 2, 0, 'sale:order:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003002004', '2003002004', '', '审核销售订单', NULL, 0, '', NULL, '2003002', '', 0, 2, 0, 'sale:order:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003002005', '2003002005', '', '导出销售订单', NULL, 0, '', NULL, '2003002', '', 0, 2, 0, 'sale:order:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003003', '2003003', 'SaleOutSheet', '销售出库管理', NULL, 0, '/sc/sale/out/index', NULL, '2003', '/out', 0, 1, 0, 'sale:out:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003003001', '2003003001', '', '新增销售出库单', NULL, 0, '', NULL, '2003003', '', 0, 2, 0, 'sale:out:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003003002', '2003003002', '', '修改销售出库单', NULL, 0, '', NULL, '2003003', '', 0, 2, 0, 'sale:out:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003003003', '2003003003', '', '删除销售出库单', NULL, 0, '', NULL, '2003003', '', 0, 2, 0, 'sale:out:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003003004', '2003003004', '', '审核销售出库单', NULL, 0, '', NULL, '2003003', '', 0, 2, 0, 'sale:out:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003003005', '2003003005', '', '导出销售出库单', NULL, 0, '', NULL, '2003003', '', 0, 2, 0, 'sale:out:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003004', '2003004', 'SaleReturn', '销售退货管理', NULL, 0, '/sc/sale/return/index', NULL, '2003', '/return', 0, 1, 0, 'sale:return:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003004001', '2003004001', '', '新增销售退货单', NULL, 0, '', NULL, '2003004', '', 0, 2, 0, 'sale:return:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003004002', '2003004002', '', '修改销售退货单', NULL, 0, '', NULL, '2003004', '', 0, 2, 0, 'sale:return:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003004003', '2003004003', '', '删除销售退货单', NULL, 0, '', NULL, '2003004', '', 0, 2, 0, 'sale:return:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003004004', '2003004004', '', '审核销售退货单', NULL, 0, '', NULL, '2003004', '', 0, 2, 0, 'sale:return:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2003004005', '2003004005', '', '导出销售退货单', NULL, 0, '', NULL, '2003004', '', 0, 2, 0, 'sale:return:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004', '2004', 'Retail', '零售管理', 'a-menu', NULL, '', NULL, '0001', '/retail', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004001', '2004001', 'RetailConfig', '零售参数设置', NULL, 0, '/sc/retail/config/index', NULL, '2004', '/config', 1, 1, 0, 'retail:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004002', '2004002', 'RetailOutSheet', '零售出库管理', NULL, 0, '/sc/retail/out/index', NULL, '2004', '/out', 0, 1, 0, 'retail:out:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004002001', '2004002001', '', '新增零售出库单', NULL, 0, '', NULL, '2004002', '', 0, 2, 0, 'retail:out:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004002002', '2004002002', '', '修改零售出库单', NULL, 0, '', NULL, '2004002', '', 0, 2, 0, 'retail:out:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004002003', '2004002003', '', '删除零售出库单', NULL, 0, '', NULL, '2004002', '', 0, 2, 0, 'retail:out:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004002004', '2004002004', '', '审核零售出库单', NULL, 0, '', NULL, '2004002', '', 0, 2, 0, 'retail:out:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004002005', '2004002005', '', '导出零售出库单', NULL, 0, '', NULL, '2004002', '', 0, 2, 0, 'retail:out:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004003', '2004003', 'RetailReturn', '零售退货管理', NULL, 0, '/sc/retail/return/index', NULL, '2004', '/return', 0, 1, 0, 'retail:return:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004003001', '2004003001', '', '新增零售退货单', NULL, 0, '', NULL, '2004003', '', 0, 2, 0, 'retail:return:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004003002', '2004003002', '', '修改零售退货单', NULL, 0, '', NULL, '2004003', '', 0, 2, 0, 'retail:return:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004003003', '2004003003', '', '删除零售退货单', NULL, 0, '', NULL, '2004003', '', 0, 2, 0, 'retail:return:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004003004', '2004003004', '', '审核零售退货单', NULL, 0, '', NULL, '2004003', '', 0, 2, 0, 'retail:return:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2004003005', '2004003005', '', '导出零售退货单', NULL, 0, '', NULL, '2004003', '', 0, 2, 0, 'retail:return:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000', '3000', 'StockManage', '库存管理', 'a-menu', NULL, '', NULL, '0001', '/stock', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000001', '3000001', 'ProductStock', '商品库存', NULL, 0, '/sc/stock/product/index', NULL, '3000', '/product', 0, 1, 0, 'stock:product:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000001001', '3000001001', '', '导出商品库存', NULL, 0, '', NULL, '3000001', '', 0, 2, 0, 'stock:product:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000003', '3000003', 'ProductStockLog', '商品库存变动记录', NULL, 0, '/sc/stock/product-log/index', NULL, '3000', '/product/log', 0, 1, 0, 'stock:product-log:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000003001', '3000003001', '', '导出商品库存变动记录', NULL, 0, '', NULL, '3000003', '', 0, 2, 0, 'stock:product-log:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004', '3000004', 'TakeStock', '库存盘点', 'a-menu', NULL, '', NULL, '0001', '/take', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004001', '3000004001', 'TakeStockConfig', '盘点参数设置', NULL, 0, '/sc/stock/take/config/index', NULL, '3000004', '/config', 1, 1, 0, 'stock:take:config:modify', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004002', '3000004002', 'PreTakeStockSheet', '预先盘点单管理', NULL, 0, '/sc/stock/take/pre/index', NULL, '3000004', '/pre', 0, 1, 0, 'stock:take:pre:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004002001', '3000004002001', '', '新增预先盘点单', NULL, 0, '', NULL, '3000004002', '', 0, 2, 0, 'stock:take:pre:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004002002', '3000004002002', '', '修改预先盘点单', NULL, 0, '', NULL, '3000004002', '', 0, 2, 0, 'stock:take:pre:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004002003', '3000004002003', '', '删除预先盘点单', NULL, 0, '', NULL, '3000004002', '', 0, 2, 0, 'stock:take:pre:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004002004', '3000004002004', '', '导出预先盘点单', NULL, 0, '', NULL, '3000004002', '', 0, 2, 0, 'stock:take:pre:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003', '3000004003', 'TakeStockPlan', '盘点任务管理', NULL, 0, '/sc/stock/take/plan/index', NULL, '3000004', '/plan', 0, 1, 0, 'stock:take:plan:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003001', '3000004003001', '', '新增盘点任务', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003002', '3000004003002', '', '修改盘点任务', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003003', '3000004003003', '', '删除盘点任务', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003004', '3000004003004', '', '导出盘点任务', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003005', '3000004003005', '', '差异生成', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:create-diff', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003006', '3000004003006', '', '差异处理', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:handle-diff', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004003007', '3000004003007', '', '作废盘点任务', NULL, 0, '', NULL, '3000004003', '', 0, 2, 0, 'stock:take:plan:cancel', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004', '3000004004', 'TakeStockSheet', '盘点单管理', NULL, 0, '/sc/stock/take/sheet/index', NULL, '3000004', '/sheet', 0, 1, 0, 'stock:take:sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004001', '3000004004001', '', '新增盘点单', NULL, 0, '', NULL, '3000004004', '', 0, 2, 0, 'stock:take:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004002', '3000004004002', '', '修改盘点单', NULL, 0, '', NULL, '3000004004', '', 0, 2, 0, 'stock:take:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004003', '3000004004003', '', '删除盘点单', NULL, 0, '', NULL, '3000004004', '', 0, 2, 0, 'stock:take:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004004', '3000004004004', '', '导出盘点单', NULL, 0, '', NULL, '3000004004', '', 0, 2, 0, 'stock:take:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004005', '3000004004005', '', '审核盘点单', NULL, 0, '', NULL, '3000004004', '', 0, 2, 0, 'stock:take:sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000004004006', '3000004004006', '', '取消审核盘点单', NULL, 0, '', NULL, '3000004004', '', 0, 2, 0, 'stock:take:sheet:cancel-approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005', '3000005', 'StockAdjust', '库存调整', 'a-menu', NULL, '', NULL, '0001', '/take-adjust', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005001', '3000005001', 'StockCostAdjustSheet', '库存成本调整', NULL, 0, '/sc/stock/adjust/cost/index', NULL, '3000005', '/cost', 0, 1, 0, 'stock:adjust:cost:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005001001', '3000005001001', '', '新增库存成本调整单', NULL, 0, '', NULL, '3000005001', '', 0, 2, 0, 'stock:adjust:cost:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005001002', '3000005001002', '', '修改库存成本调整单', NULL, 0, '', NULL, '3000005001', '', 0, 2, 0, 'stock:adjust:cost:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005001003', '3000005001003', '', '删除库存成本调整单', NULL, 0, '', NULL, '3000005001', '', 0, 2, 0, 'stock:adjust:cost:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005001004', '3000005001004', '', '导出库存成本调整单', NULL, 0, '', NULL, '3000005001', '', 0, 2, 0, 'stock:adjust:cost:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005001005', '3000005001005', '', '审核库存成本调整单', NULL, 0, '', NULL, '3000005001', '', 0, 2, 0, 'stock:adjust:cost:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000', '4000', 'SettleManage', '结算管理', 'a-menu', NULL, '', NULL, '0001', '/settle', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000001', '4000001', 'SettleInItem', '收入项目', NULL, 0, '/settle/in-item/index', NULL, '4000', '/in-item', 0, 1, 0, 'settle:in-item:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000001001', '4000001001', '', '新增收入项目', NULL, 0, '', NULL, '4000001', '', 0, 2, 0, 'settle:in-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000001002', '4000001002', '', '修改收入项目', NULL, 0, '', NULL, '4000001', '', 0, 2, 0, 'settle:in-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000001003', '4000001003', '', '导出收入项目', NULL, 0, '', NULL, '4000001', '', 0, 2, 0, 'settle:in-item:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000002', '4000002', 'SettleOutItem', '支出项目', NULL, 0, '/settle/out-item/index', NULL, '4000', '/out-item', 0, 1, 0, 'settle:out-item:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000002001', '4000002001', '', '新增支出项目', NULL, 0, '', NULL, '4000002', '', 0, 2, 0, 'settle:out-item:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000002002', '4000002002', '', '修改支出项目', NULL, 0, '', NULL, '4000002', '', 0, 2, 0, 'settle:out-item:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000002003', '4000002003', '', '导出支出项目', NULL, 0, '', NULL, '4000002', '', 0, 2, 0, 'settle:out-item:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000003', '4000003', 'SettleFeeSheet', '供应商费用', NULL, 0, '/settle/fee-sheet/index', NULL, '4000007', '/fee-sheet', 0, 1, 0, 'settle:fee-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000003001', '4000003001', '', '新增供应商费用单', NULL, 0, '', NULL, '4000003', '', 0, 2, 0, 'settle:fee-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000003002', '4000003002', '', '修改供应商费用单', NULL, 0, '', NULL, '4000003', '', 0, 2, 0, 'settle:fee-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000003003', '4000003003', '', '删除供应商费用单', NULL, 0, '', NULL, '4000003', '', 0, 2, 0, 'settle:fee-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000003004', '4000003004', '', '审核供应商费用单', NULL, 0, '', NULL, '4000003', '', 0, 2, 0, 'settle:fee-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000003005', '4000003005', '', '导出供应商费用单', NULL, 0, '', NULL, '4000003', '', 0, 2, 0, 'settle:fee-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000004', '4000004', 'SettlePreSheet', '供应商预付款', NULL, 0, '/settle/pre-sheet/index', NULL, '4000007', '/pre-sheet', 0, 1, 0, 'settle:pre-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000004001', '4000004001', '', '新增供应商预付款单', NULL, 0, '', NULL, '4000004', '', 0, 2, 0, 'settle:pre-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000004002', '4000004002', '', '修改供应商预付款单', NULL, 0, '', NULL, '4000004', '', 0, 2, 0, 'settle:pre-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000004003', '4000004003', '', '删除供应商预付款单', NULL, 0, '', NULL, '4000004', '', 0, 2, 0, 'settle:pre-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000004004', '4000004004', '', '审核供应商预付款单', NULL, 0, '', NULL, '4000004', '', 0, 2, 0, 'settle:pre-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000004005', '4000004005', '', '导出供应商预付款单', NULL, 0, '', NULL, '4000004', '', 0, 2, 0, 'settle:pre-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000005', '4000005', 'SettleCheckSheet', '供应商对账', NULL, 0, '/settle/check-sheet/index', NULL, '4000007', '/check-sheet', 0, 1, 0, 'settle:check-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000005001', '4000005001', '', '新增供应商对账单', NULL, 0, '', NULL, '4000005', '', 0, 2, 0, 'settle:check-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000005002', '4000005002', '', '修改供应商对账单', NULL, 0, '', NULL, '4000005', '', 0, 2, 0, 'settle:check-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000005003', '4000005003', '', '删除供应商对账单', NULL, 0, '', NULL, '4000005', '', 0, 2, 0, 'settle:check-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000005004', '4000005004', '', '审核供应商对账单', NULL, 0, '', NULL, '4000005', '', 0, 2, 0, 'settle:check-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000005005', '4000005005', '', '导出供应商对账单', NULL, 0, '', NULL, '4000005', '', 0, 2, 0, 'settle:check-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000006', '4000006', 'SettleSheet', '供应商结算', NULL, 0, '/settle/sheet/index', NULL, '4000007', '/sheet', 0, 1, 0, 'settle:sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000006001', '4000006001', '', '新增供应商结算单', NULL, 0, '', NULL, '4000006', '', 0, 2, 0, 'settle:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000006002', '4000006002', '', '修改供应商结算单', NULL, 0, '', NULL, '4000006', '', 0, 2, 0, 'settle:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000006003', '4000006003', '', '删除供应商结算单', NULL, 0, '', NULL, '4000006', '', 0, 2, 0, 'settle:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000006004', '4000006004', '', '审核供应商结算单', NULL, 0, '', NULL, '4000006', '', 0, 2, 0, 'settle:sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000006005', '4000006005', '', '导出供应商结算单', NULL, 0, '', NULL, '4000006', '', 0, 2, 0, 'settle:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000007', '4000007', 'SupplierSettleManage', '供应商结算', 'a-menu', NULL, '', NULL, '4000', '/supplier', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000008', '4000008', 'CustomerSettleManage', '客户结算', 'a-menu', NULL, '', NULL, '4000', '/customer', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-05 01:21:35', '系统管理员', '1', '2021-07-05 01:21:39'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000009', '4000009', 'CustomerSettleFeeSheet', '客户费用', NULL, 0, '/customer-settle/fee-sheet/index', NULL, '4000008', '/fee-sheet', 0, 1, 0, 'customer-settle:fee-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000009001', '4000009001', '', '新增客户费用单', NULL, 0, '', NULL, '4000009', '', 0, 2, 0, 'customer-settle:fee-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000009002', '4000009002', '', '修改客户费用单', NULL, 0, '', NULL, '4000009', '', 0, 2, 0, 'customer-settle:fee-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000009003', '4000009003', '', '删除客户费用单', NULL, 0, '', NULL, '4000009', '', 0, 2, 0, 'customer-settle:fee-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000009004', '4000009004', '', '审核客户费用单', NULL, 0, '', NULL, '4000009', '', 0, 2, 0, 'customer-settle:fee-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000009005', '4000009005', '', '导出客户费用单', NULL, 0, '', NULL, '4000009', '', 0, 2, 0, 'customer-settle:fee-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000010', '4000010', 'CustomerSettlePreSheet', '客户预收款', NULL, 0, '/customer-settle/pre-sheet/index', NULL, '4000008', '/pre-sheet', 0, 1, 0, 'customer-settle:pre-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000010001', '4000010001', '', '新增客户预收款单', NULL, 0, '', NULL, '4000010', '', 0, 2, 0, 'customer-settle:pre-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000010002', '4000010002', '', '修改客户预收款单', NULL, 0, '', NULL, '4000010', '', 0, 2, 0, 'customer-settle:pre-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000010003', '4000010003', '', '删除客户预收款单', NULL, 0, '', NULL, '4000010', '', 0, 2, 0, 'customer-settle:pre-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000010004', '4000010004', '', '审核客户预收款单', NULL, 0, '', NULL, '4000010', '', 0, 2, 0, 'customer-settle:pre-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000010005', '4000010005', '', '导出客户预收款单', NULL, 0, '', NULL, '4000010', '', 0, 2, 0, 'customer-settle:pre-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000011', '4000011', 'CustomerSettleCheckSheet', '客户对账', NULL, 0, '/customer-settle/check-sheet/index', NULL, '4000008', '/check-sheet', 0, 1, 0, 'customer-settle:check-sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000011001', '4000011001', '', '新增客户对账单', NULL, 0, '', NULL, '4000011', '', 0, 2, 0, 'customer-settle:check-sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000011002', '4000011002', '', '修改客户对账单', NULL, 0, '', NULL, '4000011', '', 0, 2, 0, 'customer-settle:check-sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000011003', '4000011003', '', '删除客户对账单', NULL, 0, '', NULL, '4000011', '', 0, 2, 0, 'customer-settle:check-sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000011004', '4000011004', '', '审核客户对账单', NULL, 0, '', NULL, '4000011', '', 0, 2, 0, 'customer-settle:check-sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000011005', '4000011005', '', '导出客户对账单', NULL, 0, '', NULL, '4000011', '', 0, 2, 0, 'customer-settle:check-sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000012', '4000012', 'CustomerSettleSheet', '客户结算', NULL, 0, '/customer-settle/sheet/index', NULL, '4000008', '/sheet', 0, 1, 0, 'customer-settle:sheet:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000012001', '4000012001', '', '新增客户结算单', NULL, 0, '', NULL, '4000012', '', 0, 2, 0, 'customer-settle:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000012002', '4000012002', '', '修改客户结算单', NULL, 0, '', NULL, '4000012', '', 0, 2, 0, 'customer-settle:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000012003', '4000012003', '', '删除客户结算单', NULL, 0, '', NULL, '4000012', '', 0, 2, 0, 'customer-settle:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000012004', '4000012004', '', '审核客户结算单', NULL, 0, '', NULL, '4000012', '', 0, 2, 0, 'customer-settle:sheet:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('4000012005', '4000012005', '', '导出客户结算单', NULL, 0, '', NULL, '4000012', '', 0, 2, 0, 'customer-settle:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 10:53:45', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000', '9000', 'Development', '开发管理', 'a-menu', NULL, '', NULL, '0001', '/development', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000001', '9000001', 'Qrtz', '定时器管理', NULL, 0, '/development/qrtz/index', NULL, '9000', '/qrtz', 0, 1, 0, 'development:qrtz:manage', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000002', '9000002', 'DataEntity', '数据实体', NULL, 0, '/development/data/entity/index', NULL, '9000', '/data/entity', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000003', '9000003', 'DataObj', '数据对象', NULL, 0, '/development/data/obj/index', NULL, '9000', '/data/obj', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000004', '9000004', 'CustomList', '自定义列表', NULL, 0, '/development/custom/list/index', NULL, '9000', '/custom/list', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000005', '9000005', 'CustomSelector', '自定义选择器', NULL, 0, '/development/custom/selector/index', NULL, '9000', '/custom/selector', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000006', '9000006', 'FmDesigner', '表单生成器', NULL, 0, '/development/fm-designer/index', NULL, '9000', '/fm-designer', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000007', '9000007', 'CustomForm', '自定义表单', NULL, 0, '/development/custom/form/index', NULL, '9000', '/custom/form', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9001', '9001', 'SmartWork', '便捷办公', 'a-menu', NULL, '', NULL, '0001', '/smart-work', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9001001', '9001001', 'FileBox', '文件收纳箱', NULL, 0, '/smart-work/file-box/index', NULL, '9001', '/file-box', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9001002', '9001002', 'OnlineExcel', '在线Excel', NULL, 0, '/smart-work/online-excel/index', NULL, '9001', '/online-excel', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +COMMIT; + +-- ---------------------------- +-- Table structure for sys_menu_collect +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu_collect`; +CREATE TABLE `sys_menu_collect` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `menu_id` varchar(32) NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`id`), + UNIQUE KEY `user_id, menu_id` (`user_id`,`menu_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单收藏'; + +-- ---------------------------- +-- Table structure for sys_notice +-- ---------------------------- +DROP TABLE IF EXISTS `sys_notice`; +CREATE TABLE `sys_notice` ( + `id` varchar(32) CHARACTER SET utf8mb4 NOT NULL COMMENT 'ID', + `title` varchar(200) CHARACTER SET utf8mb4 NOT NULL COMMENT '标题', + `content` longtext COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '内容', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `published` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否发布', + `create_by` varchar(32) CHARACTER SET utf8mb4 NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `readed_num` int(11) NOT NULL DEFAULT '0' COMMENT '已读人数', + `un_read_num` int(11) NOT NULL DEFAULT '0' COMMENT '未读人数', + `publish_time` datetime DEFAULT NULL COMMENT '发布时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统通知'; + +-- ---------------------------- +-- Records of sys_notice +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_notice_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_notice_log`; +CREATE TABLE `sys_notice_log` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `notice_id` varchar(32) NOT NULL COMMENT '标题', + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `readed` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已读', + `read_time` datetime DEFAULT NULL COMMENT '已读时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `notice_id` (`notice_id`,`user_id`), + KEY `user_id` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统通知记录'; + +-- ---------------------------- +-- Records of sys_notice_log +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_parameter +-- ---------------------------- +DROP TABLE IF EXISTS `sys_parameter`; +CREATE TABLE `sys_parameter` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `pm_key` varchar(100) NOT NULL COMMENT '键', + `pm_value` varchar(200) DEFAULT NULL COMMENT '值', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `pm_key` (`pm_key`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COMMENT='系统参数'; + +-- ---------------------------- +-- Records of sys_parameter +-- ---------------------------- +BEGIN; +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (1, 'tx-map.key', 'OLJBZ-ZFJK6-QWUSK-MB7XT-6UTN2-AWBSY', '腾讯地图Key', '系统管理员', '1', '2022-05-22 04:18:59', '系统管理员', '1', '2022-05-22 04:18:59'); +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (2, 'tx-map.secret', 'secret', '腾讯地图Secret', '系统管理员', '1', '2022-05-22 04:18:59', '系统管理员', '1', '2022-05-22 04:18:59'); +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (3, 'excel-import.max-size', '2000', 'Excel导入最大条数', '系统管理员', '1', '2022-06-10 21:39:32', '系统管理员', '1', '2022-06-10 21:39:32'); +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (7, 'sms.ali', '{\n \"accessKeyId\": \"123456789\",\n \"accessKeySecret\": \"123456789abcdefg\",\n \"endpoint\": \"dysmsapi.aliyuncs.com\"\n}', '阿里云短信配置', '系统管理员', '1', '2023-03-14 21:07:09', '系统管理员', '1', '2023-03-14 21:07:09'); +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (8, 'mail', '{\n \"pass\":\"123456\",\n \"sslEnable\":true,\n \"timeOut\":30000,\n \"port\":25,\n \"host\":\"smtp.xingyun.com\",\n \"connectTimeOut\":1000,\n \"from\":\"test@xingyun.com\",\n \"user\":\"test\"\n}', '邮件配置', '系统管理员', '1', '2023-03-14 21:13:44', '系统管理员', '1', '2023-03-14 21:13:44'); +COMMIT; + +-- ---------------------------- +-- Table structure for sys_position +-- ---------------------------- +DROP TABLE IF EXISTS `sys_position`; +CREATE TABLE `sys_position` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '岗位编号', + `name` varchar(20) NOT NULL COMMENT '岗位名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + UNIQUE KEY `name` (`name`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='岗位'; + +-- ---------------------------- +-- Records of sys_position +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role`; +CREATE TABLE `sys_role` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `permission` varchar(200) DEFAULT NULL COMMENT '权限', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + UNIQUE KEY `name` (`name`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色'; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +BEGIN; +INSERT INTO `sys_role` (`id`, `code`, `name`, `permission`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1', '001', '系统管理员', 'admin', 1, '系统管理员', '系统管理员', '1', '2021-05-08 18:04:41', '系统管理员', '1', '2021-05-08 18:04:45'); +COMMIT; + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_menu`; +CREATE TABLE `sys_role_menu` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `role_id` varchar(32) NOT NULL COMMENT '角色ID', + `menu_id` varchar(32) NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`id`), + UNIQUE KEY `role_id, menu_id` (`role_id`,`menu_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色与菜单关系表'; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '姓名', + `username` varchar(30) NOT NULL COMMENT '用户名', + `password` varchar(100) NOT NULL COMMENT '密码', + `email` varchar(100) DEFAULT NULL COMMENT '邮箱', + `telephone` varchar(11) DEFAULT NULL COMMENT '联系电话', + `gender` tinyint(3) NOT NULL DEFAULT '0' COMMENT '性别 0-未知 1-男 2-女', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1-在用 0停用', + `lock_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '锁定状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + UNIQUE KEY `username` (`username`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户'; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +BEGIN; +INSERT INTO `sys_user` (`id`, `code`, `name`, `username`, `password`, `email`, `telephone`, `gender`, `available`, `lock_status`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1', '001', '系统管理员', 'admin', '$2a$10$IJtHluhnhAYkgvM4PdKuZek5PWbtuxtjB9pB.twZdxg/qrlR4s4q6', 'xingyun@lframework.com', '17600000001', 0, 1, 0, '', '系统管理员', '1', '2021-04-22 22:00:27', '系统管理员', '1', '2023-03-09 13:30:44'); +COMMIT; + +-- ---------------------------- +-- Table structure for sys_user_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_dept`; +CREATE TABLE `sys_user_dept` ( + `id` varchar(32) NOT NULL, + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `dept_id` varchar(32) NOT NULL COMMENT '部门ID', + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`,`dept_id`) USING BTREE, + KEY `dept_id` (`dept_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户与部门关系表'; + +-- ---------------------------- +-- Records of sys_user_dept +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_user_position +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_position`; +CREATE TABLE `sys_user_position` ( + `id` varchar(32) NOT NULL, + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `position_id` varchar(32) NOT NULL COMMENT '岗位ID', + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`,`position_id`) USING BTREE, + KEY `position_id` (`position_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户与岗位关系表'; + +-- ---------------------------- +-- Records of sys_user_position +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_role`; +CREATE TABLE `sys_user_role` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `role_id` varchar(32) NOT NULL COMMENT '角色ID', + PRIMARY KEY (`id`), + UNIQUE KEY `user_id, role_id` (`user_id`,`role_id`) USING BTREE, + KEY `role_id` (`role_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户与角色关系表'; + +-- ---------------------------- +-- Records of sys_user_role +-- ---------------------------- +BEGIN; +INSERT INTO `sys_user_role` (`id`, `user_id`, `role_id`) VALUES ('1', '1', '1'); +COMMIT; + +-- ---------------------------- +-- Table structure for sys_user_telephone +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_telephone`; +CREATE TABLE `sys_user_telephone` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `telephone` varchar(11) NOT NULL COMMENT '手机号', + `user_id` varchar(32) DEFAULT NULL COMMENT '用户ID', + PRIMARY KEY (`id`), + UNIQUE KEY `telephone` (`telephone`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户绑定手机号表'; + +-- ---------------------------- +-- Records of sys_user_telephone +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_order_chart +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_order_chart`; +CREATE TABLE `tbl_order_chart` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `total_amount` decimal(24,2) NOT NULL COMMENT '单据总金额', + `create_time` datetime NOT NULL COMMENT '创建时间', + `create_date` varchar(19) NOT NULL COMMENT '创建日期', + `create_hour` varchar(13) NOT NULL COMMENT '创建时间(小时)', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`), + KEY `create_time` (`create_time`), + KEY `create_date` (`create_date`), + KEY `create_hour` (`create_hour`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单图表数据'; + +-- ---------------------------- +-- Records of tbl_order_chart +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_order_time_line +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_order_time_line`; +CREATE TABLE `tbl_order_time_line` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `order_id` varchar(32) NOT NULL COMMENT '单据ID', + `content` longtext COMMENT '描述内容', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`), + KEY `order_id` (`order_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='单据时间轴'; + +-- ---------------------------- +-- Records of tbl_order_time_line +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_pre_take_stock_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_pre_take_stock_sheet`; +CREATE TABLE `tbl_pre_take_stock_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `take_status` tinyint(3) NOT NULL COMMENT '盘点状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `sc_id` (`sc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存预先盘点单'; + +-- ---------------------------- +-- Records of tbl_pre_take_stock_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_pre_take_stock_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_pre_take_stock_sheet_detail`; +CREATE TABLE `tbl_pre_take_stock_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '预先盘点单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `first_num` int(11) DEFAULT NULL COMMENT '初盘数量', + `second_num` int(11) DEFAULT NULL COMMENT '复盘数量', + `rand_num` int(11) DEFAULT NULL COMMENT '抽盘数量', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存预先盘点单明细'; + +-- ---------------------------- +-- Records of tbl_pre_take_stock_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_product_stock +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_product_stock`; +CREATE TABLE `tbl_product_stock` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL DEFAULT '0' COMMENT '库存数量', + `tax_price` decimal(24,6) NOT NULL COMMENT '含税价格', + `tax_amount` decimal(24,2) NOT NULL COMMENT '含税金额', + `un_tax_price` decimal(24,6) NOT NULL COMMENT '无税价格', + `un_tax_amount` decimal(24,6) NOT NULL COMMENT '无税金额', + PRIMARY KEY (`id`), + UNIQUE KEY `product_id` (`product_id`,`sc_id`) USING BTREE, + KEY `sc_id` (`sc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品库存'; + +-- ---------------------------- +-- Records of tbl_product_stock +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_product_stock_log +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_product_stock_log`; +CREATE TABLE `tbl_product_stock_log` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `ori_tax_price` decimal(24,6) NOT NULL COMMENT '原含税成本价', + `cur_tax_price` decimal(24,6) NOT NULL COMMENT '现含税成本价', + `ori_un_tax_price` decimal(24,6) NOT NULL COMMENT '原无税成本价', + `cur_un_tax_price` decimal(24,6) NOT NULL COMMENT '现无税成本价', + `ori_stock_num` int(11) NOT NULL, + `cur_stock_num` int(11) NOT NULL, + `stock_num` int(11) NOT NULL DEFAULT '0' COMMENT '库存数量', + `tax_amount` decimal(24,2) NOT NULL COMMENT '含税金额', + `un_tax_amount` decimal(24,6) NOT NULL COMMENT '无税金额', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `biz_id` varchar(32) DEFAULT NULL COMMENT '业务单据ID', + `biz_code` varchar(32) DEFAULT NULL COMMENT '业务单据号', + `biz_detail_id` varchar(32) DEFAULT NULL COMMENT '业务单据明细ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`), + KEY `sc_id` (`sc_id`), + KEY `create_time` (`create_time`), + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品库存变动记录'; + +-- ---------------------------- +-- Records of tbl_product_stock_log +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_purchase_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_config`; +CREATE TABLE `tbl_purchase_config` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `receive_require_purchase` tinyint(1) NOT NULL DEFAULT '0' COMMENT '采购收货单是否关联采购订单', + `receive_multiple_relate_purchase` tinyint(1) NOT NULL DEFAULT '0' COMMENT '采购收货单是否多次关联采购订单', + `purchase_return_require_receive` tinyint(1) NOT NULL DEFAULT '0' COMMENT '采购退货单是否关联采购收货单', + `purchase_return_multiple_relate_receive` tinyint(1) NOT NULL DEFAULT '0' COMMENT '采购退货单是否多次关联采购收货单', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购参数设置'; + +-- ---------------------------- +-- Records of tbl_purchase_config +-- ---------------------------- +BEGIN; +INSERT INTO `tbl_purchase_config` (`id`, `receive_require_purchase`, `receive_multiple_relate_purchase`, `purchase_return_require_receive`, `purchase_return_multiple_relate_receive`) VALUES ('1', 1, 1, 1, 1); +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_purchase_order +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_order`; +CREATE TABLE `tbl_purchase_order` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `purchaser_id` varchar(32) DEFAULT NULL COMMENT '采购员ID', + `expect_arrive_date` date DEFAULT NULL COMMENT '预计到货日期', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '采购数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '采购金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `sc_id` (`sc_id`), + KEY `supplier_id` (`supplier_id`), + KEY `create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购订单'; + +-- ---------------------------- +-- Records of tbl_purchase_order +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_purchase_order_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_order_detail`; +CREATE TABLE `tbl_purchase_order_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `order_id` varchar(32) NOT NULL COMMENT '订单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '采购数量', + `tax_price` decimal(16,2) NOT NULL COMMENT '采购价', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `receive_num` int(11) NOT NULL DEFAULT '0' COMMENT '已收货数量', + PRIMARY KEY (`id`), + KEY `order_id` (`order_id`), + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购订单明细'; + +-- ---------------------------- +-- Records of tbl_purchase_order_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_purchase_return +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_return`; +CREATE TABLE `tbl_purchase_return` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `purchaser_id` varchar(32) DEFAULT NULL COMMENT '采购员ID', + `payment_date` date DEFAULT NULL COMMENT '付款日期', + `receive_sheet_id` varchar(32) DEFAULT NULL COMMENT '收货单ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '退货金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `tx_id` varchar(100) DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `sc_id` (`sc_id`) USING BTREE, + KEY `supplier_id` (`supplier_id`) USING BTREE, + KEY `receive_sheet_id` (`receive_sheet_id`), + KEY `create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购退单'; + +-- ---------------------------- +-- Records of tbl_purchase_return +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_purchase_return_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_purchase_return_detail`; +CREATE TABLE `tbl_purchase_return_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `return_id` varchar(32) NOT NULL COMMENT '收货单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `return_num` int(11) NOT NULL COMMENT '退货数量', + `tax_price` decimal(16,2) NOT NULL COMMENT '采购价', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `receive_sheet_detail_id` varchar(32) DEFAULT NULL COMMENT '收货单明细ID', + PRIMARY KEY (`id`), + KEY `return_id` (`return_id`) USING BTREE, + KEY `receive_sheet_detail_id` (`receive_sheet_detail_id`), + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购退单明细'; + +-- ---------------------------- +-- Records of tbl_purchase_return_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_receive_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_receive_sheet`; +CREATE TABLE `tbl_receive_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID', + `purchaser_id` varchar(32) DEFAULT NULL COMMENT '采购员ID', + `payment_date` date DEFAULT NULL COMMENT '付款日期', + `receive_date` date DEFAULT NULL COMMENT '到货日期', + `purchase_order_id` varchar(32) DEFAULT NULL COMMENT '采购单ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '收货金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `tx_id` varchar(100) DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `sc_id` (`sc_id`) USING BTREE, + KEY `supplier_id` (`supplier_id`) USING BTREE, + KEY `purchase_order_id` (`purchase_order_id`), + KEY `create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购收货单'; + +-- ---------------------------- +-- Records of tbl_receive_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_receive_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_receive_sheet_detail`; +CREATE TABLE `tbl_receive_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '收货单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '采购数量', + `tax_price` decimal(16,2) NOT NULL COMMENT '采购价', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `purchase_order_detail_id` varchar(32) DEFAULT NULL COMMENT '采购订单明细ID', + `return_num` int(11) NOT NULL DEFAULT '0' COMMENT '已退货数量', + PRIMARY KEY (`id`), + KEY `sheet_id` (`sheet_id`) USING BTREE, + KEY `purchase_order_detail_id` (`purchase_order_detail_id`), + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购收货单明细'; + +-- ---------------------------- +-- Records of tbl_receive_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_retail_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_config`; +CREATE TABLE `tbl_retail_config` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `retail_out_sheet_require_member` tinyint(1) NOT NULL DEFAULT '1' COMMENT '零售出库单上的会员是否必填', + `retail_return_require_out_stock` tinyint(1) NOT NULL DEFAULT '0' COMMENT '零售退货单是否关联零售出库单', + `retail_return_multiple_relate_out_stock` tinyint(1) NOT NULL DEFAULT '0' COMMENT '零售退货单是否多次关联零售出库单', + `retail_return_require_member` tinyint(1) NOT NULL DEFAULT '1' COMMENT '零售退货单上的会员是否必填', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售参数设置'; + +-- ---------------------------- +-- Records of tbl_retail_config +-- ---------------------------- +BEGIN; +INSERT INTO `tbl_retail_config` (`id`, `retail_out_sheet_require_member`, `retail_return_require_out_stock`, `retail_return_multiple_relate_out_stock`, `retail_return_require_member`) VALUES ('1', 0, 0, 1, 0); +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet`; +CREATE TABLE `tbl_retail_out_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `member_id` varchar(32) DEFAULT NULL COMMENT '会员ID', + `saler_id` varchar(32) DEFAULT NULL COMMENT '销售员ID', + `payment_date` date DEFAULT NULL COMMENT '付款日期', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '出库金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `sc_id` (`sc_id`) USING BTREE, + KEY `create_time` (`create_time`), + KEY `member_id` (`member_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售出库单'; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet_detail`; +CREATE TABLE `tbl_retail_out_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '出库单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `ori_price` decimal(16,2) NOT NULL COMMENT '原价', + `tax_price` decimal(16,2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16,2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `return_num` int(11) NOT NULL DEFAULT '0' COMMENT '已退货数量', + PRIMARY KEY (`id`), + KEY `sheet_id` (`sheet_id`) USING BTREE, + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售出库单明细'; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_retail_out_sheet_detail_lot +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_out_sheet_detail_lot`; +CREATE TABLE `tbl_retail_out_sheet_detail_lot` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `detail_id` varchar(32) NOT NULL COMMENT '明细ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `return_num` int(11) NOT NULL DEFAULT '0' COMMENT '已退货数量', + `cost_tax_amount` decimal(24,2) NOT NULL COMMENT '含税成本金额', + `cost_un_tax_amount` decimal(24,6) NOT NULL COMMENT '无税成本金额', + `settle_status` tinyint(3) NOT NULL COMMENT '结算状态', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`), + KEY `detail_id` (`detail_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售出库单批次明细'; + +-- ---------------------------- +-- Records of tbl_retail_out_sheet_detail_lot +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_retail_return +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_return`; +CREATE TABLE `tbl_retail_return` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `member_id` varchar(32) DEFAULT NULL COMMENT '会员ID', + `saler_id` varchar(32) DEFAULT NULL COMMENT '销售员ID', + `payment_date` date DEFAULT NULL COMMENT '付款日期', + `out_sheet_id` varchar(32) DEFAULT NULL COMMENT '出库单ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '退货金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `sc_id` (`sc_id`) USING BTREE, + KEY `create_time` (`create_time`), + KEY `out_sheet_id` (`out_sheet_id`) USING BTREE, + KEY `member_id` (`member_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售退单'; + +-- ---------------------------- +-- Records of tbl_retail_return +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_retail_return_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_retail_return_detail`; +CREATE TABLE `tbl_retail_return_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `return_id` varchar(32) NOT NULL COMMENT '退货单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `return_num` int(11) NOT NULL COMMENT '退货数量', + `ori_price` decimal(16,2) NOT NULL COMMENT '原价', + `tax_price` decimal(16,2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16,2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `out_sheet_detail_id` varchar(32) DEFAULT NULL COMMENT '出库单明细ID', + PRIMARY KEY (`id`), + KEY `return_id` (`return_id`) USING BTREE, + KEY `out_sheet_detail_id` (`out_sheet_detail_id`) USING BTREE, + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售退单明细'; + +-- ---------------------------- +-- Records of tbl_retail_return_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_config`; +CREATE TABLE `tbl_sale_config` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `out_stock_require_sale` tinyint(1) NOT NULL DEFAULT '0' COMMENT '销售出库单是否关联销售订单', + `out_stock_multiple_relate_sale` tinyint(1) NOT NULL DEFAULT '0' COMMENT '销售出库单是否多次关联销售订单', + `sale_return_require_out_stock` tinyint(1) NOT NULL DEFAULT '0' COMMENT '销售退货单是否关联销售出库单', + `sale_return_multiple_relate_out_stock` tinyint(1) NOT NULL DEFAULT '0' COMMENT '销售退货单是否多次关联销售出库单', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售参数设置'; + +-- ---------------------------- +-- Records of tbl_sale_config +-- ---------------------------- +BEGIN; +INSERT INTO `tbl_sale_config` (`id`, `out_stock_require_sale`, `out_stock_multiple_relate_sale`, `sale_return_require_out_stock`, `sale_return_multiple_relate_out_stock`) VALUES ('1', 0, 0, 0, 0); +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_order +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_order`; +CREATE TABLE `tbl_sale_order` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `saler_id` varchar(32) DEFAULT NULL COMMENT '销售员ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '销售数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '销售金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `sc_id` (`sc_id`), + KEY `create_time` (`create_time`), + KEY `customer_id` (`customer_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售订单'; + +-- ---------------------------- +-- Records of tbl_sale_order +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_order_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_order_detail`; +CREATE TABLE `tbl_sale_order_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `order_id` varchar(32) NOT NULL COMMENT '订单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '销售数量', + `ori_price` decimal(16,2) NOT NULL COMMENT '原价', + `tax_price` decimal(16,2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16,2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `out_num` int(11) NOT NULL DEFAULT '0' COMMENT '已出库数量', + PRIMARY KEY (`id`), + KEY `order_id` (`order_id`), + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售订单明细'; + +-- ---------------------------- +-- Records of tbl_sale_order_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet`; +CREATE TABLE `tbl_sale_out_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `saler_id` varchar(32) DEFAULT NULL COMMENT '销售员ID', + `payment_date` date DEFAULT NULL COMMENT '付款日期', + `sale_order_id` varchar(32) DEFAULT NULL COMMENT '销售单ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '出库金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `tx_id` varchar(100) DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `sc_id` (`sc_id`) USING BTREE, + KEY `create_time` (`create_time`), + KEY `customer_id` (`customer_id`) USING BTREE, + KEY `sale_order_id` (`sale_order_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售出库单'; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet_detail`; +CREATE TABLE `tbl_sale_out_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '出库单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `ori_price` decimal(16,2) NOT NULL COMMENT '原价', + `tax_price` decimal(16,2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16,2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `sale_order_detail_id` varchar(32) DEFAULT NULL COMMENT '销售订单明细ID', + `return_num` int(11) NOT NULL DEFAULT '0' COMMENT '已退货数量', + PRIMARY KEY (`id`), + KEY `sheet_id` (`sheet_id`) USING BTREE, + KEY `purchase_order_detail_id` (`sale_order_detail_id`), + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售出库单明细'; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_out_sheet_detail_lot +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_out_sheet_detail_lot`; +CREATE TABLE `tbl_sale_out_sheet_detail_lot` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `detail_id` varchar(32) NOT NULL COMMENT '明细ID', + `order_num` int(11) NOT NULL COMMENT '出库数量', + `return_num` int(11) NOT NULL DEFAULT '0' COMMENT '已退货数量', + `cost_tax_amount` decimal(24,2) NOT NULL COMMENT '含税成本金额', + `cost_un_tax_amount` decimal(24,6) NOT NULL COMMENT '无税成本金额', + `settle_status` tinyint(3) NOT NULL COMMENT '结算状态', + `order_no` int(11) NOT NULL COMMENT '排序编号', + PRIMARY KEY (`id`), + KEY `detail_id` (`detail_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售出库单批次明细'; + +-- ---------------------------- +-- Records of tbl_sale_out_sheet_detail_lot +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_return +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_return`; +CREATE TABLE `tbl_sale_return` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '单号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `customer_id` varchar(32) NOT NULL COMMENT '客户ID', + `saler_id` varchar(32) DEFAULT NULL COMMENT '销售员ID', + `payment_date` date DEFAULT NULL COMMENT '付款日期', + `out_sheet_id` varchar(32) DEFAULT NULL COMMENT '出库单ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量', + `total_gift_num` int(11) NOT NULL DEFAULT '0' COMMENT '赠品数量', + `total_amount` decimal(24,2) NOT NULL DEFAULT '0.00' COMMENT '退货金额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `tx_id` varchar(100) DEFAULT NULL COMMENT '事务ID', + `ori_settle_status` tinyint(3) DEFAULT NULL COMMENT '结算状态中间态', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) USING BTREE, + KEY `sc_id` (`sc_id`) USING BTREE, + KEY `create_time` (`create_time`), + KEY `customer_id` (`customer_id`) USING BTREE, + KEY `out_sheet_id` (`out_sheet_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售退单'; + +-- ---------------------------- +-- Records of tbl_sale_return +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_sale_return_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_sale_return_detail`; +CREATE TABLE `tbl_sale_return_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `return_id` varchar(32) NOT NULL COMMENT '退货单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `return_num` int(11) NOT NULL COMMENT '退货数量', + `ori_price` decimal(16,2) NOT NULL COMMENT '原价', + `tax_price` decimal(16,2) NOT NULL COMMENT '现价', + `discount_rate` decimal(16,2) NOT NULL COMMENT '折扣率(%)', + `is_gift` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否赠品', + `tax_rate` decimal(16,2) NOT NULL COMMENT '税率(%)', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `settle_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '结算状态', + `out_sheet_detail_id` varchar(32) DEFAULT NULL COMMENT '出库单明细ID', + PRIMARY KEY (`id`), + KEY `return_id` (`return_id`) USING BTREE, + KEY `out_sheet_detail_id` (`out_sheet_detail_id`) USING BTREE, + KEY `product_id` (`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售退单明细'; + +-- ---------------------------- +-- Records of tbl_sale_return_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_shop +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_shop`; +CREATE TABLE `tbl_shop` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `dept_id` varchar(32) DEFAULT NULL COMMENT '所属部门ID', + `lng` decimal(16,6) DEFAULT NULL COMMENT '经度', + `lat` decimal(16,6) DEFAULT NULL COMMENT '纬度', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1-在用 0停用', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='门店'; + +-- ---------------------------- +-- Records of tbl_shop +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_stock_cost_adjust_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_cost_adjust_sheet`; +CREATE TABLE `tbl_stock_cost_adjust_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `product_num` int(11) NOT NULL COMMENT '调价品种数', + `diff_amount` decimal(24,2) NOT NULL COMMENT '库存调价差额', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `sc_id` (`sc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存成本调整单'; + +-- ---------------------------- +-- Records of tbl_stock_cost_adjust_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_stock_cost_adjust_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_stock_cost_adjust_sheet_detail`; +CREATE TABLE `tbl_stock_cost_adjust_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '单据ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL COMMENT '库存数量', + `purchase_price` decimal(16,2) NOT NULL COMMENT '档案采购价', + `ori_price` decimal(16,2) NOT NULL COMMENT '调整前成本价', + `price` decimal(16,2) NOT NULL COMMENT '调整后成本价', + `diff_amount` decimal(24,2) NOT NULL COMMENT '库存调价差额', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存成本调整单明细'; + +-- ---------------------------- +-- Records of tbl_stock_cost_adjust_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_take_stock_config +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_config`; +CREATE TABLE `tbl_take_stock_config` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `show_product` tinyint(1) NOT NULL DEFAULT '0' COMMENT '库存盘点单关联盘点任务后,是否显示盘点任务中的商品数据', + `show_stock` tinyint(1) NOT NULL DEFAULT '0' COMMENT '库存盘点单是否显示盘点任务创建时商品的系统库存数量', + `auto_change_stock` tinyint(1) NOT NULL DEFAULT '0' COMMENT '盘点差异生成时是否自动调整盘点任务中商品的系统库存数量', + `allow_change_num` tinyint(1) NOT NULL DEFAULT '0' COMMENT '盘点差异单中的盘点数量是否允许手动修改', + `cancel_hours` int(11) NOT NULL DEFAULT '24' COMMENT '盘点任务创建后多少小时内内未完成,则自动作废', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存盘点参数设置'; + +-- ---------------------------- +-- Records of tbl_take_stock_config +-- ---------------------------- +BEGIN; +INSERT INTO `tbl_take_stock_config` (`id`, `show_product`, `show_stock`, `auto_change_stock`, `allow_change_num`, `cancel_hours`) VALUES ('1', 1, 1, 1, 1, 168); +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_take_stock_plan +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_plan`; +CREATE TABLE `tbl_take_stock_plan` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `take_type` tinyint(3) NOT NULL COMMENT '盘点类别', + `biz_id` longtext COMMENT '业务ID', + `take_status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '盘点状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `sc_id` (`sc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存盘点任务'; + +-- ---------------------------- +-- Records of tbl_take_stock_plan +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_take_stock_plan_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_plan_detail`; +CREATE TABLE `tbl_take_stock_plan_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `plan_id` varchar(32) NOT NULL COMMENT '盘点任务ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL COMMENT '初始库存数量', + `ori_take_num` int(11) DEFAULT NULL COMMENT '盘点数量', + `take_num` int(11) DEFAULT NULL COMMENT '修改后的盘点数量', + `total_out_num` int(11) NOT NULL DEFAULT '0' COMMENT '出项数量', + `total_in_num` int(11) NOT NULL DEFAULT '0' COMMENT '入项数量', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL DEFAULT '0' COMMENT '排序', + PRIMARY KEY (`id`), + UNIQUE KEY `plan_id` (`plan_id`,`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存盘点任务明细'; + +-- ---------------------------- +-- Records of tbl_take_stock_plan_detail +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_take_stock_sheet +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_sheet`; +CREATE TABLE `tbl_take_stock_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '业务单据号', + `plan_id` varchar(32) NOT NULL COMMENT '盘点任务ID', + `pre_sheet_id` varchar(32) DEFAULT NULL COMMENT '预先盘点单ID', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `code` (`code`), + KEY `plan_id` (`plan_id`), + KEY `sc_id` (`sc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存盘点单'; + +-- ---------------------------- +-- Records of tbl_take_stock_sheet +-- ---------------------------- +BEGIN; +COMMIT; + +-- ---------------------------- +-- Table structure for tbl_take_stock_sheet_detail +-- ---------------------------- +DROP TABLE IF EXISTS `tbl_take_stock_sheet_detail`; +CREATE TABLE `tbl_take_stock_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '盘点单ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `take_num` int(11) NOT NULL COMMENT '盘点数量', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存盘点单明细'; + +-- ---------------------------- +-- Records of tbl_take_stock_sheet_detail +-- ---------------------------- +BEGIN; +COMMIT; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.1__paytype.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.1__paytype.sql new file mode 100644 index 0000000..aca2de3 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.1__paytype.sql @@ -0,0 +1,425 @@ +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000008', '2000008', 'PayType', '支付方式', NULL, 0, '/base-data/pay-type/index', NULL, '2000', '/pay-type', 0, 1, 0, 'base-data:pay-type:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000008001', '2000008001', '', '新增支付方式', NULL, 0, '', NULL, '2000008', '', 0, 2, 0, 'base-data:pay-type:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000008002', '2000008002', '', '修改支付方式', NULL, 0, '', NULL, '2000008', '', 0, 2, 0, 'base-data:pay-type:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for base_data_pay_type +-- ---------------------------- +DROP TABLE IF EXISTS `base_data_pay_type`; +CREATE TABLE `base_data_pay_type` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `rec_text` tinyint(1) NOT NULL COMMENT '是否记录内容', + `available` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支付方式' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of base_data_pay_type +-- ---------------------------- +INSERT INTO `base_data_pay_type` VALUES ('1', '001', '现金', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('2', '002', '微信支付', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('3', '003', '支付宝支付', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('4', '004', '移动支付', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('5', '005', '优惠券', 1, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); +INSERT INTO `base_data_pay_type` VALUES ('6', '006', '积分', 0, 1, '', '系统管理员', '1', '2023-03-21 10:09:44', '系统管理员', '1', '2023-03-21 10:12:30'); + +SET FOREIGN_KEY_CHECKS = 1; + +ALTER TABLE `base_data_store_center` + ADD COLUMN `zip_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮编' AFTER `people_num`, + ADD COLUMN `receiver` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货人' AFTER `zip_code`, + ADD COLUMN `receive_telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货手机号' AFTER `receiver`, + ADD COLUMN `receive_address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货地址' AFTER `receive_telephone`, + ADD COLUMN `sender` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发货人' AFTER `receive_address`, + ADD COLUMN `send_telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发货手机号' AFTER `sender`, + ADD COLUMN `send_address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发货地址' AFTER `send_telephone`; + +ALTER TABLE `base_data_supplier` + CHANGE COLUMN `delivery_address` `send_address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发货地址' AFTER `address`, + ADD COLUMN `sender` varchar(200) NULL COMMENT '发货人' AFTER `address`, + ADD COLUMN `send_telephone` varchar(20) NULL COMMENT '发货手机号' AFTER `sender`; + +ALTER TABLE `base_data_member` + ADD COLUMN `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地区ID' AFTER `guider_id`, + ADD COLUMN `zip_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮编' AFTER `city_id`, + ADD COLUMN `receiver` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货人' AFTER `zip_code`, + ADD COLUMN `receive_telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货手机号' AFTER `receiver`, + ADD COLUMN `receive_address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货地址' AFTER `receive_telephone`; + +DROP TABLE IF EXISTS `base_data_address`; +CREATE TABLE `base_data_address` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `entity_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '实体ID', + `entity_type` tinyint(3) NOT NULL COMMENT '实体类型', + `address_type` tinyint(3) NOT NULL COMMENT '地址类型', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名', + `telephone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号', + `province_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '省', + `city_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '市', + `district_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '区', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '详细地址', + `is_default` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否默认地址', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `entity_id`(`entity_id`, `entity_type`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '地址库' ROW_FORMAT = Dynamic; +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000009', '2000009', 'Address', '地址库', NULL, 0, '/base-data/address/index', NULL, '2000', '/address', 0, 1, 0, 'base-data:address:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000009001', '2000009001', '', '新增地址', NULL, 0, '', NULL, '2000009', '', 0, 2, 0, 'base-data:address:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000009002', '2000009002', '', '修改地址', NULL, 0, '', NULL, '2000009', '', 0, 2, 0, 'base-data:address:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000009003', '2000009003', '', '导出地址', NULL, 0, '', NULL, '2000009', '', 0, 2, 0, 'base-data:address:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000009004', '2000009004', '', '导入地址', NULL, 0, '', NULL, '2000009', '', 0, 2, 0, 'base-data:address:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); + +INSERT INTO base_data_address ( + id, + entity_id, + entity_type, + address_type, + `name`, + telephone, + province_id, + city_id, + district_id, + address, + is_default, + create_by, + create_by_id, + create_time, + update_by, + update_by_id, + update_time +) SELECT + CONCAT(tb.id, 2) AS id, + tb.id AS entity_id, + 1 AS entity_type, + 2 AS address_type, + tb.receiver, + tb.receive_telephone, + p.id AS province_id, + c.id AS city_id, + d.id AS district_id, + tb.receive_address, + 1 AS is_default, + tb.create_by, + tb.create_by_id, + tb.create_time, + tb.update_by, + tb.update_by_id, + tb.update_time +FROM + base_data_store_center AS tb + INNER JOIN dic_city AS d ON d.id = tb.city_id + INNER JOIN dic_city as c ON c.id = d.parent_id + INNER JOIN dic_city as p ON p.id = c.parent_id +WHERE + tb.receiver IS NOT NULL + AND tb.receiver != '' + AND tb.receive_telephone IS NOT NULL + AND tb.receive_telephone != '' + AND tb.receive_address IS NOT NULL + AND tb.receive_address != ''; + +INSERT INTO base_data_address ( + id, + entity_id, + entity_type, + address_type, + `name`, + telephone, + province_id, + city_id, + district_id, + address, + is_default, + create_by, + create_by_id, + create_time, + update_by, + update_by_id, + update_time +) SELECT + CONCAT(tb.id, 2) AS id, + tb.id AS entity_id, + 2 AS entity_type, + 2 AS address_type, + tb.receiver, + tb.receive_telephone, + p.id AS province_id, + c.id AS city_id, + d.id AS district_id, + tb.receive_address, + 1 AS is_default, + tb.create_by, + tb.create_by_id, + tb.create_time, + tb.update_by, + tb.update_by_id, + tb.update_time +FROM + base_data_customer AS tb + INNER JOIN dic_city AS d ON d.id = tb.city_id + INNER JOIN dic_city as c ON c.id = d.parent_id + INNER JOIN dic_city as p ON p.id = c.parent_id +WHERE + tb.receiver IS NOT NULL + AND tb.receiver != '' + AND tb.receive_telephone IS NOT NULL + AND tb.receive_telephone != '' + AND tb.receive_address IS NOT NULL + AND tb.receive_address != ''; + +INSERT INTO base_data_address ( + id, + entity_id, + entity_type, + address_type, + `name`, + telephone, + province_id, + city_id, + district_id, + address, + is_default, + create_by, + create_by_id, + create_time, + update_by, + update_by_id, + update_time +) SELECT + CONCAT(tb.id, 2) AS id, + tb.id AS entity_id, + 4 AS entity_type, + 2 AS address_type, + tb.receiver, + tb.receive_telephone, + p.id AS province_id, + c.id AS city_id, + d.id AS district_id, + tb.receive_address, + 1 AS is_default, + tb.create_by, + tb.create_by_id, + tb.create_time, + tb.update_by, + tb.update_by_id, + tb.update_time +FROM + base_data_member AS tb + INNER JOIN dic_city AS d ON d.id = tb.city_id + INNER JOIN dic_city as c ON c.id = d.parent_id + INNER JOIN dic_city as p ON p.id = c.parent_id +WHERE + tb.receiver IS NOT NULL + AND tb.receiver != '' + AND tb.receive_telephone IS NOT NULL + AND tb.receive_telephone != '' + AND tb.receive_address IS NOT NULL + AND tb.receive_address != ''; + +INSERT INTO base_data_address ( + id, + entity_id, + entity_type, + address_type, + `name`, + telephone, + province_id, + city_id, + district_id, + address, + is_default, + create_by, + create_by_id, + create_time, + update_by, + update_by_id, + update_time +) SELECT + CONCAT(tb.id, 1) AS id, + tb.id AS entity_id, + 1 AS entity_type, + 1 AS address_type, + tb.sender, + tb.send_telephone, + p.id AS province_id, + c.id AS city_id, + d.id AS district_id, + tb.send_address, + 1 AS is_default, + tb.create_by, + tb.create_by_id, + tb.create_time, + tb.update_by, + tb.update_by_id, + tb.update_time +FROM + base_data_store_center AS tb + INNER JOIN dic_city AS d ON d.id = tb.city_id + INNER JOIN dic_city as c ON c.id = d.parent_id + INNER JOIN dic_city as p ON p.id = c.parent_id +WHERE + tb.sender IS NOT NULL + AND tb.sender != '' + AND tb.send_telephone IS NOT NULL + AND tb.send_telephone != '' + AND tb.send_address IS NOT NULL + AND tb.send_address != ''; + +INSERT INTO base_data_address ( + id, + entity_id, + entity_type, + address_type, + `name`, + telephone, + province_id, + city_id, + district_id, + address, + is_default, + create_by, + create_by_id, + create_time, + update_by, + update_by_id, + update_time +) SELECT + CONCAT(tb.id, 1) AS id, + tb.id AS entity_id, + 3 AS entity_type, + 1 AS address_type, + tb.sender, + tb.send_telephone, + p.id AS province_id, + c.id AS city_id, + d.id AS district_id, + tb.send_address, + 1 AS is_default, + tb.create_by, + tb.create_by_id, + tb.create_time, + tb.update_by, + tb.update_by_id, + tb.update_time +FROM + base_data_supplier AS tb + INNER JOIN dic_city AS d ON d.id = tb.city_id + INNER JOIN dic_city as c ON c.id = d.parent_id + INNER JOIN dic_city as p ON p.id = c.parent_id +WHERE + tb.sender IS NOT NULL + AND tb.sender != '' + AND tb.send_telephone IS NOT NULL + AND tb.send_telephone != '' + AND tb.send_address IS NOT NULL + AND tb.send_address != ''; + +ALTER TABLE `base_data_customer` +DROP COLUMN `receiver`, +DROP COLUMN `receive_telephone`, +DROP COLUMN `receive_address`; + +ALTER TABLE `base_data_member` +DROP COLUMN `zip_code`, +DROP COLUMN `receiver`, +DROP COLUMN `receive_telephone`, +DROP COLUMN `receive_address`; + +ALTER TABLE `base_data_supplier` +DROP COLUMN `sender`, +DROP COLUMN `send_telephone`, +DROP COLUMN `send_address`; + +ALTER TABLE `base_data_store_center` +DROP COLUMN `zip_code`, +DROP COLUMN `receiver`, +DROP COLUMN `receive_telephone`, +DROP COLUMN `receive_address`, +DROP COLUMN `sender`, +DROP COLUMN `send_telephone`, +DROP COLUMN `send_address`; + +DROP TABLE IF EXISTS `tbl_order_pay_type`; +CREATE TABLE `tbl_order_pay_type` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单ID', + `pay_type_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '支付方式ID', + `pay_amount` decimal(24, 2) NOT NULL COMMENT '支付金额', + `text` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '支付内容', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单支付方式' ROW_FORMAT = Dynamic; + +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_purchase_order where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_receive_sheet where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_purchase_return where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_retail_out_sheet where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_retail_return where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_sale_order where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_sale_out_sheet where total_amount > 0; +insert into tbl_order_pay_type (id, order_id, pay_type_id, pay_amount, text) select id, id, 1, total_amount, NULL from tbl_sale_return where total_amount > 0; + +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000002003', '1000002003', '', '部门权限', NULL, 0, '', NULL, '1000002', '', 0, 2, 0, 'system:dept:permission', 1, 1, '', '系统管理员', '1', '2021-06-27 01:33:47', '系统管理员', '1', '2021-07-04 00:34:23'); +DROP TABLE IF EXISTS `sys_data_permission_data`; +CREATE TABLE `sys_data_permission_data` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `biz_id` varchar(32) NOT NULL COMMENT '业务ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `permission_type` tinyint(3) NOT NULL COMMENT '权限类型', + `permission` longtext NOT NULL COMMENT '数据权限', + PRIMARY KEY (`id`), + UNIQUE KEY `biz_id` (`biz_id`,`biz_type`,`permission_type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限数据'; +DROP TABLE IF EXISTS `sys_data_permission_model_detail`; +CREATE TABLE `sys_data_permission_model_detail` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `model_id` int(11) NOT NULL COMMENT '模型ID', + `condition_type` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '条件', + `input_type` tinyint(3) NOT NULL COMMENT '输入类型', + `table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '表名', + `column_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段名', + `enum_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '前端枚举名', + `sql_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'SQL', + PRIMARY KEY (`id`) USING BTREE, + INDEX `model_id`(`model_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据权限模型明细' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_data_permission_model_detail +-- ---------------------------- +INSERT INTO `sys_data_permission_model_detail` VALUES (1, '编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (2, '名称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (3, '简称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'short_name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (4, 'SKU', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'sku_code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (5, '外部编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'external_code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (6, '品类编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'category', 'code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (7, '品类名称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'category', 'name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (8, '品牌编号', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'brand', 'code', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (9, '品牌名称', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'brand', 'name', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (10, '规格', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'spec', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (11, '单位', 1, '0,1,2,3,4,5,6,7,8,9,10', 0, 'product', 'unit', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (12, '状态', 1, '0,5,6,7', 1, 'product', 'available', 'AVAILABLE', NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (13, '创建时间', 1, '0,1,2,3,4,5', 2, 'product', 'create_time', NULL, NULL); +INSERT INTO `sys_data_permission_model_detail` VALUES (14, '创建人部门与本人相同', 2, '6', 99, 'order', 'create_by_id', NULL, 'SELECT __ud.user_id FROM sys_user_dept AS __ud WHERE __ud.dept_id IN ({__var#curDeptIds})'); +INSERT INTO `sys_data_permission_model_detail` VALUES (15, '创建人部门是本人的上级部门', 2, '6', 99, 'order', 'create_by_id', NULL, 'SELECT DISTINCT __ud.user_id FROM sys_user_dept AS __ud WHERE FIND_IN_SET(__ud.dept_id,(SELECT GROUP_CONCAT(__mp.path) FROM sys_dept AS __d INNER JOIN recursion_mapping AS __mp ON __mp.node_id=__d.id AND __mp.node_type=1 WHERE __d.id IN ({__var#curDeptIds}) AND __mp.level> 1))'); +INSERT INTO `sys_data_permission_model_detail` VALUES (16, '创建人部门是本人的下级部门', 2, '6', 99, 'order', 'create_by_id', NULL, 'SELECT DISTINCT __ud.user_id FROM sys_user_dept AS __ud WHERE __ud.dept_id IN (SELECT __mp.node_id FROM recursion_mapping AS __mp WHERE FIND_IN_SET((SELECT __d.id FROM sys_dept AS __d WHERE __d.id IN ({__var#curDeptIds})),__mp.path) AND __mp.node_type=1)'); +INSERT INTO `sys_data_permission_model_detail` VALUES (17, '创建时间', 2, '0,1,2,3,4,5', 2, 'order', 'create_time', NULL, NULL); diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.2__stock_adjust.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.2__stock_adjust.sql new file mode 100644 index 0000000..e391d22 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.2__stock_adjust.sql @@ -0,0 +1,69 @@ +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005002', '3000005002', 'StockAdjustReason', '库存调整原因', NULL, 0, '/sc/stock/adjust/stock/reason/index', NULL, '3000005', '/stock/reason', 0, 1, 0, 'stock:adjust:reason:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005002001', '3000005002001', '', '新增库存成本调整单', NULL, 0, '', NULL, '3000005002', '', 0, 2, 0, 'stock:adjust:reason:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005002002', '3000005002002', '', '修改库存成本调整单', NULL, 0, '', NULL, '3000005002', '', 0, 2, 0, 'stock:adjust:reason:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); + +DROP TABLE IF EXISTS `tbl_stock_adjust_reason`; +CREATE TABLE `tbl_stock_adjust_reason` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `available` tinyint(1) NOT NULL COMMENT '状态', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '库存调整原因' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tbl_stock_adjust_reason +-- ---------------------------- +INSERT INTO `tbl_stock_adjust_reason` VALUES ('1', '001', '初始化数据', 1, '系统内置', '系统管理员', '1', '2023-04-18 14:04:34', '系统管理员', '1', '2023-04-18 14:04:53'); +INSERT INTO `tbl_stock_adjust_reason` VALUES ('2', '002', '损溢', 1, '系统内置', '系统管理员', '1', '2023-04-18 14:04:34', '系统管理员', '1', '2023-04-18 14:04:53'); +INSERT INTO `tbl_stock_adjust_reason` VALUES ('3', '003', '其他', 1, '系统内置', '系统管理员', '1', '2023-04-18 14:04:34', '系统管理员', '1', '2023-04-18 14:04:53'); + +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005003', '3000005003', 'StockAdjustSheet', '库存调整', NULL, 0, '/sc/stock/adjust/stock/index', NULL, '3000005', '/stock', 0, 1, 0, 'stock:adjust:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005003001', '3000005003001', '', '新增库存调整单', NULL, 0, '', NULL, '3000005003', '', 0, 2, 0, 'stock:adjust:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005003002', '3000005003002', '', '修改库存调整单', NULL, 0, '', NULL, '3000005003', '', 0, 2, 0, 'stock:adjust:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005003003', '3000005003003', '', '删除库存调整单', NULL, 0, '', NULL, '3000005003', '', 0, 2, 0, 'stock:adjust:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005003004', '3000005003004', '', '导出库存调整单', NULL, 0, '', NULL, '3000005003', '', 0, 2, 0, 'stock:adjust:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000005003005', '3000005003005', '', '审核库存调整单', NULL, 0, '', NULL, '3000005003', '', 0, 2, 0, 'stock:adjust:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); + +DROP TABLE IF EXISTS `tbl_stock_adjust_sheet`; +CREATE TABLE `tbl_stock_adjust_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '业务单据号', + `sc_id` varchar(32) NOT NULL COMMENT '仓库ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + `reason_id` varchar(32) NOT NULL COMMENT '调整原因ID', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `approve_time` datetime DEFAULT NULL COMMENT '审核时间', + `refuse_reason` varchar(200) DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `sc_id` (`sc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存调整单'; + +DROP TABLE IF EXISTS `tbl_stock_adjust_sheet_detail`; +CREATE TABLE `tbl_stock_adjust_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '单据ID', + `product_id` varchar(32) NOT NULL COMMENT '商品ID', + `stock_num` int(11) NOT NULL COMMENT '调整库存数量', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`product_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存调整单明细'; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.3__sc_transfer.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.3__sc_transfer.sql new file mode 100644 index 0000000..be50159 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.3__sc_transfer.sql @@ -0,0 +1,74 @@ +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006', '3000006', 'ScTransferOrder', '仓库调拨', NULL, 0, '/sc/stock/transfer/index', NULL, '3000', '/transfer', 0, 1, 0, 'stock:sc-transfer:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006001', '3000006001', '', '新增仓库调拨单', NULL, 0, '', NULL, '3000006', '', 0, 2, 0, 'stock:sc-transfer:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006002', '3000006002', '', '修改仓库调拨单', NULL, 0, '', NULL, '3000006', '', 0, 2, 0, 'stock:sc-transfer:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006003', '3000006003', '', '删除仓库调拨单', NULL, 0, '', NULL, '3000006', '', 0, 2, 0, 'stock:sc-transfer:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006004', '3000006004', '', '导出仓库调拨单', NULL, 0, '', NULL, '3000006', '', 0, 2, 0, 'stock:sc-transfer:export', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006005', '3000006005', '', '审核仓库调拨单', NULL, 0, '', NULL, '3000006', '', 0, 2, 0, 'stock:sc-transfer:approve', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('3000006006', '3000006006', '', '仓库调拨单收货', NULL, 0, '', NULL, '3000006', '', 0, 2, 0, 'stock:sc-transfer:receive', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +ALTER TABLE `tbl_retail_out_sheet_detail_lot` +DROP COLUMN `cost_un_tax_amount`; + +ALTER TABLE `tbl_sale_out_sheet_detail_lot` +DROP COLUMN `cost_un_tax_amount`; + +ALTER TABLE `tbl_product_stock_log` +DROP COLUMN `ori_un_tax_price`, +DROP COLUMN `cur_un_tax_price`, +DROP COLUMN `un_tax_amount`; + +ALTER TABLE `tbl_product_stock` +DROP COLUMN `un_tax_price`, +DROP COLUMN `un_tax_amount`; + +DROP TABLE IF EXISTS `tbl_sc_transfer_order`; +CREATE TABLE `tbl_sc_transfer_order` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '单号', + `source_sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '转出仓库ID', + `target_sc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '转入仓库ID', + `total_num` int(11) NOT NULL DEFAULT 0 COMMENT '调拨数量', + `total_amount` decimal(24, 2) NOT NULL DEFAULT 0.00 COMMENT '调拨成本金额', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + `approve_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '审核人', + `approve_time` datetime NULL DEFAULT NULL COMMENT '审核时间', + `status` tinyint(3) NOT NULL COMMENT '状态', + `refuse_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '拒绝原因', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `code`(`code`) USING BTREE, + INDEX `source_sc_id`(`source_sc_id`) USING BTREE, + INDEX `target_sc_id`(`target_sc_id`) USING BTREE, + INDEX `create_time`(`create_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库调拨单' ROW_FORMAT = Dynamic; + +CREATE TABLE `tbl_sc_transfer_order_detail` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '调拨单ID', + `product_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品ID', + `transfer_num` int(11) NOT NULL COMMENT '调拨数量', + `tax_price` decimal(16, 2) NULL DEFAULT NULL COMMENT '成本价', + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `order_no` int(11) NOT NULL COMMENT '排序编号', + `receive_num` int(11) NOT NULL DEFAULT 0 COMMENT '已收货数量', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`) USING BTREE, + INDEX `product_id`(`product_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库调拨单明细' ROW_FORMAT = Dynamic; + +DROP TABLE IF EXISTS `tbl_sc_transfer_order_detail_receive`; +CREATE TABLE `tbl_sc_transfer_order_detail_receive` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID', + `order_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '调拨单ID', + `detail_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '明细ID', + `receive_num` int(11) NOT NULL COMMENT '收货数量', + `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `order_id`(`order_id`, `detail_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '仓库调拨单收货明细' ROW_FORMAT = Dynamic; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.4__bundle_product.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.4__bundle_product.sql new file mode 100644 index 0000000..4b7ed0d --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.4__bundle_product.sql @@ -0,0 +1,81 @@ +ALTER TABLE `base_data_product` +ADD COLUMN `product_type` tinyint(3) NOT NULL DEFAULT 1 COMMENT '商品类型' AFTER `brand_id`; + +ALTER TABLE `tbl_sale_out_sheet_detail` +ADD COLUMN `ori_bundle_detail_id` varchar(32) NULL COMMENT '组合商品原始明细ID' AFTER `sale_order_detail_id`; +ALTER TABLE `tbl_sale_order_detail` +ADD COLUMN `ori_bundle_detail_id` varchar(32) NULL COMMENT '组合商品原始明细ID' AFTER `out_num`; +ALTER TABLE `tbl_retail_out_sheet_detail` +ADD COLUMN `ori_bundle_detail_id` varchar(32) NULL COMMENT '组合商品原始明细ID' AFTER `return_num`; + +DROP TABLE IF EXISTS `base_data_product_bundle`; +CREATE TABLE `base_data_product_bundle` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `main_product_id` varchar(32) NOT NULL COMMENT '主商品ID', + `product_id` varchar(32) NOT NULL COMMENT '单品ID', + `bundle_num` int(11) NOT NULL COMMENT '包含数量', + `sale_price` decimal(24,2) NOT NULL COMMENT '销售价', + `retail_price` decimal(24,2) NOT NULL COMMENT '零售价', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `main_product_id` (`main_product_id`,`product_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='组合商品'; + +DROP TABLE IF EXISTS `tbl_sale_out_sheet_detail_bundle`; +CREATE TABLE `tbl_sale_out_sheet_detail_bundle` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '出库单ID', + `detail_id` varchar(32) NOT NULL COMMENT '明细ID', + `main_product_id` varchar(32) NOT NULL COMMENT '组合商品ID', + `order_num` int(11) NOT NULL DEFAULT '0' COMMENT '组合商品数量', + `product_id` varchar(32) NOT NULL COMMENT '单品ID', + `product_order_num` int(11) NOT NULL COMMENT '单品数量', + `product_ori_price` decimal(16,2) NOT NULL COMMENT '单品原价', + `product_tax_price` decimal(16,2) NOT NULL COMMENT '单品含税价格', + `product_tax_rate` varchar(16) NOT NULL COMMENT '单品税率', + `product_detail_id` varchar(32) DEFAULT NULL COMMENT '单品明细ID', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`product_detail_id`) USING BTREE, + KEY `detail_id` (`detail_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售出库单组合商品明细'; + +DROP TABLE IF EXISTS `tbl_sale_order_detail_bundle`; +CREATE TABLE `tbl_sale_order_detail_bundle` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `order_id` varchar(32) NOT NULL COMMENT '销售单ID', + `detail_id` varchar(32) NOT NULL COMMENT '明细ID', + `main_product_id` varchar(32) NOT NULL COMMENT '组合商品ID', + `order_num` int(11) NOT NULL DEFAULT '0' COMMENT '组合商品数量', + `product_id` varchar(32) NOT NULL COMMENT '单品ID', + `product_order_num` int(11) NOT NULL COMMENT '单品数量', + `product_ori_price` decimal(16,2) NOT NULL COMMENT '单品原价', + `product_tax_price` decimal(16,2) NOT NULL COMMENT '单品含税价格', + `product_tax_rate` varchar(16) NOT NULL COMMENT '单品税率', + `product_detail_id` varchar(32) DEFAULT NULL COMMENT '单品明细ID', + PRIMARY KEY (`id`), + UNIQUE KEY `order_id` (`order_id`,`product_detail_id`) USING BTREE, + KEY `detail_id` (`detail_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售单组合商品明细'; + +DROP TABLE IF EXISTS `tbl_retail_out_sheet_detail_bundle`; +CREATE TABLE `tbl_retail_out_sheet_detail_bundle` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '出库单ID', + `detail_id` varchar(32) NOT NULL COMMENT '明细ID', + `main_product_id` varchar(32) NOT NULL COMMENT '组合商品ID', + `order_num` int(11) NOT NULL DEFAULT '0' COMMENT '组合商品数量', + `product_id` varchar(32) NOT NULL COMMENT '单品ID', + `product_order_num` int(11) NOT NULL COMMENT '单品数量', + `product_ori_price` decimal(16,2) NOT NULL COMMENT '单品原价', + `product_tax_price` decimal(16,2) NOT NULL COMMENT '单品含税价格', + `product_tax_rate` varchar(16) NOT NULL COMMENT '单品税率', + `product_detail_id` varchar(32) DEFAULT NULL COMMENT '单品明细ID', + PRIMARY KEY (`id`), + UNIQUE KEY `sheet_id` (`sheet_id`,`product_detail_id`) USING BTREE, + KEY `detail_id` (`detail_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='零售出库单组合商品明细'; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.5__logistics.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.5__logistics.sql new file mode 100644 index 0000000..980ca45 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.5__logistics.sql @@ -0,0 +1,376 @@ +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000010', '2000010', 'LogisticsCompany', '物流公司', NULL, 0, '/base-data/logistics/company/index', NULL, '2000', '/logistics/company', 0, 1, 0, 'base-data:logistics-company:query', 1, 1, '', '系统管理员', '1', '2021-07-05 21:59:35', '系统管理员', '1', '2021-07-05 21:59:36'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000010001', '2000010001', '', '新增物流公司', NULL, 0, '', NULL, '2000010', '', 0, 2, 0, 'base-data:logistics-company:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('2000010002', '2000010002', '', '修改物流公司', NULL, 0, '', NULL, '2000010', '', 0, 2, 0, 'base-data:logistics-company:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-07-04 00:34:23'); +ALTER TABLE `base_data_product` +ADD COLUMN `weight` decimal(16, 2) NULL COMMENT '重量(kg)' AFTER `unit`, +ADD COLUMN `volume` decimal(16, 2) NULL COMMENT '体积(cm3)' AFTER `weight`; + +ALTER TABLE `sys_menu` +ADD COLUMN `sys_module_id` varchar(32) NULL COMMENT '系统模块ID' AFTER `parent_id`; + +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000001001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000001002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000001003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000002001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000002002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000002003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000003001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000003002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000004'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000004001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000004002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000004003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000005'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000005001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000005002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000005003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000006'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000007'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000007001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000007002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000007003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000008'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000008001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000008002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000009'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010001'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010002'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010003'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010004'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010005'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010006'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010007'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010008'; +UPDATE `sys_menu` SET `sys_module_id` = '2' WHERE `id` = '1000010009'; +UPDATE `sys_menu` SET `sys_module_id` = '1' WHERE `id` = '1000011'; +UPDATE `sys_menu` SET `sys_module_id` = '1' WHERE `id` = '1000011001'; +UPDATE `sys_menu` SET `sys_module_id` = '1' WHERE `id` = '1000011002'; +UPDATE `sys_menu` SET `sys_module_id` = '14' WHERE `id` = '1000012'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000002'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000002001'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000002002'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000002003'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000004'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000004001'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000004002'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000004003'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000005'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000005001'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000005002'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000005003'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000006'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000006001'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000006002'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000006003'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000007'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000007001'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000007002'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000007003'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000008'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000008001'; +UPDATE `sys_menu` SET `sys_module_id` = '3' WHERE `id` = '2000008002'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000009'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000009001'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000009002'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000009003'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000009004'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000010'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000010001'; +UPDATE `sys_menu` SET `sys_module_id` = '15' WHERE `id` = '2000010002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001001001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001001002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001001003'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001002001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001002002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001002003'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001003'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001003001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001003002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001003003'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001003004'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001003005'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001004'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001004001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001004002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001004003'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001004004'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001004005'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001005'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001005001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001005002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001005003'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001006'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001006001'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001006002'; +UPDATE `sys_menu` SET `sys_module_id` = '4' WHERE `id` = '2001006003'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002001'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002001'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002002'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002003'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002004'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002005'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002002006'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003001'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003002'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003003'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003004'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003005'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002003006'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002004'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002004001'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002004002'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002004003'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002004004'; +UPDATE `sys_menu` SET `sys_module_id` = '5' WHERE `id` = '2002004005'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003001'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003002'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003002001'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003002002'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003002003'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003002004'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003002005'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003003'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003003001'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003003002'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003003003'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003003004'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003003005'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003004'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003004001'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003004002'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003004003'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003004004'; +UPDATE `sys_menu` SET `sys_module_id` = '6' WHERE `id` = '2003004005'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004001'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004002'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004002001'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004002002'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004002003'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004002004'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004002005'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004003'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004003001'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004003002'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004003003'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004003004'; +UPDATE `sys_menu` SET `sys_module_id` = '7' WHERE `id` = '2004003005'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000001'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000001001'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000003'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000003001'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004001'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004002'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004002001'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004002002'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004002003'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004002004'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003001'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003002'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003003'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003004'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003005'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003006'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004003007'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004001'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004002'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004003'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004004'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004005'; +UPDATE `sys_menu` SET `sys_module_id` = '9' WHERE `id` = '3000004004006'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005001'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005001001'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005001002'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005001003'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005001004'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005001005'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005002'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005002001'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005002002'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005003'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005003001'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005003002'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005003003'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005003004'; +UPDATE `sys_menu` SET `sys_module_id` = '10' WHERE `id` = '3000005003005'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006001'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006002'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006003'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006004'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006005'; +UPDATE `sys_menu` SET `sys_module_id` = '8' WHERE `id` = '3000006006'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000001001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000001002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000001003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000002001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000002002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000002003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000003001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000003002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000003003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000003004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000003005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000004001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000004002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000004003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000004004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000004005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000005001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000005002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000005003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000005004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000005005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000006'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000006001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000006002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000006003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000006004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000006005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000007'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000008'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000009'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000009001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000009002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000009003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000009004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000009005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000010'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000010001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000010002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000010003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000010004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000010005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000011'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000011001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000011002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000011003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000011004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000011005'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000012'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000012001'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000012002'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000012003'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000012004'; +UPDATE `sys_menu` SET `sys_module_id` = '11' WHERE `id` = '4000012005'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000001'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000002'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000003'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000004'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000005'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000006'; +UPDATE `sys_menu` SET `sys_module_id` = '12' WHERE `id` = '9000007'; +UPDATE `sys_menu` SET `sys_module_id` = '13' WHERE `id` = '9001'; +UPDATE `sys_menu` SET `sys_module_id` = '13' WHERE `id` = '9001001'; +UPDATE `sys_menu` SET `sys_module_id` = '13' WHERE `id` = '9001002'; +UPDATE `sys_menu` SET `title` = '库存数量调整' WHERE `id` = '3000005003'; +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1000011003', '1000011003', '', '授权模块', NULL, 0, '', NULL, '1000011', '1', '', 0, 2, 0, 'system:tenant:module', 0, 1, '', '系统管理员', '1', '2022-08-18 14:31:12', '系统管理员', '1', '2022-08-18 14:31:12'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1001', '1001', 'Platform', '平台管理', 'a-menu', NULL, '', NULL, '0001', '1', '/platform', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +UPDATE `sys_menu` SET `parent_id` = '1001' WHERE `id` = '1000011'; +UPDATE `sys_menu` SET `parent_id` = '1001' WHERE `id` = '1000012'; + +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000', '5000', 'Logistics', '物流管理', 'a-menu', NULL, '', NULL, '0001', '15', '/logistics', 0, 0, 0, '', 1, 1, '', '系统管理员', '1', '2021-07-04 00:22:05', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001', '5000001', 'LogisticsSheet', '物流单管理', NULL, 0, '/sc/logistics/sheet/index', NULL, '5000', '15', '/sheet', 0, 1, 0, 'logistics:sheet:query', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001001', '5000001001', '', '新增物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:add', 1, 1, '', '系统管理员', '1', '2021-05-12 22:50:27', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001002', '5000001002', '', '修改物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:modify', 1, 1, '', '系统管理员', '1', '2021-05-12 23:23:33', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001003', '5000001003', '', '删除物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:delete', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001004', '5000001004', '', '物流单发货', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:delivery', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001005', '5000001005', '', '导入物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:import', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('5000001006', '5000001006', '', '导出物流单', NULL, 0, '', NULL, '5000001', '15', '', 0, 2, 0, 'logistics:sheet:export', 1, 1, '', '系统管理员', '1', '2021-05-12 23:24:36', '系统管理员', '1', '2021-07-04 00:34:23'); +ALTER TABLE `tbl_sale_config` +ADD COLUMN `out_stock_require_logistics` tinyint(1) NOT NULL DEFAULT 0 COMMENT '销售出库单是否需要物流单' AFTER `sale_return_multiple_relate_out_stock`; +ALTER TABLE `tbl_retail_config` +ADD COLUMN `retail_out_sheet_require_logistics` tinyint(1) NOT NULL DEFAULT 0 COMMENT '零售出库单是否需要发货' AFTER `retail_return_require_member`; + +DROP TABLE IF EXISTS `base_data_logistics_company`; +CREATE TABLE `base_data_logistics_company` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `contact` varchar(100) DEFAULT NULL COMMENT '联系人', + `telephone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `city_id` varchar(32) DEFAULT NULL COMMENT '地区ID', + `address` varchar(200) DEFAULT NULL COMMENT '地址', + `available` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='物流公司'; + +DROP TABLE IF EXISTS `tbl_logistics_sheet`; +CREATE TABLE `tbl_logistics_sheet` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(32) NOT NULL COMMENT '业务单据号', + `logistics_no` varchar(100) DEFAULT NULL COMMENT '物流单号', + `logistics_company_id` varchar(32) NOT NULL COMMENT '物流公司ID', + `sender_name` varchar(100) NOT NULL COMMENT '寄件人姓名', + `sender_telephone` varchar(20) NOT NULL COMMENT '寄件人联系电话', + `sender_province_id` varchar(32) NOT NULL COMMENT '寄件人省', + `sender_city_id` varchar(32) NOT NULL COMMENT '寄件人市', + `sender_district_id` varchar(32) NOT NULL COMMENT '寄件人区', + `sender_address` varchar(200) NOT NULL COMMENT '寄件人地址', + `receiver_name` varchar(100) NOT NULL COMMENT '收件人姓名', + `receiver_telephone` varchar(20) NOT NULL COMMENT '收件人联系电话', + `receiver_province_id` varchar(32) NOT NULL COMMENT '收件人省', + `receiver_city_id` varchar(32) NOT NULL COMMENT '收件人市', + `receiver_district_id` varchar(32) NOT NULL COMMENT '收件人区', + `receiver_address` varchar(200) NOT NULL COMMENT '收件人地址', + `total_weight` decimal(16,2) DEFAULT NULL COMMENT '总重量(kg)', + `total_volume` decimal(16,2) DEFAULT NULL COMMENT '总体积(cm3)', + `total_amount` decimal(16,2) DEFAULT NULL COMMENT '物流费', + `status` tinyint(3) NOT NULL COMMENT '状态', + `description` varchar(200) NOT NULL DEFAULT '' COMMENT '备注', + `delivery_by` varchar(32) DEFAULT NULL COMMENT '发货人', + `delivery_time` datetime DEFAULT NULL COMMENT '发货时间', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `logistics_no` (`logistics_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='物流单'; + +DROP TABLE IF EXISTS `tbl_logistics_sheet_detail`; +CREATE TABLE `tbl_logistics_sheet_detail` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `sheet_id` varchar(32) NOT NULL COMMENT '物流单ID', + `biz_id` varchar(32) NOT NULL COMMENT '业务单据ID', + `biz_type` tinyint(3) NOT NULL COMMENT '业务类型', + PRIMARY KEY (`id`), + UNIQUE KEY ```biz_id``` (`biz_id`,`biz_type`) USING BTREE, + KEY `sheet_id` (`sheet_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='物流单明细'; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.6__custom_page.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.6__custom_page.sql new file mode 100644 index 0000000..9448b79 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.6__custom_page.sql @@ -0,0 +1,34 @@ +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('9000008', '9000008', 'CustomPage', '自定义页面', NULL, 0, '/development/custom/page/index', NULL, '9000', '12', '/custom/page', 0, 1, 0, '', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +INSERT INTO `sys_menu` (`id`, `code`, `name`, `title`, `icon`, `component_type`, `component`, `request_param`, `parent_id`, `sys_module_id`, `path`, `no_cache`, `display`, `hidden`, `permission`, `is_special`, `available`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES ('1001001', '1001001', 'OnelineCode', '在线开发', 'a-menu', 0, '/iframes/index', NULL, '1001', '1', '/online-code?src=${magic-api.base-url}${magic-api.web}/index.html', 0, 1, 0, 'system:online-code:config', 1, 1, '', '系统管理员', '1', '2021-05-08 18:37:01', '系统管理员', '1', '2021-12-09 17:54:42'); +DROP TABLE IF EXISTS `gen_custom_page_category`; +CREATE TABLE `gen_custom_page_category` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `parent_id` varchar(32) DEFAULT NULL COMMENT '父级ID', + `code` varchar(20) NOT NULL COMMENT '编号', + `name` varchar(20) NOT NULL COMMENT '名称', + `create_by` varchar(32) NOT NULL COMMENT '创建人', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义页面分类'; +DROP TABLE IF EXISTS `gen_custom_page`; +CREATE TABLE `gen_custom_page` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(20) NOT NULL COMMENT '名称', + `category_id` varchar(32) DEFAULT NULL COMMENT '分类ID', + `page_code` longtext NOT NULL COMMENT '页面代码', + `script_code` longtext COMMENT '脚本代码', + `description` varchar(200) DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) NOT NULL COMMENT '创建人ID', + `create_by_id` varchar(32) NOT NULL COMMENT '创建人ID', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(32) NOT NULL COMMENT '修改人ID', + `update_by_id` varchar(32) NOT NULL COMMENT '修改人ID', + `update_time` datetime NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + KEY `category_id` (`category_id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='自定义页面'; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.7__upload_to_oss.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.7__upload_to_oss.sql new file mode 100644 index 0000000..ea3b8d0 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.7__upload_to_oss.sql @@ -0,0 +1,7 @@ +ALTER TABLE `sys_parameter` +MODIFY COLUMN `pm_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '值' AFTER `pm_key`; +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (9, 'upload.type', 'LOCAL', '上传类型,分为LOCAL、OSS、COS、OBS。LOCAL:服务器本地存储。OSS:阿里云对象存储。COS:腾讯云对象存储。OBS:华为云对象存储', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 10:38:10'); +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (11, 'upload.obs.config', '{\"customUrl\":\"\",\"endpoint\":\"yourEndpoint\",\"ak\":\"yourAccessKeyId\",\"sk\":\"yourAccessKeySecret\",\"bucketName\":\"yourBucketName\"}', '华为云对象存储配置信息,upload.type=OBS时生效。customUrl为自定义域名(需带协议)为空代表不使用自定义域名,示例值:https://www.lframework.com。其他参数均在华为云控台获取。', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 10:38:10'); +DELETE FROM `sys_parameter` WHERE `id` = 7 AND `pm_key` = 'sms.ali'; +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (10, 'upload.oss.config', '{\"customUrl\":\"\",\"endpoint\":\"yourEndpoint\",\"internalEndPoint\":\"\",\"accessKeyId\":\"yourAccessKeyId\",\"accessKeySecret\":\"yourAccessKeySecret\",\"bucketName\":\"yourBucketName\"}', '阿里云对象存储配置信息,upload.type=OSS时生效,注意:当服务器与OSS同一地域时,建议填写internalEndPoint,此值表示内网endpoint,在上传时会优先使用内网endpoint。customUrl为自定义域名(需带协议)为空代表不使用自定义域名,示例值:https://www.lframework.com。其他参数均在阿里云控台获取。', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 10:38:10'); +INSERT INTO `sys_parameter` (`id`, `pm_key`, `pm_value`, `description`, `create_by`, `create_by_id`, `create_time`, `update_by`, `update_by_id`, `update_time`) VALUES (12, 'upload.cos.config', '{\"customUrl\":\"yourCustomUrl\",\"region\":\"yourRegion\",\"secretId\":\"yourSecretId\",\"secretKey\":\"yourSecretKey\",\"bucketName\":\"yourBucketName\"}', '腾讯云对象存储配置信息,upload.type=COS时生效。customUrl为下载文件时的域名,如果使用自定义域名,示例值:https://www.lframework.com,如果不使用自定义域名,那么就填写COS的访问域名。其他参数均在腾讯云控台获取。', '系统管理员', '1', '2023-06-27 10:38:05', '系统管理员', '1', '2023-06-27 14:48:02'); diff --git a/xingyun-api/src/main/resources/db/migration/tenant/V1.8__v3.sql b/xingyun-api/src/main/resources/db/migration/tenant/V1.8__v3.sql new file mode 100644 index 0000000..7f00b40 --- /dev/null +++ b/xingyun-api/src/main/resources/db/migration/tenant/V1.8__v3.sql @@ -0,0 +1,49 @@ +ALTER TABLE `sw_file_box` ADD COLUMN `content_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ContentType' AFTER `url`; +ALTER TABLE `sw_file_box` MODIFY COLUMN `url` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'Url' AFTER `name`; +ALTER TABLE `sw_file_box` ADD COLUMN `file_type` tinyint(3) NOT NULL COMMENT '文件类型' AFTER `content_type`; +ALTER TABLE `sw_file_box` ADD COLUMN `file_size` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件大小' AFTER `file_type`; +ALTER TABLE `sw_file_box` ADD COLUMN `file_path` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件路径' AFTER `file_size`; +ALTER TABLE `sw_file_box` ADD COLUMN `file_suffix` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件后缀' AFTER `file_path`; +ALTER TABLE `sw_file_box` DROP COLUMN `available`; +DELETE FROM `sys_menu` WHERE `id` = '0001'; +DELETE FROM `sys_menu` WHERE `id` = '2001003'; +DELETE FROM `sys_menu` WHERE `id` = '2001003001'; +DELETE FROM `sys_menu` WHERE `id` = '2001003002'; +DELETE FROM `sys_menu` WHERE `id` = '2001003003'; +DELETE FROM `sys_menu` WHERE `id` = '2001003004'; +DELETE FROM `sys_menu` WHERE `id` = '2001003005'; +DELETE FROM `sys_menu` WHERE `id` = '2001006'; +DELETE FROM `sys_menu` WHERE `id` = '2001006001'; +DELETE FROM `sys_menu` WHERE `id` = '2001006002'; +DELETE FROM `sys_menu` WHERE `id` = '2001006003'; +DELETE FROM `sys_menu` WHERE `id` = '9000006'; +DELETE FROM `sys_menu` WHERE `id` = '9000007'; +DELETE FROM `sys_menu` WHERE `id` = '9001002'; +UPDATE `sys_menu` SET `code` = '1000', `name` = 'System', `title` = '系统管理', `icon` = 'ant-design:setting-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '2', `path` = '/system', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-04 00:22:05', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:01:09' WHERE `id` = '1000'; +UPDATE `sys_menu` SET `code` = '1000001', `name` = 'Menu', `title` = '菜单管理', `icon` = NULL, `component_type` = 0, `component` = '/system/menu/index', `request_param` = NULL, `parent_id` = '1000', `sys_module_id` = '2', `path` = '/menu', `no_cache` = 0, `display` = 1, `hidden` = 0, `permission` = 'system:menu:query', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-05-08 18:37:01', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:01:09' WHERE `id` = '1000001'; +UPDATE `sys_menu` SET `code` = '1000001001', `name` = '', `title` = '新增菜单', `icon` = NULL, `component_type` = 0, `component` = '', `request_param` = NULL, `parent_id` = '1000001', `sys_module_id` = '2', `path` = '', `no_cache` = 0, `display` = 2, `hidden` = 0, `permission` = 'system:menu:add', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-05-12 22:50:27', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:01:09' WHERE `id` = '1000001001'; +UPDATE `sys_menu` SET `code` = '1000001002', `name` = '', `title` = '修改菜单', `icon` = NULL, `component_type` = 0, `component` = '', `request_param` = NULL, `parent_id` = '1000001', `sys_module_id` = '2', `path` = '', `no_cache` = 0, `display` = 2, `hidden` = 0, `permission` = 'system:menu:modify', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-05-12 23:23:33', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:00:27' WHERE `id` = '1000001002'; +UPDATE `sys_menu` SET `code` = '1000001003', `name` = '', `title` = '删除菜单', `icon` = NULL, `component_type` = 0, `component` = '', `request_param` = NULL, `parent_id` = '1000001', `sys_module_id` = '2', `path` = '', `no_cache` = 0, `display` = 2, `hidden` = 0, `permission` = 'system:menu:delete', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-05-12 23:24:36', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:00:27' WHERE `id` = '1000001003'; +UPDATE `sys_menu` SET `code` = '1000002', `name` = 'Dept', `title` = '部门管理', `icon` = NULL, `component_type` = 0, `component` = '/system/dept/index', `request_param` = NULL, `parent_id` = '1000', `sys_module_id` = '2', `path` = '/dept', `no_cache` = 0, `display` = 1, `hidden` = 0, `permission` = 'system:dept:query', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:09:27', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:00:27' WHERE `id` = '1000002'; +UPDATE `sys_menu` SET `code` = '1000002001', `name` = '', `title` = '新增部门', `icon` = NULL, `component_type` = 0, `component` = '', `request_param` = NULL, `parent_id` = '1000002', `sys_module_id` = '2', `path` = '', `no_cache` = 0, `display` = 2, `hidden` = 0, `permission` = 'system:dept:add', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-06-27 01:33:31', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:00:27' WHERE `id` = '1000002001'; +UPDATE `sys_menu` SET `code` = '1000002002', `name` = '', `title` = '修改部门', `icon` = NULL, `component_type` = 0, `component` = '', `request_param` = NULL, `parent_id` = '1000002', `sys_module_id` = '2', `path` = '', `no_cache` = 0, `display` = 2, `hidden` = 0, `permission` = 'system:dept:modify', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-06-27 01:33:47', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:00:27' WHERE `id` = '1000002002'; +UPDATE `sys_menu` SET `code` = '1000002003', `name` = '', `title` = '部门权限', `icon` = NULL, `component_type` = 0, `component` = '', `request_param` = NULL, `parent_id` = '1000002', `sys_module_id` = '2', `path` = '', `no_cache` = 0, `display` = 2, `hidden` = 0, `permission` = 'system:dept:permission', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-06-27 01:33:47', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2023-10-27 17:00:27' WHERE `id` = '1000002003'; +UPDATE `sys_menu` SET `code` = '1000012', `name` = 'OpenDomain', `title` = '开放域', `icon` = NULL, `component_type` = 0, `component` = '/system/open-domain/index', `request_param` = NULL, `parent_id` = '1001', `sys_module_id` = '14', `path` = '/open-domain', `no_cache` = 0, `display` = 1, `hidden` = 0, `permission` = 'system:open-domain:config', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-05-08 18:37:01', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-12-09 17:54:42' WHERE `id` = '1000012'; +UPDATE `sys_menu` SET `code` = '1001', `name` = 'Platform', `title` = '平台管理', `icon` = 'ant-design:global-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '1', `path` = '/platform', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-04 00:22:05', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-04 00:34:23' WHERE `id` = '1001'; +UPDATE `sys_menu` SET `code` = '1001001', `name` = 'OnelineCode', `title` = '在线开发', `icon` = NULL, `component_type` = 0, `component` = '/iframes/index', `request_param` = NULL, `parent_id` = '1001', `sys_module_id` = '1', `path` = '/online-code?src=${magic-api.base-url}${magic-api.web}/index.html', `no_cache` = 0, `display` = 1, `hidden` = 0, `permission` = 'system:online-code:config', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-05-08 18:37:01', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-12-09 17:54:42' WHERE `id` = '1001001'; +UPDATE `sys_menu` SET `code` = '2000', `name` = 'BaseData', `title` = '基础信息管理', `icon` = 'ant-design:container-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '3', `path` = '/base-data', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '2000'; +UPDATE `sys_menu` SET `code` = '2001', `name` = 'Product', `title` = '商品中心', `icon` = 'ant-design:appstore-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '4', `path` = '/product', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '2001'; +UPDATE `sys_menu` SET `code` = '2002', `name` = 'Purchase', `title` = '采购管理', `icon` = 'ant-design:money-collect-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '5', `path` = '/purchase', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '2002'; +UPDATE `sys_menu` SET `code` = '2003', `name` = 'Sale', `title` = '销售管理', `icon` = 'ant-design:rocket-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '6', `path` = '/sale', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '2003'; +UPDATE `sys_menu` SET `code` = '2004', `name` = 'Retail', `title` = '零售管理', `icon` = 'ant-design:flag-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '7', `path` = '/retail', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '2004'; +UPDATE `sys_menu` SET `code` = '3000', `name` = 'StockManage', `title` = '库存管理', `icon` = 'ant-design:hdd-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '8', `path` = '/stock', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '3000'; +UPDATE `sys_menu` SET `code` = '3000004', `name` = 'TakeStock', `title` = '库存盘点', `icon` = 'ant-design:monitor-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '9', `path` = '/take', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '3000004'; +UPDATE `sys_menu` SET `code` = '3000005', `name` = 'StockAdjust', `title` = '库存调整', `icon` = 'ant-design:thunderbolt-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '10', `path` = '/take-adjust', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '3000005'; +UPDATE `sys_menu` SET `code` = '4000', `name` = 'SettleManage', `title` = '结算管理', `icon` = 'ant-design:credit-card-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '11', `path` = '/settle', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '4000'; +UPDATE `sys_menu` SET `code` = '4000007', `name` = 'SupplierSettleManage', `title` = '供应商结算', `icon` = NULL, `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = '4000', `sys_module_id` = '11', `path` = '/supplier', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '4000007'; +UPDATE `sys_menu` SET `code` = '4000008', `name` = 'CustomerSettleManage', `title` = '客户结算', `icon` = NULL, `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = '4000', `sys_module_id` = '11', `path` = '/customer', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-05 01:21:35', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-05 01:21:39' WHERE `id` = '4000008'; +UPDATE `sys_menu` SET `code` = '5000', `name` = 'Logistics', `title` = '物流管理', `icon` = 'ant-design:gift-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '15', `path` = '/logistics', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-04 00:22:05', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-04 00:34:23' WHERE `id` = '5000'; +UPDATE `sys_menu` SET `code` = '9000', `name` = 'Development', `title` = '开发管理', `icon` = 'ant-design:tool-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '12', `path` = '/development', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-04 00:22:05', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-04 00:34:23' WHERE `id` = '9000'; +UPDATE `sys_menu` SET `code` = '9001', `name` = 'SmartWork', `title` = '便捷办公', `icon` = 'ant-design:read-outlined', `component_type` = NULL, `component` = '', `request_param` = NULL, `parent_id` = NULL, `sys_module_id` = '13', `path` = '/smart-work', `no_cache` = 0, `display` = 0, `hidden` = 0, `permission` = '', `is_special` = 1, `available` = 1, `description` = '', `create_by` = '系统管理员', `create_by_id` = '1', `create_time` = '2021-07-04 00:22:05', `update_by` = '系统管理员', `update_by_id` = '1', `update_time` = '2021-07-04 00:34:23' WHERE `id` = '9001'; +ALTER TABLE `op_logs` + MODIFY COLUMN `log_type` int(11) NOT NULL COMMENT '类别' AFTER `name`; \ No newline at end of file diff --git a/xingyun-api/src/main/resources/magic-editor-config.js b/xingyun-api/src/main/resources/magic-editor-config.js new file mode 100644 index 0000000..f582920 --- /dev/null +++ b/xingyun-api/src/main/resources/magic-editor-config.js @@ -0,0 +1,21 @@ +var MAGIC_EDITOR_CONFIG = { + title: '在线开发平台', + header: { + skin: false, // 屏蔽皮肤按钮 + document: false, // 屏蔽文档按钮 + repo: false, // 屏蔽gitee和github + qqGroup: false // 屏蔽加入QQ群 + }, + getMagicTokenValue: function(){ + return this.getCookie('X-Auth-Token'); + }, + getCookie: function(name) { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i].trim().split('='); + if (cookie[0] === name) { + return decodeURIComponent(cookie[1]); + } + } + } +} \ No newline at end of file diff --git a/xingyun-api/src/main/resources/scripts/start.sh b/xingyun-api/src/main/resources/scripts/start.sh new file mode 100644 index 0000000..b38807f --- /dev/null +++ b/xingyun-api/src/main/resources/scripts/start.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +export BUILD_ID=dontkillme +if [ -z $JAVA_HOME ] ; +then +echo "JAVA_HOME is not exist, please check" +exit 1 +fi +export APP_HOME_BIN_PATH=$(cd `dirname $0`; pwd) +export APP_HOME=${APP_HOME_BIN_PATH%/bin} + +$JAVA_HOME/bin/java -jar -server -Xmx256m -XX:MaxPermSize=32m -XX:MaxNewSize=32m $APP_HOME/@build.finalName@.jar >/dev/null 2>&1 & \ No newline at end of file diff --git a/xingyun-api/src/main/resources/scripts/stop.sh b/xingyun-api/src/main/resources/scripts/stop.sh new file mode 100644 index 0000000..260e4e2 --- /dev/null +++ b/xingyun-api/src/main/resources/scripts/stop.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +export APP_HOME_BIN_PATH=$(cd `dirname $0`; pwd) +export APP_HOME=${APP_HOME_BIN_PATH%/bin} + +export C_PID=`ps -ef | grep java | grep $APP_HOME | grep -v grep | awk '{print $2}'` + +if [ ! -z "$C_PID" ]; then + kill -15 $C_PID; +fi \ No newline at end of file diff --git a/xingyun-basedata/pom.xml b/xingyun-basedata/pom.xml new file mode 100644 index 0000000..25fbfc1 --- /dev/null +++ b/xingyun-basedata/pom.xml @@ -0,0 +1,21 @@ + + + + xingyun + com.lframework + 1.0.0-SNAPSHOT + + 4.0.0 + + xingyun-basedata + 【${project.artifactId}】基础数据服务层 + + + + com.lframework + xingyun-core + + + diff --git a/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/AddressSelectorBo.java b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/AddressSelectorBo.java new file mode 100644 index 0000000..d96ad74 --- /dev/null +++ b/xingyun-basedata/src/main/java/com/lframework/xingyun/basedata/bo/address/AddressSelectorBo.java @@ -0,0 +1,120 @@ +package com.lframework.xingyun.basedata.bo.address; + +import com.lframework.starter.common.constants.StringPool; +import com.lframework.starter.web.annotations.convert.EnumConvert; +import com.lframework.starter.web.bo.BaseBo; +import com.lframework.starter.web.common.utils.ApplicationUtil; +import com.lframework.xingyun.basedata.entity.Address; +import com.lframework.xingyun.core.dto.dic.city.DicCityDto; +import com.lframework.xingyun.core.service.DicCityService; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class AddressSelectorBo extends BaseBo