商品进销存管理系统、ERP系统源码

【实例简介】

采用SpringBoot、HTML、JqueryUI、mysql实现的一整套进销存ERP系统,功能比较齐全,能立刻部署运行支持普通公司的ERP运营,附带测试使用的数据库,后管默认登录账号:admin 密码:123456

文件:590m.com/f/25127180-488778732-3b5ac3(访问密码:551685)

【实例截图】

【核心代码】

package com.jsh.erp.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.jsh.erp.constants.BusinessConstants; import com.jsh.erp.constants.ExceptionConstants; import com.jsh.erp.datasource.entities.Account; import com.jsh.erp.datasource.vo.AccountVo4InOutList; import com.jsh.erp.exception.BusinessRunTimeException; import com.jsh.erp.service.account.AccountService; import com.jsh.erp.utils.BaseResponseInfo; import com.jsh.erp.utils.ErpInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.jsh.erp.utils.ResponseJsonUtil.returnJson; /** * @author jishenghua 752718920 / @RestController @RequestMapping(value = “/account”) public class AccountController { private Logger logger = LoggerFactory.getLogger(AccountController.class); @Resource private AccountService accountService; /* * 查找结算账户信息-下拉框 * @param request * @return / @GetMapping(value = “/findBySelect”) public String findBySelect(HttpServletRequest request) throws Exception {

String res = null; try {

List dataList = accountService.findBySelect(); //存放数据json数组 JSONArray dataArray = new JSONArray(); if (null != dataList) { for (Account account : dataList) {

JSONObject item = new JSONObject();

item.put(“Id”, account.getId()); //结算账户名称 item.put(“AccountName”, account.getName());

dataArray.add(item);

}

}

res = dataArray.toJSONString();

} catch(Exception e){

e.printStackTrace();

res = “获取数据失败”;

} return res;

} /* * 获取所有结算账户 * @param request * @return / @GetMapping(value = “/getAccount”) public BaseResponseInfo getAccount(HttpServletRequest request) throws Exception {

BaseResponseInfo res = new BaseResponseInfo();

Map map = new HashMap(); try {

List accountList = accountService.getAccount();

map.put(“accountList”, accountList);

res.code = 200;

res.data = map;

} catch(Exception e){

e.printStackTrace();

res.code = 500;

res.data = “获取数据失败”;

} return res;

} /* * 账户流水信息 * @param currentPage * @param pageSize * @param accountId * @param initialAmount * @param request * @return / @GetMapping(value = “/findAccountInOutList”) public BaseResponseInfo findAccountInOutList(@RequestParam(“currentPage”) Integer currentPage, @RequestParam(“pageSize”) Integer pageSize, @RequestParam(“accountId”) Long accountId, @RequestParam(“initialAmount”) BigDecimal initialAmount,

HttpServletRequest request) throws Exception{

BaseResponseInfo res = new BaseResponseInfo();

Map map = new HashMap(); try {

List dataList = accountService.findAccountInOutList(accountId, (currentPage-1)pageSize, pageSize); int total = accountService.findAccountInOutListCount(accountId);

map.put(“total”, total); //存放数据json数组 JSONArray dataArray = new JSONArray(); if (null != dataList) { for (AccountVo4InOutList aEx : dataList) {

String timeStr = aEx.getOperTime().toString();

BigDecimal balance = accountService.getAccountSum(accountId, timeStr, “date”).add(accountService.getAccountSumByHead(accountId, timeStr, “date”))

.add(accountService.getAccountSumByDetail(accountId, timeStr, “date”)).add(accountService.getManyAccountSum(accountId, timeStr, “date”)).add(initialAmount);

aEx.setBalance(balance);

dataArray.add(aEx);

}

}

map.put(“rows”, dataArray);

res.code = 200;

res.data = map;

} catch(Exception e){

e.printStackTrace();

res.code = 500;

res.data = “获取数据失败”;

} return res;

} @PostMapping(value = “/updateAmountIsDefault”) public String updateAmountIsDefault(@RequestParam(“isDefault”) Boolean isDefault, @RequestParam(“accountId”) Long accountId,

HttpServletRequest request) throws Exception{

Map objectMap = new HashMap(); int res = accountService.updateAmountIsDefault(isDefault, accountId); if(res > 0) { return returnJson(objectMap, ErpInfo.OK.name, ErpInfo.OK.code);

} else { return returnJson(objectMap, ErpInfo.ERROR.name, ErpInfo.ERROR.code);

}

} / * create by: qiankunpingtai * website:https://qiankunpingtai.cn

* description: * 批量删除账户信息 * create time: 2019/3/29 10:49 * @Param: ids * @return java.lang.Object */ @RequestMapping(value = “/batchDeleteAccountByIds”) public Object batchDeleteAccountByIds(@RequestParam(“ids”) String ids,@RequestParam(value=“deleteType”,

required =false,defaultValue=BusinessConstants.DELETE_TYPE_NORMAL)String deleteType) throws Exception {
JSONObject result = ExceptionConstants.standardSuccess(); /** * create by: qiankunpingtai * create time: 2019/4/10 10:19 * website:https://qiankunpingtai.cn * description: * 出于兼容性考虑,没有传递删除类型时,默认为正常删除 */ int i=0; if(BusinessConstants.DELETE_TYPE_NORMAL.equals(deleteType)){ i= accountService.batchDeleteAccountByIdsNormal(ids); }else if(BusinessConstants.DELETE_TYPE_FORCE.equals(deleteType)){ i= accountService.batchDeleteAccountByIds(ids); }else{ logger.error(“异常码[{}],异常提示[{}],参数,ids[{}],deleteType[{}]”, ExceptionConstants.DELETE_REFUSED_CODE,ExceptionConstants.DELETE_REFUSED_MSG,ids,deleteType); throw new BusinessRunTimeException(ExceptionConstants.DELETE_REFUSED_CODE, ExceptionConstants.DELETE_REFUSED_MSG); } if(i<1){ logger.error(“异常码[{}],异常提示[{}],参数,ids[{}]”, ExceptionConstants.ACCOUNT_DELETE_FAILED_CODE,ExceptionConstants.ACCOUNT_DELETE_FAILED_MSG,ids); throw new BusinessRunTimeException(ExceptionConstants.ACCOUNT_DELETE_FAILED_CODE, ExceptionConstants.ACCOUNT_DELETE_FAILED_MSG); } return result; }

}

package com.jsh.erp.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.jsh.erp.constants.BusinessConstants; import com.jsh.erp.constants.ExceptionConstants; import com.jsh.erp.datasource.entities.Tenant; import com.jsh.erp.datasource.entities.User; import com.jsh.erp.datasource.entities.UserEx; import com.jsh.erp.datasource.vo.TreeNodeEx; import com.jsh.erp.exception.BusinessParamCheckingException; import com.jsh.erp.service.log.LogService; import com.jsh.erp.service.tenant.TenantService; import com.jsh.erp.service.user.UserService; import com.jsh.erp.utils.; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static com.jsh.erp.utils.ResponseJsonUtil.returnJson; /** * @author ji_sheng_hua 华夏erp */ @RestController @RequestMapping(value = “/user”) public class UserController { private Logger logger = LoggerFactory.getLogger(UserController.class); @Value(“${manage.roleId}”) private Integer manageRoleId; @Resource private UserService userService; @Resource private TenantService tenantService; @Resource private LogService logService; private static String message = “成功”; private static final String HTTP = “http://”; private static final String CODE_OK = “200”;

@PostMapping(value = “/login”) public BaseResponseInfo login(@RequestParam(value = “loginame”, required = false) String loginame, @RequestParam(value = “password”, required = false) String password, HttpServletRequest request)throws Exception { logger.info(“============用户登录 login 方法调用开始==============”); String msgTip = “”; User user=null; BaseResponseInfo res = new BaseResponseInfo(); try { String username = loginame.trim(); password = password.trim(); //判断用户是否已经登录过,登录过不再处理 Object userInfo = request.getSession().getAttribute(“user”); User sessionUser = new User(); if (userInfo != null) { sessionUser = (User) userInfo; } if (sessionUser != null && username.equalsIgnoreCase(sessionUser.getLoginame())) { logger.info(“====用户 ” username “已经登录过, login 方法调用结束====”); msgTip = “user already login”; } //获取用户状态 int userStatus = -1; try { userStatus = userService.validateUser(username, password); } catch (Exception e) { e.printStackTrace(); logger.error(“>>>>>>>>>>>>>用户 ” username ” 登录 login 方法 访问服务层异常====”, e); msgTip = “access service exception”; } switch (userStatus) { case ExceptionCodeConstants.UserExceptionCode.USER_NOT_EXIST: msgTip = “user is not exist”; break; case ExceptionCodeConstants.UserExceptionCode.USER_PASSWORD_ERROR: msgTip = “user password error”; break; case ExceptionCodeConstants.UserExceptionCode.BLACK_USER: msgTip = “user is black”; break; case ExceptionCodeConstants.UserExceptionCode.USER_ACCESS_EXCEPTION: msgTip = “access service error”; break; default: try { msgTip = “user can login”; //验证通过 ,可以登录,放入session,记录登录日志 user = userService.getUserByUserName(username); request.getSession().setAttribute(“user”,user); if(user.getTenantId()!=null) { Tenant tenant = tenantService.getTenantByTenantId(user.getTenantId()); if(tenant!=null) { Long tenantId = tenant.getTenantId(); Integer userNumLimit = tenant.getUserNumLimit(); Integer billsNumLimit = tenant.getBillsNumLimit(); if(tenantId!=null) { request.getSession().setAttribute(“tenantId”,tenantId); //租户tenantId request.getSession().setAttribute(“userNumLimit”,userNumLimit); //用户限制数 request.getSession().setAttribute(“billsNumLimit”,billsNumLimit); //单据限制数 } } } logService.insertLog(“用户”, new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_LOGIN).append(user.getId()).toString(), ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()); } catch (Exception e) { e.printStackTrace(); logger.error(“>>>>>>>>>>>>>>>查询用户名为:” username ” ,用户信息异常”, e); } break; } Map<String, Object> data = new HashMap<String, Object>(); data.put(“msgTip”, msgTip); /** * 在IE模式下,无法获取到user数据, * 在此处明确添加上user信息 * */ if(user!=null){ data.put(“user”,user); } res.code = 200; res.data = data; logger.info(“===============用户登录 login 方法调用结束===============”); } catch(Exception e){ e.printStackTrace(); logger.error(e.getMessage()); res.code = 500; res.data = “用户登录失败”; } return res; } @GetMapping(value = “/getUserSession”) public BaseResponseInfo getSessionUser(HttpServletRequest request)throws Exception { BaseResponseInfo res = new BaseResponseInfo(); try { Map<String, Object> data = new HashMap<String, Object>(); Object userInfo = request.getSession().getAttribute(“user”); if(userInfo!=null) { User user = (User) userInfo; user.setPassword(null); data.put(“user”, user); } res.code = 200; res.data = data; } catch(Exception e){ e.printStackTrace(); res.code = 500; res.data = “获取session失败”; } return res; } @GetMapping(value = “/logout”) public BaseResponseInfo logout(HttpServletRequest request, HttpServletResponse response)throws Exception { BaseResponseInfo res = new BaseResponseInfo(); try { request.getSession().removeAttribute(“user”); request.getSession().removeAttribute(“tenantId”); request.getSession().removeAttribute(“userNumLimit”); request.getSession().removeAttribute(“billsNumLimit”); response.sendRedirect(“/login.html”); } catch(Exception e){ e.printStackTrace(); res.code = 500; res.data = “退出失败”; } return res; } @PostMapping(value = “/resetPwd”) public String resetPwd(@RequestParam(“id”) Long id, HttpServletRequest request) throws Exception { Map<String, Object> objectMap = new HashMap<String, Object>(); String password = “123456”; String md5Pwd = Tools.md5Encryp(password); int update = userService.resetPwd(md5Pwd, id); if(update > 0) { return returnJson(objectMap, message, ErpInfo.OK.code); } else { return returnJson(objectMap, message, ErpInfo.ERROR.code); } } @PostMapping(value = “/updatePwd”) public String updatePwd(@RequestParam(“userId”) Long userId, @RequestParam(“password”) String password, @RequestParam(“oldpwd”) String oldpwd, HttpServletRequest request)throws Exception { Integer flag = 0; Map<String, Object> objectMap = new HashMap<String, Object>(); try { User user = userService.getUser(userId); String oldPassword = Tools.md5Encryp(oldpwd); String md5Pwd = Tools.md5Encryp(password); //必须和原始密码一致才可以更新密码 if(user.getLoginame().equals(“jsh”)){ flag = 3; //管理员jsh不能修改密码 } else if (oldPassword.equalsIgnoreCase(user.getPassword())) { user.setPassword(md5Pwd); flag = userService.updateUserByObj(user); //1-成功 } else { flag = 2; //原始密码输入错误 } objectMap.put(“status”, flag); if(flag > 0) { return returnJson(objectMap, message, ErpInfo.OK.code); } else { return returnJson(objectMap, message, ErpInfo.ERROR.code); } } catch (Exception e) { logger.error(“>>>>>>>>>>>>>修改用户ID为 : ” userId “密码信息失败”, e); flag = 3; objectMap.put(“status”, flag); return returnJson(objectMap, message, ErpInfo.ERROR.code); } } /** * 获取全部用户数据列表 * @param request * @return */ @GetMapping(value = “/getAllList”) public BaseResponseInfo getAllList(HttpServletRequest request)throws Exception { BaseResponseInfo res = new BaseResponseInfo(); try { Map<String, Object> data = new HashMap<String, Object>(); List<User> dataList = userService.getUser(); if(dataList!=null) { data.put(“userList”, dataList); } res.code = 200; res.data = data; } catch(Exception e){ e.printStackTrace(); res.code = 500; res.data = “获取失败”; } return res; } /** * create by: cjl * description: * 查询分页用户列表 * create time: 2019/3/8 15:08 * @Param: pageSize * @Param: currentPage * @Param: search * @return java.lang.String */ @GetMapping(value = “/getUserList”) public String getUserList(@RequestParam(value = Constants.PAGE_SIZE, required = false) Integer pageSize, @RequestParam(value = Constants.CURRENT_PAGE, required = false) Integer currentPage, @RequestParam(value = Constants.SEARCH, required = false) String search)throws Exception { Map<String, Object> parameterMap = new HashMap<String, Object>(); //查询参数 JSONObject obj= JSON.parseObject(search); Set<String> key= obj.keySet(); for(String keyEach: key){ parameterMap.put(keyEach,obj.getString(keyEach)); } PageQueryInfo queryInfo = new PageQueryInfo(); Map<String, Object> objectMap = new HashMap<String, Object>(); if (pageSize == null || pageSize <= 0) { pageSize = BusinessConstants.DEFAULT_PAGINATION_PAGE_SIZE; } if (currentPage == null || currentPage <= 0) { currentPage = BusinessConstants.DEFAULT_PAGINATION_PAGE_NUMBER; } PageHelper.startPage(currentPage,pageSize,true); List<UserEx> list = userService.getUserList(parameterMap); //获取分页查询后的数据 PageInfo<UserEx> pageInfo = new PageInfo<>(list); objectMap.put(“page”, queryInfo); if (list == null) { queryInfo.setRows(new ArrayList<Object>()); queryInfo.setTotal(BusinessConstants.DEFAULT_LIST_NULL_NUMBER); return returnJson(objectMap, “查找不到数据”, ErpInfo.OK.code); } queryInfo.setRows(list); queryInfo.setTotal(pageInfo.getTotal()); return returnJson(objectMap, ErpInfo.OK.name, ErpInfo.OK.code); } /** * create by: cjl * description: * 新增用户及机构和用户关系 * create time: 2019/3/8 16:06 * @Param: beanJson * @return java.lang.Object */ @PostMapping(“/addUser”) @ResponseBody public Object addUser(@RequestParam(“info”) String beanJson, HttpServletRequest request)throws Exception{ JSONObject result = ExceptionConstants.standardSuccess(); Long userNumLimit = Long.parseLong(request.getSession().getAttribute(“userNumLimit”).toString()); Long count = userService.countUser(null,null); if(count>= userNumLimit) { throw new BusinessParamCheckingException(ExceptionConstants.USER_OVER_LIMIT_FAILED_CODE, ExceptionConstants.USER_OVER_LIMIT_FAILED_MSG); } else { UserEx ue= JSON.parseObject(beanJson, UserEx.class); userService.addUserAndOrgUserRel(ue); } return result; } /** * 注册用户 * @param loginame * @param password * @return * @throws Exception */ @PostMapping(value = “/registerUser”) public Object registerUser(@RequestParam(value = “loginame”, required = false) String loginame, @RequestParam(value = “password”, required = false) String password, HttpServletRequest request)throws Exception{ JSONObject result = ExceptionConstants.standardSuccess(); UserEx ue= new UserEx(); ue.setUsername(loginame); ue.setLoginame(loginame); ue.setPassword(password); userService.checkUserNameAndLoginName(ue); //检查用户名和登录名 ue = userService.registerUser(ue,manageRoleId,request); return result; } /** * create by: cjl * description: * 修改用户及机构和用户关系 * create time: 2019/3/8 16:06 * @Param: beanJson * @return java.lang.Object */ @PostMapping(“/updateUser”) @ResponseBody public Object updateUser(@RequestParam(“info”) String beanJson,@RequestParam(“id”) Long id)throws Exception{ JSONObject result = ExceptionConstants.standardSuccess(); UserEx ue= JSON.parseObject(beanJson, UserEx.class); ue.setId(id); userService.updateUserAndOrgUserRel(ue); return result; } @PostMapping(“/deleteUser”) @ResponseBody public Object deleteUser(@RequestParam(“ids”) String ids)throws Exception{ JSONObject result = ExceptionConstants.standardSuccess(); userService.batDeleteUser(ids); return result; } @PostMapping(“/batchDeleteUser”) @ResponseBody public Object batchDeleteUser(@RequestParam(“ids”) String ids)throws Exception{ JSONObject result = ExceptionConstants.standardSuccess(); userService.batDeleteUser(ids); return result; } @RequestMapping(“/getOrganizationUserTree”) public JSONArray getOrganizationUserTree()throws Exception{ JSONArray arr=new JSONArray(); List<TreeNodeEx> organizationUserTree= userService.getOrganizationUserTree(); if(organizationUserTree!=null&&organizationUserTree.size()>0){ for(TreeNodeEx node:organizationUserTree){ String str=JSON.toJSONString(node); JSONObject obj=JSON.parseObject(str); arr.add(obj) ; } } return arr; }

}

以下内容无关:

——————————————-分割线———————————————

环境信息:

mysql:5.7.32

seata-server:1.4.1

SpringCloud:Hoxton.SR10

SpringBoot:2.3.8.RELEASE

注册中心:Eureka

涉及服务:

Seata-server

1、在file.conf中修改

mode = “db”

然后配置DB信息:

database store property

db {

datasource = “druid”

## mysql/oracle/postgresql/h2/oceanbase etc.

dbType = “mysql”

driverClassName = “com.mysql.jdbc.Driver”

url = “jdbc:mysql://127.0.0.1:3306/seata”

user = “root”

password = “123456”

minConn = 5

maxConn = 100

globalTable = “global_table”

branchTable = “branch_table”

lockTable = “lock_table”

queryLimit = 100

maxWait = 5000

}

2、在register.conf

registry {

file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

type = “eureka”

loadBalance = “RandomLoadBalance”

loadBalanceVirtualNodes = 10

eureka {

serviceUrl = “http://eureka-chengdu:8761/eureka,http://eureka-hangzhou:8762/eureka

application = “seata-server”

weight = “1”

}

3、客户端修改

这里所指的客户端包含所有的资源管理器,包含所有需要seata-server管理的服务

在服务启动yml中增加:

seata:

enabled: true

事务群组(可以每个应用独立取名,也可以使用相同的名字)

tx-service-group: my_tx_group

client:

rm-report-success-enable: true

# 异步提交缓存队列长度(默认10000)

rm-async-commit-buffer-limit: 1000

# 一阶段全局提交结果上报TC重试次数(默认1次,建议大于1)

tm-commit-retry-count: 3

# 一阶段全局回滚结果上报TC重试次数(默认1次,建议大于1)

tm-rollback-retry-count: 3

support:

# 数据源自动代理开关(默认false关闭)

spring-datasource-autoproxy: false

service:

vgroup-mapping:

# TC 集群(必须与seata-server保持一致)

my_tx_group: seata-server

grouplist:

default: seata-server:8091

registry:

type: eureka

eureka:

serviceUrl: http://eureka-chengdu:8761/eureka/,http://eureka-hangzhou:8762/eureka/

TCC模式

TCC模式实践需要四个服务,除了seata-server外,其他服务调用关系如下:

business服务是全局事务的发起者,需要增加@GlobalTransactional注解

@Override

@GlobalTransactional

public String processTcc(Map params) {

String xid = RootContext.getXID();

System.out.println((“—》》》》xid:” + xid));

uploadFeign.upload(params);

downloadFeign.download(params);

return xid;

}

business服务会通过feign远程调用upload和download服务,这两个服务都要声明TCC的三个接口,并通过TwoPhaseBusinessAction注解声明。

upload服务:

@LocalTCC

public interface TccService {

@TwoPhaseBusinessAction(name = “upload”, commitMethod = “commitTcc”, rollbackMethod = “cancel”)

String upload(@BusinessActionContextParameter(paramName = “params”) Map<String, String> params);
boolean commitTcc(BusinessActionContext context); boolean cancel(BusinessActionContext context);

}

具体实现,这里模拟了TCC结果并放到Result中,通过restful接口可以查看,实际业务需要考虑防悬挂和空回滚问题,例子只是简单描述如何使用TCC模式:

@Slf4j

@Service

public class TccServiceImpl implements TccService {

@Value(“${spring.application.name}”)

private String appName;
@PostConstruct private void initAppName() { Result.getResult().setAppName(appName); } @Override public String upload(Map<String, String> params) { String xid = RootContext.getXID(); System.out.println((“—》》》》xid: ” + xid)); return “success”; } @Override public boolean commitTcc(BusinessActionContext context) { String xbid = context.getXid(); System.out.println((“—》》》》xid: ” + xbid + “提交成功”)); Result.getResult().setActionResult(context.getXid(), +context.getBranchId(), “Commit”, context.getActionContext(“params”)); return true; } @Override public boolean cancel(BusinessActionContext context) { System.out.println((“—》》》》xid: ” + context.getXid() + “回滚成功”)); Result.getResult().setActionResult(context.getXid(), context.getBranchId(), “Rollback”, context.getActionContext(“params”)); return true; }

}

download服务

download服务也同样需要声明一个TCC接口,实现上在Try阶段模拟每三次调用,,延迟30s失败一次场景

@Override

public String download(Map params) {

String xid = RootContext.getXID();

System.out.println((“—》》》》xid: ” + xid));

if (count.incrementAndGet() % 3 == 0) {

try {

TimeUnit.SECONDS.sleep(30);

} catch (InterruptedException e) {

log.warn(“InterruptedException”, e);

}

throw new RuntimeException(“服务异常”);

}

return “success”;

}

测试

1、通过restful接口调用两次,返回全局事务ID

2、查看download和upload服务结果,可以看到结果都是成功。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片