SpringBoot 仓库 ERP 管理系统
01 系统概述
基于 SpringBoot 框架和 SaaS 模式,非常好用的 ERP 软件,目前专注进销存 + 财务功能。主要模块有零售管理、采购管理、销售管理、仓库管理、财务管理、报表查询、系统管理等。支持预付款、收入支出、仓库调拨、组装拆卸、订单等特色功能。拥有库存状况、出入库统计等报表。权限控制更加精确
02 技术
SpringBoot + MyBatis + easyui
03 运行环境
- 开发工具:idea/eclipse,推荐使用 idea
- maven3+,并且在开发工具中配置好
- jdk1.8+,推荐 1.8
- MySQL5.5+, 推荐 5.7,5.6
04 技术架构
- 核心框架:SpringBoot 2.0.0
- 持久层框架:MyBatis 1.3.2
- 日志管理:Log4j 2.10.0
- JS 框架:jQuery 1.8.0
- UI 框架: EasyUI 1.9.4
- 模板框架: AdminLTE 2.4.0
- 项目管理框架:Maven 3.2.3
05 功能模块
- 零售管理
- 采购管理
- 销售管理
- 仓库管理
- 财务管理
- 报表查询
- 商品管理
- 基本信息
- 系统管理
06 项目结构
07 运行截图
零售关系-> 零售出库
采购管理-> 采购入库
财务管理-> 收入单
商品管理-> 商品信息
08 主要代码
用户管理
```java 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 / @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 = "loginName", required = false) String loginName,
@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 = loginName.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 {
request.getSession().removeAttribute("tenantId");
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;
}
}
```
账户管理
```java 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 75271 8920 / @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<Account> 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<String, Object> map = new HashMap<String, Object>();
try {
List<Account> 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<String, Object> map = new HashMap<String, Object>();
try {
List<AccountVo4InOutList> 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<String, Object> objectMap = new HashMap<String, Object>();
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;
}
}
```
10 如何使用
- 下载代码后解压缩
-
导入
-
将项目导入到开发工具当中
- 配置 maven(因为我是直接从我工程中打包的,里面含有我本地的 maven 配置,所以需要重新配置一下)
- 导入 SQL 到 MySQL 当中,修改 application.properties 中的数据源信息,和你自己的对应上就可以了
- 启动之后会有网址访问提示,直接访问就 ok。默认用户名密码:admin/123456
参考文献
- SaaS模式的ERP系统的研究(武汉理工大学·陆洪潮)
- 第三方物流仓储管理系统的设计与实现(东北大学·吴梦佳)
- 第三方物流仓储管理系统的设计与实现(东北大学·吴梦佳)
- 基于J2EE的库存管理系统的研究与实现(复旦大学·祝文)
- 智能仓储系统关键技术研究与实现(西安电子科技大学·翟雁琦)
- 基于.NET的ERP系统在中小型企业中的实现与研究(安徽理工大学·刘文娟)
- 发酵工厂的ERP系统设计(杭州电子科技大学·龚健华)
- 邮政仓储管理信息系统的设计与实现(大连理工大学·于思佳)
- ERP仓库物流管理信息系统的设计与实现(北京工业大学·王景发)
- 基于J2EE的库存管理系统的研究与实现(复旦大学·祝文)
- 临沂市联通公司物料系统的设计与实现(山东大学·远征)
- ERP仓库物流管理信息系统的设计与实现(北京工业大学·王景发)
- 仓库管理系统的设计与实现(电子科技大学·张天一)
- ERP仓库物流管理信息系统的设计与实现(北京工业大学·王景发)
- 基于SAP的WMS无线扫描系统的设计与实现(山东大学·滕军委)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:源码码头网 ,原文地址:https://m.bishedaima.com/yuanma/35777.html