Browse Source

Merge branch 'dev' of ssh://10.10.100.21/source/saas-platform into dev

zhuth 7 years ago
parent
commit
826c4f1305
24 changed files with 632 additions and 32 deletions
  1. 11 1
      base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/CompanyDTO.java
  2. 65 0
      base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/CompanyRegDTO.java
  3. 41 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/AccountController.java
  4. 18 5
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/CompanyController.java
  5. 16 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/mapper/AccountMapper.java
  6. 9 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/po/Account.java
  7. 14 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/service/AccountService.java
  8. 16 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/service/impl/AccountServiceImpl.java
  9. 1 1
      base-servers/account/account-server/src/main/resources/mapper/AccountCompanyMapper.xml
  10. 17 4
      base-servers/account/account-server/src/main/resources/mapper/AccountMapper.xml
  11. 118 0
      base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/controller/AccountControllerTest.java
  12. 75 0
      base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/controller/CompanyControllerTest.java
  13. 8 8
      base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/service/AccountServiceTest.java
  14. 4 6
      base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/service/CompanyServiceTest.java
  15. 22 0
      framework/core/src/main/java/com/usoftchina/saas/base/Result.java
  16. 1 0
      framework/core/src/main/java/com/usoftchina/saas/exception/ExceptionCode.java
  17. 12 0
      framework/core/src/main/java/com/usoftchina/saas/utils/JsonUtils.java
  18. 17 1
      framework/server-starter/src/main/java/com/usoftchina/saas/server/ServerAutoConfiguration.java
  19. 22 0
      framework/test-starter/pom.xml
  20. 118 0
      framework/test-starter/src/main/java/com.usoftchina.saas.test/BaseControllerTest.java
  21. 16 0
      framework/test-starter/src/main/java/com.usoftchina.saas.test/TestConstant.java
  22. 3 3
      framework/test-starter/src/main/java/com.usoftchina.saas.test/TestContextListener.java
  23. 1 1
      framework/test-starter/src/main/resources/META-INF/spring.factories
  24. 7 2
      script/mysql/init/account.sql

+ 11 - 1
base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/CompanyDTO.java

@@ -10,6 +10,7 @@ import java.io.Serializable;
  */
 @ApiModel(value = "Company", description = "公司信息")
 public class CompanyDTO implements Serializable{
+    private Long id;
     /**
      * 唯一名称
      */
@@ -21,6 +22,14 @@ public class CompanyDTO implements Serializable{
     private String address;
     private String logoUrl;
 
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
     public String getName() {
         return name;
     }
@@ -56,7 +65,8 @@ public class CompanyDTO implements Serializable{
     @Override
     public String toString() {
         return "CompanyDTO{" +
-                "name='" + name + '\'' +
+                "id=" + id +
+                ", name='" + name + '\'' +
                 ", businessCode='" + businessCode + '\'' +
                 ", address='" + address + '\'' +
                 ", logoUrl='" + logoUrl + '\'' +

+ 65 - 0
base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/CompanyRegDTO.java

@@ -0,0 +1,65 @@
+package com.usoftchina.saas.account.dto;
+
+import io.swagger.annotations.ApiModel;
+
+import java.io.Serializable;
+
+/**
+ * @author yingp
+ * @date 2018/10/2
+ */
+@ApiModel(value = "CompanyReg", description = "公司注册信息")
+public class CompanyRegDTO implements Serializable{
+    /**
+     * 唯一名称
+     */
+    private String name;
+    /**
+     * 商业登记证号
+     */
+    private String businessCode;
+    private String address;
+    private String logoUrl;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getBusinessCode() {
+        return businessCode;
+    }
+
+    public void setBusinessCode(String businessCode) {
+        this.businessCode = businessCode;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public String getLogoUrl() {
+        return logoUrl;
+    }
+
+    public void setLogoUrl(String logoUrl) {
+        this.logoUrl = logoUrl;
+    }
+
+    @Override
+    public String toString() {
+        return "CompanyRegDTO{" +
+                "name='" + name + '\'' +
+                ", businessCode='" + businessCode + '\'' +
+                ", address='" + address + '\'' +
+                ", logoUrl='" + logoUrl + '\'' +
+                '}';
+    }
+}

+ 41 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/AccountController.java

@@ -53,6 +53,7 @@ public class AccountController {
         }
 
         account = BeanMapper.map(accountRegDTO, Account.class);
+        account.setEnabled(true);
         account.setSalt(account.getMobile());
         account.setPassword(accountService.getEncryptedPassword(account.getPassword(), account.getSalt()));
         accountService.save(account);
@@ -74,6 +75,10 @@ public class AccountController {
             return Result.error(ExceptionCode.USER_NOT_EXIST);
         }
 
+        if (!account.isEnabled()) {
+            return Result.error(ExceptionCode.USER_NOT_ENABLE);
+        }
+
         boolean checked = accountService.checkPwd(account, password);
         if (!checked) {
             return Result.error(ExceptionCode.USER_PWD_ERROR);
@@ -171,4 +176,40 @@ public class AccountController {
         accountService.unbindRole(accountId, roleId);
         return Result.success();
     }
+
+    /**
+     * 账户禁用
+     *
+     * @param accountId
+     * @return
+     */
+    @PostMapping("/disable")
+    public Result disableAccount(@RequestParam long accountId) {
+        accountService.disable(accountId);
+        return Result.success();
+    }
+
+    /**
+     * 账户启用
+     *
+     * @param accountId
+     * @return
+     */
+    @PostMapping("/enable")
+    public Result enableAccount(@RequestParam long accountId) {
+        accountService.enable(accountId);
+        return Result.success();
+    }
+
+    /**
+     * 账户删除
+     *
+     * @param accountId
+     * @return
+     */
+    @PostMapping("/delete")
+    public Result deleteAccount(@RequestParam long accountId) {
+        accountService.removeByPrimaryKey(accountId);
+        return Result.success();
+    }
 }

+ 18 - 5
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/CompanyController.java

@@ -1,6 +1,7 @@
 package com.usoftchina.saas.account.controller;
 
 import com.usoftchina.saas.account.dto.CompanyDTO;
+import com.usoftchina.saas.account.dto.CompanyRegDTO;
 import com.usoftchina.saas.account.po.Company;
 import com.usoftchina.saas.account.service.CompanyService;
 import com.usoftchina.saas.base.Result;
@@ -23,22 +24,22 @@ public class CompanyController {
     /**
      * 注册
      *
-     * @param companyDTO
+     * @param companyRegDTO
      * @return
      */
     @PostMapping("/register")
-    public Result register(@RequestBody CompanyDTO companyDTO) {
+    public Result register(@RequestBody CompanyRegDTO companyRegDTO) {
         // 判断是否已注册
-        Company company = companyService.findByName(companyDTO.getName());
+        Company company = companyService.findByName(companyRegDTO.getName());
         if (null != company) {
             return Result.error(ExceptionCode.COMPANY_NAME_EXIST);
         }
-        company = companyService.findByBusinessCode(companyDTO.getBusinessCode());
+        company = companyService.findByBusinessCode(companyRegDTO.getBusinessCode());
         if (null != company) {
             return Result.error(ExceptionCode.COMPANY_CODE_EXIST);
         }
 
-        company = BeanMapper.map(companyDTO, Company.class);
+        company = BeanMapper.map(companyRegDTO, Company.class);
         companyService.save(company);
 
         return Result.success();
@@ -75,4 +76,16 @@ public class CompanyController {
         }
         return Result.error(ExceptionCode.COMPANY_NOT_EXIST);
     }
+
+    /**
+     * 删除
+     *
+     * @param companyId
+     * @return
+     */
+    @PostMapping("/delete")
+    public Result delete(@RequestParam Long companyId) {
+        companyService.removeByPrimaryKey(companyId);
+        return Result.success();
+    }
 }

+ 16 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/mapper/AccountMapper.java

@@ -24,6 +24,14 @@ public interface AccountMapper {
      */
     int insertSelective(Account account);
 
+    /**
+     * 按ID查找
+     *
+     * @param id
+     * @return
+     */
+    Account selectByPrimaryKey(@Param("id") Long id);
+
     /**
      * 按用户名查找
      *
@@ -55,4 +63,12 @@ public interface AccountMapper {
      * @return
      */
     int deleteByPrimaryKey(@Param("id") Long id);
+
+    /**
+     * 更新启用状态
+     *
+     * @param id
+     * @param enabled
+     */
+    void updateEnabled(@Param("id") Long id, @Param("enabled") Boolean enabled);
 }

+ 9 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/po/Account.java

@@ -21,6 +21,7 @@ public class Account implements Serializable {
      * 账号类型 0 - 管理员
      */
     private Integer type;
+    private boolean enabled;
     protected Date createTime;
     protected long creatorId;
     protected Date updateTime;
@@ -82,6 +83,14 @@ public class Account implements Serializable {
         this.type = type;
     }
 
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
     public Long getId() {
         return id;
     }

+ 14 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/service/AccountService.java

@@ -97,4 +97,18 @@ public interface AccountService {
      */
     boolean removeByPrimaryKey(Long id);
 
+    /**
+     * 禁用
+     *
+     * @param accountId
+     */
+    void disable(Long accountId);
+
+    /**
+     * 启用
+     *
+     * @param accountId
+     */
+    void enable(Long accountId);
+
 }

+ 16 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/service/impl/AccountServiceImpl.java

@@ -88,4 +88,20 @@ public class AccountServiceImpl implements AccountService {
         accountCompanyMapper.deleteByAccountId(id);
         return accountMapper.deleteByPrimaryKey(id) > 0;
     }
+
+    @Override
+    public void enable(Long accountId) {
+        Account account = accountMapper.selectByPrimaryKey(accountId);
+        if (null != account && !account.isEnabled()) {
+            accountMapper.updateEnabled(accountId, true);
+        }
+    }
+
+    @Override
+    public void disable(Long accountId) {
+        Account account = accountMapper.selectByPrimaryKey(accountId);
+        if (null != account && account.isEnabled()) {
+            accountMapper.updateEnabled(accountId, false);
+        }
+    }
 }

+ 1 - 1
base-servers/account/account-server/src/main/resources/mapper/AccountCompanyMapper.xml

@@ -5,7 +5,7 @@
         insert into ac_account_company(account_id,company_id) values (#{accountId}, #{companyId})
     </insert>
     <delete id="delete">
-        delete from ac_account_company where account_id=#{accountId} and companyId=#{companyId}
+        delete from ac_account_company where account_id=#{accountId} and company_id=#{companyId}
     </delete>
     <delete id="deleteByAccountId" parameterType="java.lang.Long">
         delete from ac_account_company where account_id=#{accountId}

+ 17 - 4
base-servers/account/account-server/src/main/resources/mapper/AccountMapper.xml

@@ -10,18 +10,19 @@
         <result column="email" jdbcType="VARCHAR" property="email"/>
         <result column="mobile" jdbcType="VARCHAR" property="mobile"/>
         <result column="type" jdbcType="INTEGER" property="type"/>
+        <result column="enabled" jdbcType="BOOLEAN" property="enabled"/>
         <result column="creator_id" jdbcType="BIGINT" property="creatorId"/>
         <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
         <result column="updater_id" jdbcType="BIGINT" property="updaterId"/>
         <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
     </resultMap>
     <sql id="baseColumns">
-        id,username,password,salt,realname,email,mobile,type,creator_id,create_time,updater_id,update_time
+        id,username,password,salt,realname,email,mobile,type,enabled,creator_id,create_time,updater_id,update_time
     </sql>
     <insert id="insert" parameterType="com.usoftchina.saas.account.po.Account">
-        insert into ac_account(username,password,salt,realname,email,mobile,type,creator_id,create_time,updater_id,update_time)
+        insert into ac_account(username,password,salt,realname,email,mobile,type,enabled,creator_id,create_time,updater_id,update_time)
         values (#{username,jdbcType=VARCHAR},#{password,jdbcType=VARCHAR}, #{salt,jdbcType=VARCHAR},
-        #{realname,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{mobile,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER},
+        #{realname,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{mobile,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, #{enabled,jdbcType=BOOLEAN},
         #{creatorId,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP}, #{updaterId,jdbcType=BIGINT}, #{updateTime,jdbcType=TIMESTAMP})
     </insert>
     <insert id="insertSelective" parameterType="com.usoftchina.saas.account.po.Account">
@@ -48,6 +49,9 @@
             <if test="type != null">
                 type,
             </if>
+            <if test="enabled != null">
+                enabled,
+            </if>
             <if test="creatorId != null">
                 creator_id,
             </if>
@@ -81,7 +85,10 @@
                 #{mobile,jdbcType=VARCHAR},
             </if>
             <if test="type != null">
-                #{type,jdbcType=INT},
+                #{type,jdbcType=INTEGER},
+            </if>
+            <if test="enabled != null">
+                #{enabled,jdbcType=BOOLEAN},
             </if>
             <if test="creatorId != null">
                 #{creatorId,jdbcType=BIGINT},
@@ -97,6 +104,9 @@
             </if>
         </trim>
     </insert>
+    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        select <include refid="baseColumns"/> from ac_account where id=#{id}
+    </select>
     <select id="selectByUsername" parameterType="java.lang.String" resultMap="BaseResultMap">
         select <include refid="baseColumns"/> from ac_account where username=#{username}
     </select>
@@ -109,4 +119,7 @@
     <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
         delete from ac_account where id=#{id}
     </delete>
+    <update id="updateEnabled">
+        update ac_account set enabled=#{enabled,jdbcType=BOOLEAN} where id=#{id,jdbcType=BIGINT}
+    </update>
 </mapper>

+ 118 - 0
base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/controller/AccountControllerTest.java

@@ -0,0 +1,118 @@
+package com.usoftchina.saas.account.controller;
+
+import com.usoftchina.saas.account.constant.AccountType;
+import com.usoftchina.saas.account.dto.AccountDTO;
+import com.usoftchina.saas.account.dto.AccountRegDTO;
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.test.BaseControllerTest;
+import com.usoftchina.saas.test.TestConstant;
+import org.junit.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MvcResult;
+//import org.springframework.transaction.annotation.Transactional;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+//@Transactional
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class AccountControllerTest extends BaseControllerTest {
+
+    private final String mobile = "13500000000";
+
+    private final String password = "select111***";
+
+    @Test
+    public void testA_register() throws Exception {
+        AccountRegDTO accountRegDTO = new AccountRegDTO();
+        accountRegDTO.setUsername(mobile);
+        accountRegDTO.setMobile(mobile);
+        accountRegDTO.setEmail("jack-ma@mxhichina.com");
+        accountRegDTO.setRealname("Jack Ma");
+        accountRegDTO.setPassword(password);
+        accountRegDTO.setType(AccountType.ADMIN.getType());
+
+        mockMvc.perform(requestBody("/account/register", accountRegDTO))
+                .andExpect(isSuccess());
+    }
+
+    @Test
+    public void testB_validByUsernameAndPwd() throws Exception {
+        MvcResult mvcResult = mockMvc.perform(get("/account/pwd/check")
+                .param("username", mobile)
+                .param("password", password))
+                .andExpect(isSuccess())
+                .andReturn();
+        Result<AccountDTO> result = result(mvcResult, AccountDTO.class);
+        System.out.println(result.getData());
+        Assert.assertEquals(result.getData().getMobile(), mobile);
+    }
+
+    @Test
+    public void testC_validByUsernameAndErrorPwd() throws Exception {
+        mockMvc.perform(get("/account/pwd/check")
+                .param("username", mobile)
+                .param("password", "1"))
+                .andExpect(isFail());
+    }
+
+    @Test
+    public void testD_getAccount() throws Exception {
+        AccountDTO accountDTO = getAccountDTO();
+        Assert.assertEquals(accountDTO.getMobile(), mobile);
+    }
+
+    private AccountDTO getAccountDTO() throws Exception {
+        MvcResult mvcResult = mockMvc.perform(get("/account")
+                .param("username", mobile))
+                .andExpect(isSuccess())
+                .andReturn();
+        Result<AccountDTO> result = result(mvcResult, AccountDTO.class);
+        System.out.println(result.getData());
+        return result.getData();
+    }
+
+    @Test
+    public void testE_bindCompany() throws Exception {
+        AccountDTO accountDTO = getAccountDTO();
+        mockMvc.perform(post("/account/bind/company")
+                .param("accountId", String.valueOf(accountDTO.getId()))
+                .param("companyId", String.valueOf(TestConstant.DEFAULT_COMPANY_ID)))
+                .andExpect(isSuccess());
+    }
+
+    @Test
+    public void testF_unbindCompany() throws Exception {
+        AccountDTO accountDTO = getAccountDTO();
+        mockMvc.perform(post("/account/unbind/company")
+                .param("accountId", String.valueOf(accountDTO.getId()))
+                .param("companyId", String.valueOf(TestConstant.DEFAULT_COMPANY_ID)))
+                .andExpect(isSuccess());
+    }
+
+    @Test
+    public void testG_disableAccount() throws Exception {
+        AccountDTO accountDTO = getAccountDTO();
+        mockMvc.perform(post("/account/disable")
+                .param("accountId", String.valueOf(accountDTO.getId())))
+                .andExpect(isSuccess());
+    }
+
+    @Test
+    public void testH_enableAccount() throws Exception {
+        AccountDTO accountDTO = getAccountDTO();
+        mockMvc.perform(post("/account/enable")
+                .param("accountId", String.valueOf(accountDTO.getId())))
+                .andExpect(isSuccess());
+    }
+
+    @Test
+    public void testI_deleteAccount() throws Exception {
+        AccountDTO accountDTO = getAccountDTO();
+        mockMvc.perform(post("/account/delete")
+                .param("accountId", String.valueOf(accountDTO.getId())))
+                .andExpect(isSuccess());
+    }
+}

+ 75 - 0
base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/controller/CompanyControllerTest.java

@@ -0,0 +1,75 @@
+package com.usoftchina.saas.account.controller;
+
+import com.usoftchina.saas.account.dto.CompanyDTO;
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.test.BaseControllerTest;
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MvcResult;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class CompanyControllerTest extends BaseControllerTest {
+
+    private final String name = "spring.test";
+    private final String businessCode = "T00000000000000000";
+
+    @Test
+    public void testA_register() throws Exception {
+        CompanyDTO companyDTO = new CompanyDTO();
+        companyDTO.setName(name);
+        companyDTO.setBusinessCode(businessCode);
+        companyDTO.setAddress("深圳市南山区粤海街道高新技术产业园科技南五路英唐大厦六楼");
+        companyDTO.setLogoUrl("https://co-image.qichacha.com/CompanyImage/104eb3c232bbac93393a5e204d6a47d1.jpg?x-oss-process=style/qcc_cmp");
+
+        mockMvc.perform(requestBody("/company/register", companyDTO))
+                .andExpect(isSuccess());
+    }
+
+    @Test
+    public void testB_getByName() throws Exception {
+        CompanyDTO companyDTO = getByName();
+        Assert.assertEquals(companyDTO.getBusinessCode(), businessCode);
+    }
+
+    private CompanyDTO getByName() throws Exception {
+        MvcResult mvcResult = mockMvc.perform(get("/company")
+                .param("name", name))
+                .andExpect(isSuccess())
+                .andReturn();
+        Result<CompanyDTO> result = result(mvcResult, CompanyDTO.class);
+        System.out.println(result.getData());
+        return result.getData();
+    }
+
+    private CompanyDTO getByBusinessCode() throws Exception {
+        MvcResult mvcResult = mockMvc.perform(get("/company")
+                .param("businessCode", businessCode))
+                .andExpect(isSuccess())
+                .andReturn();
+        Result<CompanyDTO> result = result(mvcResult, CompanyDTO.class);
+        System.out.println(result.getData());
+        return result.getData();
+    }
+
+    @Test
+    public void testC_getByBusinessCode() throws Exception {
+        CompanyDTO companyDTO = getByBusinessCode();
+        Assert.assertEquals(companyDTO.getName(), name);
+    }
+
+    @Test
+    public void testD_delete() throws Exception {
+        CompanyDTO companyDTO = getByName();
+        mockMvc.perform(post("/company/delete")
+                .param("companyId", String.valueOf(companyDTO.getId())))
+                .andExpect(isSuccess());
+    }
+
+}

+ 8 - 8
base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/service/AccountServiceTest.java

@@ -2,18 +2,18 @@ package com.usoftchina.saas.account.service;
 
 import com.usoftchina.saas.account.constant.AccountType;
 import com.usoftchina.saas.account.po.Account;
-import org.junit.Assert;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
+import org.junit.*;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
+//import org.springframework.transaction.annotation.Transactional;
 
 @RunWith(SpringRunner.class)
 @SpringBootTest
-@FixMethodOrder(MethodSorters.JVM)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+//@Transactional
 public class AccountServiceTest {
 
     @Autowired
@@ -24,12 +24,12 @@ public class AccountServiceTest {
     private final String password = "select111***";
 
     @Test
-    public void save() throws Exception {
+    public void testA_save() throws Exception {
         Account account = new Account();
         account.setMobile(mobile);
         account.setUsername(mobile);
         account.setSalt(mobile);
-        account.setEmail("mayun@mxhichina.com");
+        account.setEmail("jack-ma@mxhichina.com");
         account.setPassword(accountService.getEncryptedPassword(password, account.getSalt()));
         account.setRealname("Jack Ma");
         account.setType(AccountType.ADMIN.getType());
@@ -39,7 +39,7 @@ public class AccountServiceTest {
     }
 
     @Test
-    public void checkPwd() throws Exception {
+    public void testB_checkPwd() throws Exception {
         Account account = accountService.findByMobile(mobile);
         Assert.assertNotNull(account);
         boolean checked = accountService.checkPwd(account, password);
@@ -47,7 +47,7 @@ public class AccountServiceTest {
     }
 
     @Test
-    public void removeByPrimaryKey() throws Exception {
+    public void testC_removeByPrimaryKey() throws Exception {
         Account account = accountService.findByMobile(mobile);
         Assert.assertNotNull(account);
         boolean removed = accountService.removeByPrimaryKey(account.getId());

+ 4 - 6
base-servers/account/account-server/src/test/java/com/usoftchina/saas/account/service/CompanyServiceTest.java

@@ -1,9 +1,7 @@
 package com.usoftchina.saas.account.service;
 
 import com.usoftchina.saas.account.po.Company;
-import org.junit.Assert;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
+import org.junit.*;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -16,7 +14,7 @@ import org.springframework.test.context.junit4.SpringRunner;
  */
 @RunWith(SpringRunner.class)
 @SpringBootTest
-@FixMethodOrder(MethodSorters.JVM)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class CompanyServiceTest {
 
     @Autowired
@@ -25,7 +23,7 @@ public class CompanyServiceTest {
     private final String name = "spring.test";
 
     @Test
-    public void save() {
+    public void testA_save() {
         Company company = new Company();
         company.setName(name);
         company.setBusinessCode("T00000000000000000");
@@ -37,7 +35,7 @@ public class CompanyServiceTest {
     }
 
     @Test
-    public void removeByPrimaryKey() {
+    public void testB_removeByPrimaryKey() {
         Company company = companyService.findByName(name);
         Assert.assertNotNull(company);
         boolean removed = companyService.removeByPrimaryKey(company.getId());

+ 22 - 0
framework/core/src/main/java/com/usoftchina/saas/base/Result.java

@@ -1,9 +1,13 @@
 package com.usoftchina.saas.base;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.usoftchina.saas.exception.BaseException;
 import com.usoftchina.saas.exception.BaseExceptionCode;
+import com.usoftchina.saas.utils.JsonUtils;
+import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
 
 import java.io.Serializable;
+import java.lang.reflect.Type;
 
 /**
  * 结果
@@ -122,4 +126,22 @@ public class Result<T> implements Serializable {
         result.setMessage(e.getMessage());
         return result;
     }
+
+    /**
+     * json字符串转换Result对象
+     *
+     * @param jsonString
+     * @param <T>
+     * @return
+     */
+    public static <T> Result<T> fromJsonString(String jsonString, Class<T> targetCls) {
+        Type[] types = new Type[]{targetCls};
+        final ParameterizedTypeImpl type = ParameterizedTypeImpl.make(Result.class, types, Result.class.getDeclaringClass());
+        return JsonUtils.fromJsonString(jsonString, new TypeReference<Result<T>>() {
+            @Override
+            public Type getType() {
+                return type;
+            }
+        });
+    }
 }

+ 1 - 0
framework/core/src/main/java/com/usoftchina/saas/exception/ExceptionCode.java

@@ -32,6 +32,7 @@ public enum ExceptionCode implements BaseExceptionCode {
     USER_PWD_ERROR(53003, "密码错误"),
     USER_PWD_NOT_EQUALS(53004, "密码与确认密码不一致"),
     USER_NOT_EXIST(53005, "用户不存在"),
+    USER_NOT_ENABLE(53006, "用户禁止使用"),
 
     // 文件相关
     FOLDER_NULL(55000, "文件夹为空"),

+ 12 - 0
framework/core/src/main/java/com/usoftchina/saas/utils/JsonUtils.java

@@ -1,5 +1,6 @@
 package com.usoftchina.saas.utils;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.springframework.util.StringUtils;
 
@@ -29,4 +30,15 @@ public class JsonUtils {
             return null;
         }
     }
+
+    public static <T> T fromJsonString(String json, TypeReference valueTypeRef) {
+        if (StringUtils.isEmpty(json)) {
+            return null;
+        }
+        try {
+            return mapper.readValue(json, valueTypeRef);
+        } catch (Exception e) {
+            return null;
+        }
+    }
 }

+ 17 - 1
framework/server-starter/src/main/java/com/usoftchina/saas/server/ServerAutoConfiguration.java

@@ -1,14 +1,20 @@
 package com.usoftchina.saas.server;
 
+import com.usoftchina.saas.server.error.ServletErrorUtils;
+import com.usoftchina.saas.server.error.UnCaughtErrorFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.lang.Nullable;
 import org.springframework.web.servlet.HandlerExceptionResolver;
 import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.util.NestedServletException;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 
 /**
  * @author yingp
@@ -18,13 +24,23 @@ import javax.servlet.http.HttpServletResponse;
 @ComponentScan(basePackages = {"com.usoftchina.saas.server"})
 public class ServerAutoConfiguration {
 
+    private Logger logger = LoggerFactory.getLogger(UnCaughtErrorFilter.class);
+
     @Bean
     public HandlerExceptionResolver handlerExceptionResolver() {
         return new HandlerExceptionResolver(){
             @Nullable
             @Override
             public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object o, Exception e) {
-                System.err.println("############" + request.getRequestURI() + "#" + response.getStatus());
+                Throwable cause = e;
+                if (e instanceof NestedServletException) {
+                    cause = ((NestedServletException) e).getRootCause();
+                }
+                logger.error(ServletErrorUtils.buildMessage(request, cause), cause);
+                try {
+                    ServletErrorUtils.writerErrorResult(response, cause);
+                } catch (IOException ex) {
+                }
                 return null;
             }
         };

+ 22 - 0
framework/test-starter/pom.xml

@@ -21,5 +21,27 @@
             <groupId>com.usoftchina.saas</groupId>
             <artifactId>core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 </project>

+ 118 - 0
framework/test-starter/src/main/java/com.usoftchina.saas.test/BaseControllerTest.java

@@ -0,0 +1,118 @@
+package com.usoftchina.saas.test;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.utils.JsonUtils;
+import org.junit.Before;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultMatcher;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
+
+/**
+ * @author yingp
+ * @date 2018/10/23
+ */
+public abstract class BaseControllerTest {
+    @Autowired
+    protected WebApplicationContext context;
+
+    protected MockMvc mockMvc;
+
+    @Before
+    public void setup() {
+        this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
+                .alwaysDo(print())
+                .alwaysExpect(isOk())
+                .alwaysExpect(isJson())
+                .build();
+    }
+
+    /**
+     * GET请求
+     *
+     * @param urlTemplate
+     * @return
+     */
+    public static MockHttpServletRequestBuilder get(String urlTemplate) {
+        return MockMvcRequestBuilders.get(urlTemplate);
+    }
+
+    /**
+     * POST form方式请求
+     *
+     * @param urlTemplate
+     * @return
+     */
+    public static MockHttpServletRequestBuilder post(String urlTemplate) {
+        return MockMvcRequestBuilders.post(urlTemplate);
+    }
+
+    /**
+     * POST Payload方式请求,使用@RequestBody注解情况下
+     *
+     * @param object
+     * @return
+     */
+    public static MockHttpServletRequestBuilder requestBody(String urlTemplate, Object object) {
+        return post(urlTemplate).contentType(MediaType.APPLICATION_JSON_UTF8)
+                .content(JsonUtils.toJsonString(object));
+    }
+
+    /**
+     * 是否返回 http status: 200
+     *
+     * @return
+     */
+    public static ResultMatcher isOk() {
+        return status().isOk();
+    }
+
+    /**
+     * 是否返回json格式
+     *
+     * @return
+     */
+    public static ResultMatcher isJson() {
+        return content().contentType(MediaType.APPLICATION_JSON_UTF8);
+    }
+
+    /**
+     * 是否执行成功 {"success": true}
+     *
+     * @return
+     */
+    public static ResultMatcher isSuccess() {
+        return jsonPath("success").value(true);
+    }
+
+    /**
+     * 是否执行失败 {"success": false}
+     *
+     * @return
+     */
+    public static ResultMatcher isFail() {
+        return jsonPath("success").value(false);
+    }
+
+    /**
+     * Result转换
+     *
+     * @param mvcResult
+     * @param <T>
+     * @return
+     * @throws Exception
+     */
+    public static <T> Result<T> result(MvcResult mvcResult, Class<T> targetCls) throws Exception {
+        String content = mvcResult.getResponse().getContentAsString();
+        return Result.fromJsonString(content, targetCls);
+    }
+
+}

+ 16 - 0
framework/test-starter/src/main/java/com.usoftchina.saas.test/TestConstant.java

@@ -0,0 +1,16 @@
+package com.usoftchina.saas.test;
+
+/**
+ * @author yingp
+ * @date 2018/10/22
+ */
+public class TestConstant {
+    /**
+     * 默认企业ID
+     */
+    public static final long DEFAULT_COMPANY_ID = 1;
+    /**
+     * 默认账户ID
+     */
+    public static final long DEFAULT_ACCOUNT_ID = 1;
+}

+ 3 - 3
framework/test-starter/src/main/java/com.usoftchina.saas.test/DefaultContextHolderListener.java → framework/test-starter/src/main/java/com.usoftchina.saas.test/TestContextListener.java

@@ -8,11 +8,11 @@ import org.springframework.test.context.support.AbstractTestExecutionListener;
  * @author yingp
  * @date 2018/10/22
  */
-public class DefaultContextHolderListener extends AbstractTestExecutionListener {
+public class TestContextListener extends AbstractTestExecutionListener {
     @Override
     public void beforeTestClass(TestContext testContext) throws Exception {
         // 设置测试环境默认用户
-        BaseContextHolder.setCompanyId(1);
-        BaseContextHolder.setUserId(1);
+        BaseContextHolder.setCompanyId(TestConstant.DEFAULT_COMPANY_ID);
+        BaseContextHolder.setUserId(TestConstant.DEFAULT_ACCOUNT_ID);
     }
 }

+ 1 - 1
framework/test-starter/src/main/resources/META-INF/spring.factories

@@ -1,3 +1,3 @@
 # Test Execution Listeners
 org.springframework.test.context.TestExecutionListener=\
-com.usoftchina.saas.test.DefaultContextHolderListener
+com.usoftchina.saas.test.TestContextListener

+ 7 - 2
script/mysql/init/account.sql

@@ -22,6 +22,7 @@ create table `ac_account` (
   email varchar(100) comment '邮箱',
   mobile varchar(100) not null comment '手机号',
   type int comment '账户类型 0, 1',
+  enabled bool comment '是否启用',
   creator_id int unsigned,
   create_time datetime,
   updater_id int unsigned,
@@ -71,12 +72,16 @@ create table `ac_role_resource` (
   resource_id int unsigned
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色绑定资源';
 
-insert into ac_account(id,username,password,salt,realname,email,mobile,type,
+insert into ac_account(id,username,password,salt,realname,email,mobile,type,enabled,
                        creator_id,create_time,updater_id,update_time)
 values (1,'18888888888','3e8451e274a8ee847872194e584a4145','18888888888','Administrator',
-          'admin@usoftchina.com', '18888888888', 0, 1, now(), 1, now());
+          'admin@usoftchina.com', '18888888888', 0, 1, 1, now(), 1, now());
 
 insert into ac_company(name, business_code, address, logo_url, creator_id, create_time, updater_id, update_time)
 values ('测试账套', '000000000000000000','深圳市南山区粤海街道高新技术产业园科技南五路英唐大厦六楼',
         'https://co-image.qichacha.com/CompanyImage/104eb3c232bbac93393a5e204d6a47d1.jpg?x-oss-process=style/qcc_cmp',
         1, now(), 1, now());
+
+insert into ac_account_company(account_id, company_id) values (1, 1);
+
+