diff --git a/blade-ops/blade-seata-order/README.md b/blade-ops/blade-seata-order/README.md
new file mode 100644
index 0000000..d8e10fd
--- /dev/null
+++ b/blade-ops/blade-seata-order/README.md
@@ -0,0 +1,30 @@
+-- 创建 order库、业务表、undo_log表
+create database seata_order;
+use seata_order;
+
+DROP TABLE IF EXISTS `tb_order`;
+CREATE TABLE `tb_order` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `user_id` varchar(255) DEFAULT NULL,
+ `commodity_code` varchar(255) DEFAULT NULL,
+ `count` int(11) DEFAULT 0,
+ `money` int(11) DEFAULT 0,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `undo_log`
+(
+ `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+ `branch_id` BIGINT(20) NOT NULL,
+ `xid` VARCHAR(100) NOT NULL,
+ `context` VARCHAR(128) NOT NULL,
+ `rollback_info` LONGBLOB NOT NULL,
+ `log_status` INT(11) NOT NULL,
+ `log_created` DATETIME NOT NULL,
+ `log_modified` DATETIME NOT NULL,
+ `ext` VARCHAR(100) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8;
\ No newline at end of file
diff --git a/blade-ops/blade-seata-order/pom.xml b/blade-ops/blade-seata-order/pom.xml
new file mode 100644
index 0000000..efe6d37
--- /dev/null
+++ b/blade-ops/blade-seata-order/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ blade-ops
+ org.springblade
+ 2.5.0
+
+ 4.0.0
+
+ blade-seata-order
+ ${project.artifactId}
+ ${blade.project.version}
+ jar
+
+
+
+ org.springblade
+ blade-core-boot
+ ${blade.tool.version}
+
+
+ org.springblade
+ blade-core-transaction
+ ${blade.tool.version}
+
+
+
+
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/SeataOrderApplication.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/SeataOrderApplication.java
new file mode 100644
index 0000000..f277f03
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/SeataOrderApplication.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * 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.
+ */
+package org.springblade.seata.order;
+
+import org.springblade.core.launch.BladeApplication;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springblade.core.transaction.annotation.SeataCloudApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * Order启动器
+ *
+ * @author Chill
+ */
+@SeataCloudApplication
+@EnableFeignClients(AppConstant.BASE_PACKAGES)
+public class SeataOrderApplication {
+
+ public static void main(String[] args) {
+ BladeApplication.run("blade-seata-order", SeataOrderApplication.class, args);
+ }
+
+}
+
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/config/OrderConfiguration.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/config/OrderConfiguration.java
new file mode 100644
index 0000000..edafd3a
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/config/OrderConfiguration.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * 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.
+ */
+package org.springblade.seata.order.config;
+
+
+import org.springblade.core.secure.registry.SecureRegistry;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * secure模块api放行配置
+ *
+ * @author Chill
+ */
+@Configuration
+public class OrderConfiguration implements WebMvcConfigurer {
+
+ @Bean
+ public SecureRegistry secureRegistry() {
+ SecureRegistry secureRegistry = new SecureRegistry();
+ secureRegistry.excludePathPatterns("/order/create/**");
+ return secureRegistry;
+ }
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/controller/OrderController.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/controller/OrderController.java
new file mode 100644
index 0000000..9308568
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/controller/OrderController.java
@@ -0,0 +1,34 @@
+package org.springblade.seata.order.controller;
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.seata.order.service.IOrderService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * OrderController
+ *
+ * @author Chill
+ */
+@RestController
+@RequestMapping("order")
+@AllArgsConstructor
+public class OrderController {
+
+ private IOrderService orderService;
+
+ /**
+ * 创建订单
+ *
+ * @param userId 用户id
+ * @param commodityCode 商品代码
+ * @param count 数量
+ * @return boolean
+ */
+ @RequestMapping("/create")
+ public R createOrder(String userId, String commodityCode, Integer count) {
+ return R.status(orderService.createOrder(userId, commodityCode, count));
+ }
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/entity/Order.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/entity/Order.java
new file mode 100644
index 0000000..8ccac26
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/entity/Order.java
@@ -0,0 +1,31 @@
+package org.springblade.seata.order.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * Order
+ *
+ * @author Chill
+ */
+@Data
+@Accessors(chain = true)
+@TableName("tb_order")
+public class Order implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+ private String userId;
+ private String commodityCode;
+ private Integer count;
+ private BigDecimal money;
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/feign/IStorageClient.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/feign/IStorageClient.java
new file mode 100644
index 0000000..1312d8b
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/feign/IStorageClient.java
@@ -0,0 +1,25 @@
+package org.springblade.seata.order.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * StorageClient
+ *
+ * @author Chill
+ */
+@FeignClient(name = "blade-seata-storage", fallback = StorageClientFallback.class)
+public interface IStorageClient {
+
+ /**
+ * 减库存
+ *
+ * @param commodityCode 商品代码
+ * @param count 数量
+ * @return boolean
+ */
+ @GetMapping("/deduct")
+ int deduct(@RequestParam("commodityCode") String commodityCode, @RequestParam("count") Integer count);
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/feign/StorageClientFallback.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/feign/StorageClientFallback.java
new file mode 100644
index 0000000..6bfaeef
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/feign/StorageClientFallback.java
@@ -0,0 +1,18 @@
+package org.springblade.seata.order.feign;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * StorageClientFallback
+ *
+ * @author Chill
+ */
+@Component
+public class StorageClientFallback implements IStorageClient {
+
+ @Override
+ public int deduct(String commodityCode, Integer count) {
+ return -1;
+ }
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/mapper/OrderMapper.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/mapper/OrderMapper.java
new file mode 100644
index 0000000..078c980
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/mapper/OrderMapper.java
@@ -0,0 +1,12 @@
+package org.springblade.seata.order.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.seata.order.entity.Order;
+
+/**
+ * OrderMapper
+ *
+ * @author Chill
+ */
+public interface OrderMapper extends BaseMapper {
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/mapper/OrderMapper.xml b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/mapper/OrderMapper.xml
new file mode 100644
index 0000000..da6e86c
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/mapper/OrderMapper.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/service/IOrderService.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/service/IOrderService.java
new file mode 100644
index 0000000..81a3a4d
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/service/IOrderService.java
@@ -0,0 +1,23 @@
+package org.springblade.seata.order.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.seata.order.entity.Order;
+
+/**
+ * IOrderService
+ *
+ * @author Chill
+ */
+public interface IOrderService extends IService {
+
+ /**
+ * 创建订单
+ *
+ * @param userId 用户id
+ * @param commodityCode 商品代码
+ * @param count 数量
+ * @return boolean
+ */
+ boolean createOrder(String userId, String commodityCode, Integer count);
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/service/impl/OrderServiceImpl.java b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/service/impl/OrderServiceImpl.java
new file mode 100644
index 0000000..388d75f
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/java/org/springblade/seata/order/service/impl/OrderServiceImpl.java
@@ -0,0 +1,48 @@
+package org.springblade.seata.order.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import io.seata.spring.annotation.GlobalTransactional;
+import lombok.AllArgsConstructor;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.seata.order.entity.Order;
+import org.springblade.seata.order.feign.IStorageClient;
+import org.springblade.seata.order.mapper.OrderMapper;
+import org.springblade.seata.order.service.IOrderService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+
+/**
+ * OrderServiceImpl
+ *
+ * @author Chill
+ */
+@Service
+@AllArgsConstructor
+public class OrderServiceImpl extends ServiceImpl implements IOrderService {
+
+ private IStorageClient storageClient;
+
+ @Override
+ @GlobalTransactional
+ @Transactional(rollbackFor = Exception.class)
+ public boolean createOrder(String userId, String commodityCode, Integer count) {
+ int maxCount = 100;
+ BigDecimal orderMoney = new BigDecimal(count).multiply(new BigDecimal(5));
+ Order order = new Order()
+ .setUserId(userId)
+ .setCommodityCode(commodityCode)
+ .setCount(count)
+ .setMoney(orderMoney);
+ int cnt1 = baseMapper.insert(order);
+ int cnt2 = storageClient.deduct(commodityCode, count);
+ if (cnt2 < 0) {
+ throw new ServiceException("创建订单失败");
+ } else if (count > maxCount) {
+ throw new ServiceException("超过订单最大值,创建订单失败");
+ }
+ return cnt1 > 0 && cnt2 > 0;
+ }
+
+}
diff --git a/blade-ops/blade-seata-order/src/main/resources/application-dev.yml b/blade-ops/blade-seata-order/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..ed2ec08
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/resources/application-dev.yml
@@ -0,0 +1,10 @@
+#服务器端口
+server:
+ port: 8501
+
+#数据源配置
+spring:
+ datasource:
+ url: jdbc:mysql://localhost:3306/seata_order?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
+ username: root
+ password: root
diff --git a/blade-ops/blade-seata-order/src/main/resources/registry.conf b/blade-ops/blade-seata-order/src/main/resources/registry.conf
new file mode 100644
index 0000000..da0dda8
--- /dev/null
+++ b/blade-ops/blade-seata-order/src/main/resources/registry.conf
@@ -0,0 +1,20 @@
+registry {
+ # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
+ type = "nacos"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = ""
+ cluster = "default"
+ }
+}
+
+config {
+ # file、nacos 、apollo、zk、consul、etcd3
+ type = "nacos"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = ""
+ }
+}
diff --git a/blade-ops/blade-seata-storage/README.md b/blade-ops/blade-seata-storage/README.md
new file mode 100644
index 0000000..62575a7
--- /dev/null
+++ b/blade-ops/blade-seata-storage/README.md
@@ -0,0 +1,33 @@
+-- 创建 storage库、业务表、undo_log表
+create database seata_storage;
+use seata_storage;
+
+DROP TABLE IF EXISTS `tb_storage`;
+CREATE TABLE `tb_storage` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `commodity_code` varchar(255) DEFAULT NULL,
+ `count` int(11) DEFAULT 0,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY (`commodity_code`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `undo_log`
+(
+ `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+ `branch_id` BIGINT(20) NOT NULL,
+ `xid` VARCHAR(100) NOT NULL,
+ `context` VARCHAR(128) NOT NULL,
+ `rollback_info` LONGBLOB NOT NULL,
+ `log_status` INT(11) NOT NULL,
+ `log_created` DATETIME NOT NULL,
+ `log_modified` DATETIME NOT NULL,
+ `ext` VARCHAR(100) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8;
+
+-- 初始化库存模拟数据
+INSERT INTO seata_storage.tb_storage (id, commodity_code, count) VALUES (1, 'product-1', 9999999);
+INSERT INTO seata_storage.tb_storage (id, commodity_code, count) VALUES (2, 'product-2', 0);
\ No newline at end of file
diff --git a/blade-ops/blade-seata-storage/pom.xml b/blade-ops/blade-seata-storage/pom.xml
new file mode 100644
index 0000000..c350b31
--- /dev/null
+++ b/blade-ops/blade-seata-storage/pom.xml
@@ -0,0 +1,31 @@
+
+
+
+ blade-ops
+ org.springblade
+ 2.5.0
+
+ 4.0.0
+
+ blade-seata-storage
+ ${project.artifactId}
+ ${blade.project.version}
+ jar
+
+
+
+ org.springblade
+ blade-core-boot
+ ${blade.tool.version}
+
+
+ org.springblade
+ blade-core-transaction
+ ${blade.tool.version}
+
+
+
+
+
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/SeataStorageApplication.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/SeataStorageApplication.java
new file mode 100644
index 0000000..d98ee65
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/SeataStorageApplication.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * 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.
+ */
+package org.springblade.seata.storage;
+
+import org.springblade.core.launch.BladeApplication;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springblade.core.transaction.annotation.SeataCloudApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * Storage启动器
+ *
+ * @author Chill
+ */
+@SeataCloudApplication
+@EnableFeignClients(AppConstant.BASE_PACKAGES)
+public class SeataStorageApplication {
+
+ public static void main(String[] args) {
+ BladeApplication.run("blade-seata-storage", SeataStorageApplication.class, args);
+ }
+
+}
+
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/config/StorageConfiguration.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/config/StorageConfiguration.java
new file mode 100644
index 0000000..7ac2e9e
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/config/StorageConfiguration.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ *
+ * 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.
+ */
+package org.springblade.seata.storage.config;
+
+
+import org.springblade.core.secure.registry.SecureRegistry;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * secure模块api放行配置
+ *
+ * @author Chill
+ */
+@Configuration
+public class StorageConfiguration implements WebMvcConfigurer {
+
+ @Bean
+ public SecureRegistry secureRegistry() {
+ SecureRegistry secureRegistry = new SecureRegistry();
+ secureRegistry.excludePathPatterns("/deduct/**");
+ return secureRegistry;
+ }
+
+}
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/controller/StorageController.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/controller/StorageController.java
new file mode 100644
index 0000000..0033d28
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/controller/StorageController.java
@@ -0,0 +1,30 @@
+package org.springblade.seata.storage.controller;
+
+import lombok.AllArgsConstructor;
+import org.springblade.seata.storage.service.IStorageService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * StorageController
+ *
+ * @author Chill
+ */
+@RestController
+@AllArgsConstructor
+public class StorageController {
+
+ private IStorageService storageService;
+
+ /**
+ * 减库存
+ *
+ * @param commodityCode 商品代码
+ * @param count 数量
+ */
+ @RequestMapping(path = "/deduct")
+ public int deduct(String commodityCode, Integer count) {
+ return storageService.deduct(commodityCode, count);
+ }
+
+}
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/entity/Storage.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/entity/Storage.java
new file mode 100644
index 0000000..73e4935
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/entity/Storage.java
@@ -0,0 +1,24 @@
+package org.springblade.seata.storage.entity;
+
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * storage
+ *
+ * @author Chill
+ */
+@Data
+@TableName("tb_storage")
+public class Storage implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+ private String commodityCode;
+ private Long count;
+
+}
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/mapper/StorageMapper.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/mapper/StorageMapper.java
new file mode 100644
index 0000000..800ac01
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/mapper/StorageMapper.java
@@ -0,0 +1,12 @@
+package org.springblade.seata.storage.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.seata.storage.entity.Storage;
+
+/**
+ * StorageMapper
+ *
+ * @author Chill
+ */
+public interface StorageMapper extends BaseMapper {
+}
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/mapper/StorageMapper.xml b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/mapper/StorageMapper.xml
new file mode 100644
index 0000000..c2c8a9a
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/mapper/StorageMapper.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/service/IStorageService.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/service/IStorageService.java
new file mode 100644
index 0000000..1b2fe40
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/service/IStorageService.java
@@ -0,0 +1,22 @@
+package org.springblade.seata.storage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.seata.storage.entity.Storage;
+
+/**
+ * IStorageService
+ *
+ * @author Chill
+ */
+public interface IStorageService extends IService {
+
+ /**
+ * 减库存
+ *
+ * @param commodityCode 商品代码
+ * @param count 数量
+ * @return boolean
+ */
+ int deduct(String commodityCode, int count);
+
+}
diff --git a/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/service/impl/StorageServiceImpl.java b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/service/impl/StorageServiceImpl.java
new file mode 100644
index 0000000..fc1eacc
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/java/org/springblade/seata/storage/service/impl/StorageServiceImpl.java
@@ -0,0 +1,30 @@
+package org.springblade.seata.storage.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.seata.storage.entity.Storage;
+import org.springblade.seata.storage.mapper.StorageMapper;
+import org.springblade.seata.storage.service.IStorageService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * StorageServiceImpl
+ *
+ * @author Chill
+ */
+@Service
+public class StorageServiceImpl extends ServiceImpl implements IStorageService {
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int deduct(String commodityCode, int count) {
+ Storage storage = baseMapper.selectOne(Wrappers.query().lambda().eq(Storage::getCommodityCode, commodityCode));
+ if (storage.getCount() < count) {
+ throw new RuntimeException("超过库存数,扣除失败!");
+ }
+ storage.setCount(storage.getCount() - count);
+ return baseMapper.updateById(storage);
+ }
+
+}
diff --git a/blade-ops/blade-seata-storage/src/main/resources/application-dev.yml b/blade-ops/blade-seata-storage/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..35d9cb4
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/resources/application-dev.yml
@@ -0,0 +1,10 @@
+#服务器端口
+server:
+ port: 8502
+
+#数据源配置
+spring:
+ datasource:
+ url: jdbc:mysql://localhost:3306/seata_storage?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
+ username: root
+ password: root
diff --git a/blade-ops/blade-seata-storage/src/main/resources/registry.conf b/blade-ops/blade-seata-storage/src/main/resources/registry.conf
new file mode 100644
index 0000000..da0dda8
--- /dev/null
+++ b/blade-ops/blade-seata-storage/src/main/resources/registry.conf
@@ -0,0 +1,20 @@
+registry {
+ # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
+ type = "nacos"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = ""
+ cluster = "default"
+ }
+}
+
+config {
+ # file、nacos 、apollo、zk、consul、etcd3
+ type = "nacos"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = ""
+ }
+}
diff --git a/blade-ops/pom.xml b/blade-ops/pom.xml
index 08f24af..ac572c0 100644
--- a/blade-ops/pom.xml
+++ b/blade-ops/pom.xml
@@ -5,7 +5,7 @@
SpringBlade
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
@@ -15,6 +15,8 @@
blade-admin
blade-develop
blade-resource
+ blade-seata-order
+ blade-seata-storage
diff --git a/blade-service-api/blade-desk-api/pom.xml b/blade-service-api/blade-desk-api/pom.xml
index ea6421e..e346057 100644
--- a/blade-service-api/blade-desk-api/pom.xml
+++ b/blade-service-api/blade-desk-api/pom.xml
@@ -5,7 +5,7 @@
blade-service-api
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
diff --git a/blade-service-api/blade-dict-api/pom.xml b/blade-service-api/blade-dict-api/pom.xml
index c8e15bb..3d794f7 100644
--- a/blade-service-api/blade-dict-api/pom.xml
+++ b/blade-service-api/blade-dict-api/pom.xml
@@ -5,7 +5,7 @@
blade-service-api
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
diff --git a/blade-service-api/blade-system-api/pom.xml b/blade-service-api/blade-system-api/pom.xml
index 361e93e..38b1753 100644
--- a/blade-service-api/blade-system-api/pom.xml
+++ b/blade-service-api/blade-system-api/pom.xml
@@ -5,7 +5,7 @@
blade-service-api
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
diff --git a/blade-service-api/blade-user-api/pom.xml b/blade-service-api/blade-user-api/pom.xml
index a65adc9..d034221 100644
--- a/blade-service-api/blade-user-api/pom.xml
+++ b/blade-service-api/blade-user-api/pom.xml
@@ -5,7 +5,7 @@
blade-service-api
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
diff --git a/blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/User.java b/blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/User.java
index 0e6490f..5bbe58d 100644
--- a/blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/User.java
+++ b/blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/User.java
@@ -23,7 +23,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.TenantEntity;
-import java.time.LocalDateTime;
+import java.util.Date;
/**
* 实体类
@@ -71,7 +71,7 @@ public class User extends TenantEntity {
/**
* 生日
*/
- private LocalDateTime birthday;
+ private Date birthday;
/**
* 性别
*/
diff --git a/blade-service-api/pom.xml b/blade-service-api/pom.xml
index 867a56c..04dbac8 100644
--- a/blade-service-api/pom.xml
+++ b/blade-service-api/pom.xml
@@ -5,13 +5,13 @@
SpringBlade
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
blade-service-api
${project.artifactId}
- 2.4.1
+ 2.5.0
pom
SpringBlade 微服务API集合
diff --git a/blade-service/blade-desk/pom.xml b/blade-service/blade-desk/pom.xml
index 0a60006..f4f5ec3 100644
--- a/blade-service/blade-desk/pom.xml
+++ b/blade-service/blade-desk/pom.xml
@@ -6,7 +6,7 @@
org.springblade
blade-service
- 2.4.1
+ 2.5.0
4.0.0
@@ -58,6 +58,7 @@
+
diff --git a/blade-service/blade-log/pom.xml b/blade-service/blade-log/pom.xml
index 9ae4f4f..3195d8f 100644
--- a/blade-service/blade-log/pom.xml
+++ b/blade-service/blade-log/pom.xml
@@ -5,7 +5,7 @@
blade-service
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
@@ -36,6 +36,7 @@
+
diff --git a/blade-service/blade-system/pom.xml b/blade-service/blade-system/pom.xml
index 71385bf..8b7a671 100644
--- a/blade-service/blade-system/pom.xml
+++ b/blade-service/blade-system/pom.xml
@@ -5,7 +5,7 @@
blade-service
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
@@ -45,6 +45,7 @@
+
diff --git a/blade-service/blade-user/pom.xml b/blade-service/blade-user/pom.xml
index e7dc353..6047d7d 100644
--- a/blade-service/blade-user/pom.xml
+++ b/blade-service/blade-user/pom.xml
@@ -5,7 +5,7 @@
blade-service
org.springblade
- 2.4.1
+ 2.5.0
4.0.0
@@ -46,6 +46,7 @@
+
diff --git a/blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java b/blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java
index a54e6bf..134e6d1 100644
--- a/blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java
+++ b/blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java
@@ -21,6 +21,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import org.springblade.common.constant.CommonConstant;
import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.user.entity.User;
@@ -29,7 +30,6 @@ import org.springblade.system.user.mapper.UserMapper;
import org.springblade.system.user.service.IUserService;
import org.springframework.stereotype.Service;
-import java.time.LocalDateTime;
import java.util.List;
/**
@@ -92,7 +92,7 @@ public class UserServiceImpl extends BaseServiceImpl implement
public boolean resetPassword(String userIds) {
User user = new User();
user.setPassword(DigestUtil.encrypt(CommonConstant.DEFAULT_PASSWORD));
- user.setUpdateTime(LocalDateTime.now());
+ user.setUpdateTime(DateUtil.now());
return this.update(user, Wrappers.update().lambda().in(User::getId, Func.toIntList(userIds)));
}
diff --git a/blade-service/pom.xml b/blade-service/pom.xml
index 1afe72e..7946e6e 100644
--- a/blade-service/pom.xml
+++ b/blade-service/pom.xml
@@ -7,12 +7,12 @@
org.springblade
SpringBlade
- 2.4.1
+ 2.5.0
blade-service
${project.artifactId}
- 2.4.1
+ 2.5.0
pom
SpringBlade 微服务集合
diff --git a/doc/sql/blade-mysql-update.sql b/doc/sql/blade-mysql-update.sql
deleted file mode 100644
index 3b5bcb3..0000000
--- a/doc/sql/blade-mysql-update.sql
+++ /dev/null
@@ -1,56 +0,0 @@
--- ----------------------------
--- 创建数据源配置表
--- ----------------------------
-CREATE TABLE `blade_datasource` (
- `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
- `name` varchar(100) NULL COMMENT '名称',
- `driver_class` varchar(100) NULL COMMENT '驱动类',
- `url` varchar(500) NULL COMMENT '连接地址',
- `username` varchar(50) NULL COMMENT '用户名',
- `password` varchar(50) NULL COMMENT '密码',
- `remark` varchar(255) NULL COMMENT '备注',
- `create_user` bigint(64) NULL DEFAULT NULL COMMENT '创建人',
- `create_dept` bigint(64) NULL DEFAULT NULL COMMENT '创建部门',
- `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
- `update_user` bigint(64) NULL DEFAULT NULL COMMENT '修改人',
- `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
- `status` int(2) NULL DEFAULT NULL COMMENT '状态',
- `is_deleted` int(2) NULL DEFAULT NULL COMMENT '是否已删除',
- PRIMARY KEY (`id`) USING BTREE
-) COMMENT = '数据源配置表' ;
-
--- ----------------------------
--- 插入数据源默认数据
--- ----------------------------
-INSERT INTO `blade_datasource`(`id`, `name`, `driver_class`, `url`, `username`, `password`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`) VALUES (1, 'mysql', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql://localhost:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true', 'root', 'root', 'mysql', 1, 1, '2019-08-14 11:43:06', 1, '2019-08-14 11:43:06', 1, 0);
-INSERT INTO `blade_datasource`(`id`, `name`, `driver_class`, `url`, `username`, `password`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`) VALUES (2, 'postgresql', 'org.postgresql.Driver', 'jdbc:postgresql://127.0.0.1:5432/blade', 'postgres', '123456', 'postgresql', 1, 1, '2019-08-14 11:43:41', 1, '2019-08-14 11:43:41', 1, 0);
-INSERT INTO `blade_datasource`(`id`, `name`, `driver_class`, `url`, `username`, `password`, `remark`, `create_user`, `create_dept`, `create_time`, `update_user`, `update_time`, `status`, `is_deleted`) VALUES (3, 'oracle', 'oracle.jdbc.OracleDriver', 'jdbc:oracle:thin:@127.0.0.1:49161:orcl', 'BLADE', 'blade', 'oracle', 1, 1, '2019-08-14 11:44:03', 1, '2019-08-14 11:44:03', 1, 0);
-
--- ----------------------------
--- 插入数据源菜单数据
--- ----------------------------
-INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES (17, 'datasource', '数据源管理', 'menu', '/tool/datasource', 'iconfont icon-caidanguanli', 2, 1, 0, 1, NULL, 0);
-set @parentid = (SELECT LAST_INSERT_ID());
-INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES (@parentid, 'datasource_add', '新增', 'add', '/tool/datasource/add', 'plus', 1, 2, 1, 1, NULL, 0);
-INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES (@parentid, 'datasource_edit', '修改', 'edit', '/tool/datasource/edit', 'form', 2, 2, 2, 2, NULL, 0);
-INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES (@parentid, 'datasource_delete', '删除', 'delete', '/api/blade-develop/datasource/remove', 'delete', 3, 2, 3, 3, NULL, 0);
-INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
-VALUES (@parentid, 'datasource_view', '查看', 'view', '/tool/datasource/view', 'file-text', 4, 2, 2, 2, NULL, 0);
-
--- ----------------------------
--- 代码生成表增加数据源字段
--- ----------------------------
-ALTER TABLE `blade_code`
- ADD COLUMN `datasource_id` bigint(64) NULL COMMENT '数据源主键' AFTER `id`,
- ADD COLUMN `base_mode` int(2) NULL COMMENT '基础业务模式' AFTER `package_name`,
- ADD COLUMN `wrap_mode` int(2) NULL COMMENT '包装器模式' AFTER `base_mode`;
-
-
--- ----------------------------
--- 代码生成记录增加数据源字段
--- ----------------------------
-UPDATE `blade_code` SET `datasource_id` = 1, `base_mode` = 1, `wrap_mode` = 1 WHERE `id` = 1;
diff --git a/pom.xml b/pom.xml
index 4535882..adbe9a4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,17 +5,17 @@
org.springblade
SpringBlade
- 2.4.1
+ 2.5.0
pom
- 2.4.1
- 2.4.1
+ 2.5.0
+ 2.5.0
1.8
2.9.2
1.5.21
- 1.9.4
+ 1.9.6
3.1.2
4.0.1
1.6.0
@@ -23,8 +23,8 @@
2.1.0.RELEASE
2.1.5
- 2.1.7.RELEASE
- Greenwich.SR2
+ 2.1.8.RELEASE
+ Greenwich.SR3
Cairo-SR8
diff --git a/script/docker/.env b/script/docker/.env
index 7f48f6e..b109b62 100644
--- a/script/docker/.env
+++ b/script/docker/.env
@@ -1,2 +1,2 @@
REGISTER=192.168.0.157/blade
-TAG=2.4.1
+TAG=2.5.0