Merge remote-tracking branch 'origin/dev_1.0.2' into dev_1.0.2
commit
5749d20c80
|
|
@ -1,5 +1,11 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
function createLoginFormData(data) {
|
||||
const formData = new FormData()
|
||||
Object.keys(data).forEach(key => formData.append(key, data[key]))
|
||||
return formData
|
||||
}
|
||||
|
||||
// 登录方法 - 基于 Session 认证,使用 FormData 格式
|
||||
export function login(username, password, code, rememberMe) {
|
||||
const formData = new FormData()
|
||||
|
|
@ -9,6 +15,41 @@ export function login(username, password, code, rememberMe) {
|
|||
formData.append('rememberMe', rememberMe || false)
|
||||
return request({
|
||||
url: '/login',
|
||||
headers: {
|
||||
isToken: false,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
repeatSubmit: false,
|
||||
allowWarning: true
|
||||
},
|
||||
method: 'post',
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
export function resetLoginPwd(data) {
|
||||
const formData = createLoginFormData({
|
||||
username: data.username,
|
||||
oldPassword: data.oldPassword,
|
||||
newPassword: data.newPassword,
|
||||
confirmPassword: data.confirmPassword,
|
||||
emailCode: data.emailCode
|
||||
})
|
||||
return request({
|
||||
url: '/login/resetPwd',
|
||||
headers: {
|
||||
isToken: false,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
repeatSubmit: false
|
||||
},
|
||||
method: 'post',
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
export function sendResetPwdEmailCode(username) {
|
||||
const formData = createLoginFormData({ username })
|
||||
return request({
|
||||
url: '/login/sendResetPwdEmailCode',
|
||||
headers: {
|
||||
isToken: false,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
|
|
|
|||
|
|
@ -85,3 +85,48 @@ export function updateFinanceStatus(id, status) {
|
|||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询产品配货备货明细
|
||||
export function productMatchList(orderCode) {
|
||||
return request({
|
||||
url: '/project/order/vue/productMatchList',
|
||||
method: 'get',
|
||||
params: { orderCode }
|
||||
})
|
||||
}
|
||||
|
||||
// 查询产品配备货绑定信息
|
||||
export function productMatchBindList(orderCode, productCode, params = {}) {
|
||||
return request({
|
||||
url: '/project/order/vue/productMatchBindList',
|
||||
method: 'get',
|
||||
params: { orderCode, productCode, ...params }
|
||||
})
|
||||
}
|
||||
|
||||
// 保存订单关联采购单
|
||||
export function savePurchaseOrderMap(data) {
|
||||
return request({
|
||||
url: '/project/order/vue/purchaseOrderMap',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询采购单SN码列表
|
||||
export function purchaseSnList(purchaseNo, orderCode) {
|
||||
return request({
|
||||
url: '/project/order/vue/purchaseSnList',
|
||||
method: 'get',
|
||||
params: { purchaseNo, orderCode }
|
||||
})
|
||||
}
|
||||
|
||||
// 订单绑定SN码
|
||||
export function bindOrderSnCodes(orderCode, productCode, productSnList) {
|
||||
return request({
|
||||
url: '/project/order/vue/bindOrderSnCodes',
|
||||
method: 'post',
|
||||
data: { orderCode, productCode, productSnList }
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const user = {
|
|||
const rememberMe = userInfo.rememberMe
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, rememberMe).then(res => {
|
||||
resolve()
|
||||
resolve(res)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
|
|
@ -60,17 +60,16 @@ const user = {
|
|||
},
|
||||
|
||||
// 获取用户信息
|
||||
GetInfo({ commit, state }) {
|
||||
GetInfo({ commit }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo().then(res => {
|
||||
// 后端返回的数据在 res.data 中
|
||||
const data = res.data || res
|
||||
const user = data.user
|
||||
let avatar = user.avatar? '/common/download/resource?resource='+encodeURIComponent(user.avatar) : ""
|
||||
let avatar = user.avatar ? '/common/download/resource?resource=' + encodeURIComponent(user.avatar) : ""
|
||||
if (!isHttp(avatar)) {
|
||||
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
|
||||
}
|
||||
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
if (data.roles && data.roles.length > 0) {
|
||||
commit('SET_ROLES', data.roles)
|
||||
commit('SET_PERMISSIONS', data.permissions)
|
||||
} else {
|
||||
|
|
@ -82,15 +81,13 @@ const user = {
|
|||
commit('SET_NAME', user.loginName)
|
||||
commit('SET_NICK_NAME', user.userName)
|
||||
commit('SET_AVATAR', avatar)
|
||||
/* 初始密码提示 */
|
||||
if(data.isDefaultModifyPwd) {
|
||||
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
if (data.isDefaultModifyPwd) {
|
||||
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||
}).catch(() => {})
|
||||
}
|
||||
/* 过期密码提示 */
|
||||
if(!data.isDefaultModifyPwd && data.isPasswordExpired) {
|
||||
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
if (!data.isDefaultModifyPwd && data.isPasswordExpired) {
|
||||
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
|
@ -102,7 +99,7 @@ const user = {
|
|||
},
|
||||
|
||||
// 退出系统 - 基于 Session 认证
|
||||
LogOut({ commit, state }) {
|
||||
LogOut({ commit }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout().then(() => {
|
||||
commit('SET_ROLES', [])
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ service.interceptors.response.use(res => {
|
|||
} else if (code === 601) {
|
||||
Message({ message: msg, type: 'warning' })
|
||||
return Promise.reject('error')
|
||||
} else if (code === 301 && res.config.headers && res.config.headers.allowWarning) {
|
||||
return res.data
|
||||
} else if (code !== 200) {
|
||||
Notification.error({ title: msg })
|
||||
return Promise.reject('error')
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -135,6 +135,7 @@ export default {
|
|||
inventoryStatus: '0',
|
||||
productCode: undefined,
|
||||
warehouseId: undefined,
|
||||
orderCode: undefined,
|
||||
},
|
||||
isImported: false, // Flag to track if data is from import
|
||||
isInitialLoad: false,
|
||||
|
|
@ -168,6 +169,7 @@ export default {
|
|||
});
|
||||
console.log('outerForm 关键字段:', {
|
||||
outerCode: outerForm && outerForm.outerCode,
|
||||
orderCode: outerForm && outerForm.orderCode,
|
||||
deliveryTime: outerForm && outerForm.deliveryTime,
|
||||
vendorName: outerForm && outerForm.vendorName,
|
||||
notifierAddress: outerForm && outerForm.notifierAddress
|
||||
|
|
@ -183,6 +185,7 @@ export default {
|
|||
|
||||
this.queryParams.productCode = productRow.productCode;
|
||||
this.queryParams.warehouseId = productRow.warehouseId;
|
||||
this.queryParams.orderCode = outerForm && outerForm.orderCode;
|
||||
this.queryParams.pageSize = productRow.quantity - productRow.deliveryGenerateQuantity - productRow.deliveryConfirmQuantity;
|
||||
|
||||
this.isInitialLoad = true;
|
||||
|
|
@ -333,6 +336,7 @@ export default {
|
|||
inventoryStatus: '0',
|
||||
productCode: undefined,
|
||||
warehouseId: undefined,
|
||||
orderCode: undefined,
|
||||
};
|
||||
this.isImported = false;
|
||||
this.price = null;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,37 @@
|
|||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog
|
||||
title="修改密码"
|
||||
:visible.sync="resetPwdOpen"
|
||||
width="420px"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
append-to-body
|
||||
>
|
||||
<el-form ref="resetPwdForm" :model="resetPwdForm" :rules="resetPwdRules" label-width="100px">
|
||||
<el-form-item label="旧密码" prop="oldPassword">
|
||||
<el-input v-model="resetPwdForm.oldPassword" type="password" placeholder="请输入旧密码" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="newPassword">
|
||||
<el-input v-model="resetPwdForm.newPassword" type="password" placeholder="请输入新密码" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="确认新密码" prop="confirmPassword">
|
||||
<el-input v-model="resetPwdForm.confirmPassword" type="password" placeholder="请确认新密码" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱验证码" prop="emailCode">
|
||||
<el-input v-model="resetPwdForm.emailCode" placeholder="请输入邮箱验证码" maxlength="6" style="width: 190px" />
|
||||
<el-button :loading="emailCodeLoading" :disabled="emailCodeCountdown > 0" @click="sendEmailCode">
|
||||
{{ emailCodeCountdown > 0 ? emailCodeCountdown + '秒后重发' : '发送验证码' }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<div class="password-tip">密码长度8-20位,需包含大小写字母、数字、特殊字符</div>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" :loading="resetPwdLoading" @click="submitResetPwd">提 交</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 底部 -->
|
||||
<div class="el-login-footer">
|
||||
<span>Copyright © 2018-2025 unissense All Rights Reserved.</span>
|
||||
|
|
@ -64,6 +95,7 @@
|
|||
<script>
|
||||
import Cookies from "js-cookie"
|
||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
||||
import { resetLoginPwd, sendResetPwdEmailCode } from '@/api/login'
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
|
|
@ -77,6 +109,36 @@ export default {
|
|||
rememberMe: false,
|
||||
code: ""
|
||||
},
|
||||
resetPwdForm: {
|
||||
username: "",
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
confirmPassword: "",
|
||||
emailCode: ""
|
||||
},
|
||||
resetPwdOpen: false,
|
||||
resetPwdLoading: false,
|
||||
emailCodeLoading: false,
|
||||
emailCodeCountdown: 0,
|
||||
emailCodeTimer: null,
|
||||
resetPwdRules: {
|
||||
oldPassword: [
|
||||
{ required: true, trigger: "blur", message: "请输入旧密码" }
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, trigger: "blur", message: "请输入新密码" },
|
||||
{ min: 8, max: 20, trigger: "blur", message: "密码长度为8到20个字符" },
|
||||
{ pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,20}$/, trigger: "blur", message: "密码需包含大小写字母、数字、特殊字符" }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, trigger: "blur", message: "请确认新密码" },
|
||||
{ validator: (rule, value, callback) => this.equalToNewPassword(rule, value, callback), trigger: "blur" }
|
||||
],
|
||||
emailCode: [
|
||||
{ required: true, trigger: "blur", message: "请输入邮箱验证码" },
|
||||
{ pattern: /^\d{6}$/, trigger: "blur", message: "邮箱验证码为6位数字" }
|
||||
]
|
||||
},
|
||||
loginRules: {
|
||||
username: [
|
||||
{ required: true, trigger: "blur", message: "请输入您的账号" }
|
||||
|
|
@ -103,9 +165,12 @@ export default {
|
|||
}
|
||||
},
|
||||
created() {
|
||||
// this.getCode()
|
||||
this.getCode()
|
||||
this.getCookie()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearEmailCodeTimer()
|
||||
},
|
||||
methods: {
|
||||
getCode() {
|
||||
// 基于 Session 认证,直接使用图片 URL,添加时间戳防止缓存
|
||||
|
|
@ -120,9 +185,84 @@ export default {
|
|||
this.loginForm = {
|
||||
username: username === undefined ? this.loginForm.username : username,
|
||||
password: password === undefined ? this.loginForm.password : decrypt(password),
|
||||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
|
||||
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
|
||||
code: this.loginForm.code
|
||||
}
|
||||
},
|
||||
equalToNewPassword(rule, value, callback) {
|
||||
if (this.resetPwdForm.newPassword !== value) {
|
||||
callback(new Error("两次输入的密码不一致"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
openResetPwdDialog() {
|
||||
this.resetPwdOpen = true
|
||||
this.clearEmailCodeTimer()
|
||||
this.resetPwdForm = {
|
||||
username: this.loginForm.username,
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
confirmPassword: "",
|
||||
emailCode: ""
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.resetPwdForm) {
|
||||
this.$refs.resetPwdForm.clearValidate()
|
||||
}
|
||||
})
|
||||
},
|
||||
sendEmailCode() {
|
||||
if (!this.resetPwdForm.username) {
|
||||
this.$modal.msgError("请输入用户名")
|
||||
return
|
||||
}
|
||||
this.emailCodeLoading = true
|
||||
sendResetPwdEmailCode(this.resetPwdForm.username).then(() => {
|
||||
this.$modal.msgSuccess("验证码已发送")
|
||||
this.startEmailCodeCountdown()
|
||||
}).finally(() => {
|
||||
this.emailCodeLoading = false
|
||||
})
|
||||
},
|
||||
startEmailCodeCountdown() {
|
||||
this.clearEmailCodeTimer()
|
||||
this.emailCodeCountdown = 60
|
||||
this.emailCodeTimer = setInterval(() => {
|
||||
if (this.emailCodeCountdown <= 1) {
|
||||
this.clearEmailCodeTimer()
|
||||
} else {
|
||||
this.emailCodeCountdown--
|
||||
}
|
||||
}, 1000)
|
||||
},
|
||||
clearEmailCodeTimer() {
|
||||
if (this.emailCodeTimer) {
|
||||
clearInterval(this.emailCodeTimer)
|
||||
this.emailCodeTimer = null
|
||||
}
|
||||
this.emailCodeCountdown = 0
|
||||
},
|
||||
submitResetPwd() {
|
||||
this.$refs.resetPwdForm.validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
this.resetPwdLoading = true
|
||||
resetLoginPwd(this.resetPwdForm).then(() => {
|
||||
this.$modal.msgSuccess("密码修改成功,请重新登录")
|
||||
this.resetPwdOpen = false
|
||||
this.$refs.loginForm.resetFields()
|
||||
this.loginForm.password = ""
|
||||
this.$nextTick(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.resetPwdLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleLogin() {
|
||||
this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
|
|
@ -136,7 +276,18 @@ export default {
|
|||
Cookies.remove("password")
|
||||
Cookies.remove('rememberMe')
|
||||
}
|
||||
this.$store.dispatch("Login", this.loginForm).then(() => {
|
||||
this.$store.dispatch("Login", this.loginForm).then((res) => {
|
||||
if (res && res.code === 301) {
|
||||
this.resetPwdForm.username = this.loginForm.username
|
||||
this.resetPwdForm.oldPassword = this.loginForm.password
|
||||
this.resetPwdForm.newPassword = ""
|
||||
this.resetPwdForm.confirmPassword = ""
|
||||
this.resetPwdForm.emailCode = ""
|
||||
this.clearEmailCodeTimer()
|
||||
this.resetPwdOpen = true
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
this.$router.push({ path: this.redirect || "/" }).catch(()=>{})
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
|
|
@ -160,6 +311,13 @@ export default {
|
|||
background-image: url("../assets/images/login-background.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
.password-tip {
|
||||
margin-top: -5px;
|
||||
margin-bottom: 15px;
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.title {
|
||||
margin: 0px auto 30px auto;
|
||||
text-align: center;
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ export default {
|
|||
} else if (type === 'hardware') {
|
||||
this.currentProductType = '2';
|
||||
} else if (type === 'maintenance') {
|
||||
this.currentProductType = '3';
|
||||
this.currentProductType = '3,22';
|
||||
}
|
||||
|
||||
this.selectProductVisible = true;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import cn.hutool.extra.mail.Mail;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.IncorrectCredentialsException;
|
||||
import org.apache.shiro.authc.UnknownAccountException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -33,6 +39,12 @@ import com.ruoyi.framework.web.service.ConfigService;
|
|||
@Slf4j
|
||||
public class SysLoginController extends BaseController
|
||||
{
|
||||
private static final String RESET_PWD_EMAIL_CODE_KEY = "RESET_PWD_EMAIL_CODE_";
|
||||
|
||||
private static final String RESET_PWD_EMAIL_CODE_TIME_KEY = "RESET_PWD_EMAIL_CODE_TIME_";
|
||||
|
||||
private static final long RESET_PWD_EMAIL_CODE_EXPIRE_TIME = 5 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* 是否开启记住我功能
|
||||
*/
|
||||
|
|
@ -42,6 +54,12 @@ public class SysLoginController extends BaseController
|
|||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@Autowired
|
||||
private SysPasswordService passwordService;
|
||||
|
||||
@GetMapping("/login")
|
||||
public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap)
|
||||
{
|
||||
|
|
@ -69,15 +87,24 @@ public class SysLoginController extends BaseController
|
|||
@ResponseBody
|
||||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
||||
{
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, Boolean.TRUE.equals(rememberMe));
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try
|
||||
{
|
||||
subject.login(token);
|
||||
if (!passwordService.isStrongPassword(password))
|
||||
{
|
||||
subject.logout();
|
||||
return AjaxResult.warn("当前密码不符合安全规则,请修改密码后重新登录");
|
||||
}
|
||||
return success();
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
if (e instanceof UnknownAccountException || e instanceof IncorrectCredentialsException)
|
||||
{
|
||||
return error("用户名或密码错误");
|
||||
}
|
||||
String msg = "用户或密码错误";
|
||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
||||
{
|
||||
|
|
@ -87,6 +114,118 @@ public class SysLoginController extends BaseController
|
|||
}
|
||||
}
|
||||
|
||||
@PostMapping("/login/sendResetPwdEmailCode")
|
||||
@ResponseBody
|
||||
public AjaxResult sendResetPwdEmailCode(String username)
|
||||
{
|
||||
if (StringUtils.isEmpty(username))
|
||||
{
|
||||
return error("请输入用户名");
|
||||
}
|
||||
SysUser user = userService.selectUserByLoginName(username);
|
||||
if (user == null)
|
||||
{
|
||||
return error("用户不存在");
|
||||
}
|
||||
if (StringUtils.isEmpty(user.getEmail()))
|
||||
{
|
||||
return error("请联系管理员绑定邮箱1");
|
||||
}
|
||||
String code = String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000));
|
||||
try
|
||||
{
|
||||
Mail.create()
|
||||
.setTos(user.getEmail())
|
||||
.setTitle("OMS系统修改密码邮箱验证码")
|
||||
.setContent("您的修改密码邮箱验证码为:" + code + ",有效期5分钟。如非本人操作,请忽略本邮件。")
|
||||
.setHtml(false)
|
||||
.send();
|
||||
ServletUtils.getRequest().getSession().setAttribute(RESET_PWD_EMAIL_CODE_KEY + username, code);
|
||||
ServletUtils.getRequest().getSession().setAttribute(RESET_PWD_EMAIL_CODE_TIME_KEY + username, System.currentTimeMillis());
|
||||
return success("验证码已发送");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("发送修改密码邮箱验证码失败", e);
|
||||
return error("验证码发送失败,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/login/resetPwd")
|
||||
@ResponseBody
|
||||
public AjaxResult resetPwd(String username, String oldPassword, String newPassword, String confirmPassword, String emailCode)
|
||||
{
|
||||
if (StringUtils.isEmpty(username))
|
||||
{
|
||||
return error("请输入用户名");
|
||||
}
|
||||
if (StringUtils.isEmpty(emailCode))
|
||||
{
|
||||
return error("请输入邮箱验证码");
|
||||
}
|
||||
if (!StringUtils.equals(newPassword, confirmPassword))
|
||||
{
|
||||
return error("两次密码输入不一致");
|
||||
}
|
||||
if (!passwordService.isStrongPassword(newPassword))
|
||||
{
|
||||
return error("新密码长度为8-20位,且需包含大小写字母、数字、特殊字符");
|
||||
}
|
||||
SysUser user = userService.selectUserByLoginName(username);
|
||||
if (user == null)
|
||||
{
|
||||
return error("用户不存在");
|
||||
}
|
||||
if (StringUtils.isEmpty(user.getEmail()))
|
||||
{
|
||||
return error("请联系管理员绑定邮箱1");
|
||||
}
|
||||
AjaxResult emailCodeValidateResult = validateResetPwdEmailCode(username, emailCode);
|
||||
if (emailCodeValidateResult != null)
|
||||
{
|
||||
return emailCodeValidateResult;
|
||||
}
|
||||
if (!passwordService.matches(user, oldPassword))
|
||||
{
|
||||
return error("修改密码失败,旧密码错误");
|
||||
}
|
||||
if (passwordService.matches(user, newPassword))
|
||||
{
|
||||
return error("新密码不能与旧密码相同");
|
||||
}
|
||||
user.setSalt(ShiroUtils.randomSalt());
|
||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
user.setPwdUpdateDate(new java.util.Date());
|
||||
if (userService.resetUserPwd(user) > 0)
|
||||
{
|
||||
ServletUtils.getRequest().getSession().removeAttribute(RESET_PWD_EMAIL_CODE_KEY + username);
|
||||
ServletUtils.getRequest().getSession().removeAttribute(RESET_PWD_EMAIL_CODE_TIME_KEY + username);
|
||||
return success("密码修改成功,请重新登录");
|
||||
}
|
||||
return error("修改密码异常,请联系管理员");
|
||||
}
|
||||
|
||||
private AjaxResult validateResetPwdEmailCode(String username, String emailCode)
|
||||
{
|
||||
Object sessionCode = ServletUtils.getRequest().getSession().getAttribute(RESET_PWD_EMAIL_CODE_KEY + username);
|
||||
Object sessionCodeTime = ServletUtils.getRequest().getSession().getAttribute(RESET_PWD_EMAIL_CODE_TIME_KEY + username);
|
||||
if (sessionCode == null || sessionCodeTime == null)
|
||||
{
|
||||
return error("请先获取邮箱验证码");
|
||||
}
|
||||
if (System.currentTimeMillis() - (Long) sessionCodeTime > RESET_PWD_EMAIL_CODE_EXPIRE_TIME)
|
||||
{
|
||||
ServletUtils.getRequest().getSession().removeAttribute(RESET_PWD_EMAIL_CODE_KEY + username);
|
||||
ServletUtils.getRequest().getSession().removeAttribute(RESET_PWD_EMAIL_CODE_TIME_KEY + username);
|
||||
return error("邮箱验证码已过期,请重新获取");
|
||||
}
|
||||
if (!StringUtils.equals(String.valueOf(sessionCode), emailCode))
|
||||
{
|
||||
return error("邮箱验证码错误");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@GetMapping("/unauth")
|
||||
public String unauth()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ spring:
|
|||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://121.199.168.157:3306/unis_pms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true
|
||||
url: jdbc:mysql://192.168.124.202:3307/oms_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true
|
||||
username: root
|
||||
password: unis@db
|
||||
password: Unis@123
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ shiro:
|
|||
# 首页地址
|
||||
indexUrl: /index
|
||||
# 验证码开关
|
||||
captchaEnabled: false
|
||||
captchaEnabled: true
|
||||
# 验证码类型 math 数字计算 char 字符验证
|
||||
captchaType: math
|
||||
cookie:
|
||||
|
|
|
|||
|
|
@ -1,91 +1,91 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ehcache name="ruoyi" updateCheck="false">
|
||||
|
||||
<!-- 磁盘缓存位置 -->
|
||||
<diskStore path="java.io.tmpdir"/>
|
||||
|
||||
<!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
|
||||
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
|
||||
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
|
||||
<!-- timeToIdleSeconds:失效前的空闲秒数,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||
<!-- timeToLiveSeconds:失效前的存活秒数,创建时间到失效时间的间隔为存活时间,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
|
||||
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->
|
||||
|
||||
<!-- 默认缓存 -->
|
||||
<defaultCache
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="false"
|
||||
timeToIdleSeconds="3600"
|
||||
timeToLiveSeconds="3600"
|
||||
overflowToDisk="false">
|
||||
</defaultCache>
|
||||
|
||||
<!-- 登录记录缓存 锁定10分钟 -->
|
||||
<cache name="loginRecordCache"
|
||||
maxEntriesLocalHeap="2000"
|
||||
eternal="false"
|
||||
timeToIdleSeconds="600"
|
||||
timeToLiveSeconds="0"
|
||||
overflowToDisk="false"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统活跃用户缓存 -->
|
||||
<cache name="sys-userCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统用户授权缓存 没必要过期 -->
|
||||
<cache name="sys-authCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
memoryStoreEvictionPolicy="LRU"
|
||||
statistics="false"/>
|
||||
|
||||
<!-- 系统缓存 -->
|
||||
<cache name="sys-cache"
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="true"
|
||||
overflowToDisk="true"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统参数缓存 -->
|
||||
<cache name="sys-config"
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="true"
|
||||
overflowToDisk="true"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统字典缓存 -->
|
||||
<cache name="sys-dict"
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="true"
|
||||
overflowToDisk="true"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统会话缓存 -->
|
||||
<cache name="shiro-activeSessionCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
statistics="false"/>
|
||||
|
||||
</ehcache>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ehcache name="ruoyi" updateCheck="false">
|
||||
|
||||
<!-- 磁盘缓存位置 -->
|
||||
<diskStore path="java.io.tmpdir"/>
|
||||
|
||||
<!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
|
||||
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
|
||||
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
|
||||
<!-- timeToIdleSeconds:失效前的空闲秒数,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||
<!-- timeToLiveSeconds:失效前的存活秒数,创建时间到失效时间的间隔为存活时间,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
|
||||
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->
|
||||
|
||||
<!-- 默认缓存 -->
|
||||
<defaultCache
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="false"
|
||||
timeToIdleSeconds="3600"
|
||||
timeToLiveSeconds="3600"
|
||||
overflowToDisk="false">
|
||||
</defaultCache>
|
||||
|
||||
<!-- 登录记录缓存 锁定10分钟 -->
|
||||
<cache name="loginRecordCache"
|
||||
maxEntriesLocalHeap="2000"
|
||||
eternal="false"
|
||||
timeToIdleSeconds="600"
|
||||
timeToLiveSeconds="0"
|
||||
overflowToDisk="false"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统活跃用户缓存 -->
|
||||
<cache name="sys-userCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统用户授权缓存 没必要过期 -->
|
||||
<cache name="sys-authCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
memoryStoreEvictionPolicy="LRU"
|
||||
statistics="false"/>
|
||||
|
||||
<!-- 系统缓存 -->
|
||||
<cache name="sys-cache"
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="true"
|
||||
overflowToDisk="true"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统参数缓存 -->
|
||||
<cache name="sys-config"
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="true"
|
||||
overflowToDisk="true"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统字典缓存 -->
|
||||
<cache name="sys-dict"
|
||||
maxEntriesLocalHeap="1000"
|
||||
eternal="true"
|
||||
overflowToDisk="true"
|
||||
statistics="false">
|
||||
</cache>
|
||||
|
||||
<!-- 系统会话缓存 -->
|
||||
<cache name="shiro-activeSessionCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
statistics="false"/>
|
||||
|
||||
</ehcache>
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#错误消息
|
||||
not.null=* 必须填写
|
||||
user.jcaptcha.error=验证码错误
|
||||
user.not.exists=用户不存在/密码错误
|
||||
user.password.not.match=用户不存在/密码错误
|
||||
user.not.exists=用户名或密码错误
|
||||
user.password.not.match=用户名或密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
|
||||
user.password.delete=对不起,您的账号已被删除
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ public class UserConstants
|
|||
public static final int USERNAME_MIN_LENGTH = 2;
|
||||
public static final int USERNAME_MAX_LENGTH = 20;
|
||||
|
||||
/**
|
||||
* 密码长度限制
|
||||
*/
|
||||
/** 密码长度限制 */
|
||||
public static final int PASSWORD_MIN_LENGTH = 5;
|
||||
public static final int PASSWORD_MAX_LENGTH = 20;
|
||||
|
||||
public static final String PASSWORD_COMPLEXITY_PATTERN = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z0-9]).{8,20}$";
|
||||
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -305,6 +305,8 @@ public class ShiroConfig
|
|||
filterChainDefinitionMap.put("/mcp/**", "mcpBot");
|
||||
filterChainDefinitionMap.put("/logout", "logout");
|
||||
// 不需要拦截的访问
|
||||
filterChainDefinitionMap.put("/login/resetPwd", "anon");
|
||||
filterChainDefinitionMap.put("/login/sendResetPwdEmailCode", "anon");
|
||||
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
|
||||
// 注册相关
|
||||
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.ruoyi.framework.shiro.service;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
|
|
@ -10,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
||||
|
|
@ -33,6 +35,8 @@ public class SysPasswordService
|
|||
@Value(value = "${user.password.maxRetryCount}")
|
||||
private String maxRetryCount;
|
||||
|
||||
private static final Pattern PASSWORD_COMPLEXITY_PATTERN = Pattern.compile(UserConstants.PASSWORD_COMPLEXITY_PATTERN);
|
||||
|
||||
@PostConstruct
|
||||
public void init()
|
||||
{
|
||||
|
|
@ -73,6 +77,11 @@ public class SysPasswordService
|
|||
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
}
|
||||
|
||||
public boolean isStrongPassword(String password)
|
||||
{
|
||||
return password != null && PASSWORD_COMPLEXITY_PATTERN.matcher(password).matches();
|
||||
}
|
||||
|
||||
public void clearLoginRecordCache(String loginName)
|
||||
{
|
||||
loginRecordCache.remove(loginName);
|
||||
|
|
|
|||
|
|
@ -2,17 +2,10 @@ package com.ruoyi.sip.controller;
|
|||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.sip.dto.ProjectTransferRequest;
|
||||
import com.ruoyi.sip.service.IDataProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 数据处理控制器
|
||||
|
|
@ -43,4 +36,10 @@ public class DataProcessController {
|
|||
dataProcessService.generateServiceBillsWhenAllDelivered(orderCode);
|
||||
}
|
||||
|
||||
@Anonymous
|
||||
@GetMapping("/projectPushCRM")
|
||||
public void projectSendCRM(@RequestParam("projectId") Long projectId) {
|
||||
dataProcessService.projectSendCRM(projectId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
|
@ -421,13 +425,17 @@ public class ProjectOrderInfoController extends BaseController
|
|||
@PostMapping("/importContractData")
|
||||
@ResponseBody
|
||||
public AjaxResult importContractData(@RequestPart("file") MultipartFile file, @RequestParam(value = "orderId",required = false) Long orderId, @RequestParam("fileSort") String fileSort, @RequestParam("versionCode") String versionCode) {
|
||||
String fileName = file.getOriginalFilename();
|
||||
if (!isAllowedContractFile(fileName, fileSort)) {
|
||||
return AjaxResult.error(getContractFileTypeError(fileSort));
|
||||
}
|
||||
ProjectOrderFileLog projectOrderFileLog = new ProjectOrderFileLog();
|
||||
projectOrderFileLog.setFileType(ProjectOrderFileLog.FileTypeEnum.CONTRACT.getCode());
|
||||
projectOrderFileLog.setOrderId(orderId);
|
||||
projectOrderFileLog.setUploadTime(DateUtils.getNowDate());
|
||||
projectOrderFileLog.setUploadUser(ShiroUtils.getUserId().toString());
|
||||
projectOrderFileLog.setUploadUserName(ShiroUtils.getSysUser().getUserName().toString());
|
||||
projectOrderFileLog.setFileName(file.getOriginalFilename());
|
||||
projectOrderFileLog.setFileName(fileName);
|
||||
projectOrderFileLog.setFileSort(fileSort);
|
||||
projectOrderFileLog.setFileVersionCode(versionCode);
|
||||
try {
|
||||
|
|
@ -440,6 +448,46 @@ public class ProjectOrderInfoController extends BaseController
|
|||
return AjaxResult.success(projectOrderFileLog);
|
||||
}
|
||||
|
||||
private boolean isAllowedContractFile(String fileName, String fileSort) {
|
||||
if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(fileSort)) {
|
||||
return false;
|
||||
}
|
||||
int dotIndex = fileName.lastIndexOf('.');
|
||||
if (dotIndex < 0 || dotIndex == fileName.length() - 1) {
|
||||
return false;
|
||||
}
|
||||
String extension = fileName.substring(dotIndex + 1).toLowerCase(Locale.ROOT);
|
||||
return getAllowedContractExtensions(fileSort).contains(extension);
|
||||
}
|
||||
|
||||
private Set<String> getAllowedContractExtensions(String fileSort) {
|
||||
switch (fileSort) {
|
||||
case "0":
|
||||
case "1":
|
||||
case "3":
|
||||
return new HashSet<>(Arrays.asList("pdf", "jpg", "png"));
|
||||
case "2":
|
||||
return new HashSet<>(Arrays.asList("zip", "rar", "jpg", "png"));
|
||||
default:
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
private String getContractFileTypeError(String fileSort) {
|
||||
switch (fileSort) {
|
||||
case "0":
|
||||
return "商务折扣审批文件仅支持 pdf、jpg、png 格式";
|
||||
case "1":
|
||||
return "合同文件仅支持 pdf、jpg、png 格式";
|
||||
case "2":
|
||||
return "补充附件仅支持 zip、rar、jpg、png 格式";
|
||||
case "3":
|
||||
return "已盖章合同文件仅支持 pdf、jpg、png 格式";
|
||||
default:
|
||||
return "不支持的文件类型";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/contract/export")
|
||||
public void contractExport(@RequestParam(required = false) String fileName,
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.sip.domain.OmsPurchaseOrderMap;
|
||||
import com.ruoyi.sip.domain.ProjectOrderFileLog;
|
||||
import com.ruoyi.sip.domain.ProjectOrderInfo;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchBindDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchDto;
|
||||
import com.ruoyi.sip.flowable.domain.Todo;
|
||||
import com.ruoyi.sip.flowable.service.TodoService;
|
||||
import com.ruoyi.sip.service.IProjectOrderFileLogService;
|
||||
|
|
@ -155,4 +158,51 @@ public class VueProjectOrderInfoController extends BaseController {
|
|||
String fileName = projectOrderInfoService.exportMcpList(projectOrderInfo);
|
||||
return AjaxResult.success(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配备货产品信息
|
||||
*/
|
||||
@GetMapping("/productMatchList")
|
||||
public AjaxResult productMatchList(@RequestParam String orderCode) {
|
||||
List<OrderProductMatchDto> list = projectOrderInfoService.selectProductMatchList(orderCode);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配备货绑定信息
|
||||
*/
|
||||
@GetMapping("/productMatchBindList")
|
||||
public TableDataInfo productMatchBindList(@RequestParam String orderCode, @RequestParam String productCode) {
|
||||
startPage();
|
||||
List<OrderProductMatchBindDto> list = projectOrderInfoService.selectProductMatchBindList(orderCode, productCode);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单关联采购单保存
|
||||
*/
|
||||
@PostMapping("/purchaseOrderMap")
|
||||
public AjaxResult savePurchaseOrderMap(@RequestBody OmsPurchaseOrderMap omsPurchaseOrderMap) {
|
||||
return toAjax(projectOrderInfoService.savePurchaseOrderMap(omsPurchaseOrderMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* 采购单SN码列表
|
||||
*/
|
||||
@GetMapping("/purchaseSnList")
|
||||
public AjaxResult purchaseSnList(@RequestParam String purchaseNo, @RequestParam String orderCode) {
|
||||
return AjaxResult.success(projectOrderInfoService.selectPurchaseSnList(purchaseNo, orderCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单绑定SN码
|
||||
*/
|
||||
@PostMapping("/bindOrderSnCodes")
|
||||
public AjaxResult bindOrderSnCodes(@RequestBody Map<String, Object> params) {
|
||||
String orderCode = (String) params.get("orderCode");
|
||||
String productCode = (String) params.get("productCode");
|
||||
List<String> productSnList = (List<String>) params.get("productSnList");
|
||||
return toAjax(projectOrderInfoService.bindOrderSnCodes(orderCode, productCode, productSnList));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public class InventoryInfo extends BaseEntity
|
|||
/** 出库单号 */
|
||||
@Excel(name = "出库单号")
|
||||
private String outerCode;
|
||||
private String orderCode;
|
||||
|
||||
/** 所属仓库 */
|
||||
@Excel(name = "所属仓库")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
package com.ruoyi.sip.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class OmsPurchaseOrderMap {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long orderId;
|
||||
|
||||
private Long purchaseId;
|
||||
|
||||
private Integer bindNum;
|
||||
}
|
||||
|
|
@ -264,6 +264,10 @@ public class ProjectOrderInfo extends BaseEntity {
|
|||
private String approveNode;
|
||||
//计收状态
|
||||
private String chargeStatus;
|
||||
/**
|
||||
* 备货状态
|
||||
*/
|
||||
private String orderStockingStatus;
|
||||
|
||||
/**
|
||||
* 付款方式
|
||||
|
|
@ -435,4 +439,21 @@ public class ProjectOrderInfo extends BaseEntity {
|
|||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum OrderStockingStatusEnum {
|
||||
PHZ("PHZ", "配货中"),
|
||||
YPH("YPH", "已配货"),
|
||||
BFBH("BFBH", "部分备货"),
|
||||
BHWC("BHWC", "备货完成"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String value;
|
||||
|
||||
OrderStockingStatusEnum(String code, String value) {
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.ruoyi.sip.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OrderProductMatchBindDto {
|
||||
|
||||
/** 产品编号 */
|
||||
private String productCode;
|
||||
|
||||
/** 产品型号 */
|
||||
private String model;
|
||||
|
||||
/** 采购单主键 */
|
||||
private Long purchaseId;
|
||||
|
||||
/** 采购单号 */
|
||||
private String purchaseNo;
|
||||
|
||||
/** 制造商 */
|
||||
private String vendorAddress;
|
||||
|
||||
/** 采购数量 */
|
||||
private Integer cgNum;
|
||||
|
||||
/** 可用数量 */
|
||||
private Integer kyNum;
|
||||
|
||||
/** 配额数量 */
|
||||
private Integer phNum;
|
||||
|
||||
/** 备货数量 */
|
||||
private Integer bhNum;
|
||||
|
||||
/** 入库状态 */
|
||||
private String status;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.ruoyi.sip.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OrderProductMatchDto {
|
||||
|
||||
/** 产品编码 */
|
||||
private String productCode;
|
||||
|
||||
/** 产品型号 */
|
||||
private String model;
|
||||
|
||||
/** 订单数量 */
|
||||
private Integer orderNum;
|
||||
|
||||
/** 配货数量 */
|
||||
private Integer phNum;
|
||||
|
||||
/** 备货数量 */
|
||||
private Integer bhNum;
|
||||
|
||||
/** 总成本 */
|
||||
private BigDecimal sumCost;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.ruoyi.sip.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OrderProductMatchSnDetailDto {
|
||||
|
||||
/** 产品SN码 */
|
||||
private String productSn;
|
||||
|
||||
/** 仓库名称 */
|
||||
private String warehouseName;
|
||||
|
||||
/** 订单编号 */
|
||||
private String orderCode;
|
||||
|
||||
/** 出库单号 */
|
||||
private String outerCode;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.ruoyi.sip.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OrderProductMatchSnDto {
|
||||
|
||||
/** SN码总数量 */
|
||||
private Integer totalQuantity;
|
||||
|
||||
private Integer quotaQuantity;
|
||||
|
||||
/** 仓库列表 */
|
||||
private List<OrderProductMatchWarehouseDto> warehouseList;
|
||||
|
||||
/** SN码列表 */
|
||||
private List<OrderProductMatchSnDetailDto> snList;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.ruoyi.sip.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OrderProductMatchWarehouseDto {
|
||||
|
||||
/** 仓库名称 */
|
||||
private String WarehouseName;
|
||||
|
||||
/** 绑定数量 */
|
||||
private Integer bindNum;
|
||||
|
||||
}
|
||||
|
|
@ -83,4 +83,8 @@ public interface InventoryInfoMapper
|
|||
List<InventoryInfo> selectInventoryInfoByOuterCodeList(List<String> outerCodeList);
|
||||
|
||||
List<InventoryInfo> selectInventoryInfoByInnerCodeList(List<String> innerCodeList);
|
||||
|
||||
int clearOrderCodeByOrderCodeAndProductCode(@Param("orderCode") String orderCode, @Param("productCode") String productCode);
|
||||
|
||||
int updateOrderCodeByProductSnList(@Param("productSnList") List<String> productSnList, @Param("orderCode") String orderCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.ruoyi.sip.mapper;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPurchaseOrderMap;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface OmsPurchaseOrderMapMapper {
|
||||
|
||||
OmsPurchaseOrderMap selectByOrderIdAndPurchaseId(@Param("orderId") Long orderId, @Param("purchaseId") Long purchaseId);
|
||||
|
||||
int insertOmsPurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap);
|
||||
|
||||
int updateOmsPurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap);
|
||||
}
|
||||
|
|
@ -5,6 +5,9 @@ import java.util.List;
|
|||
import com.ruoyi.sip.domain.InventoryDelivery;
|
||||
import com.ruoyi.sip.domain.ProjectOrderInfo;
|
||||
import com.ruoyi.sip.dto.HomepageQueryDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchBindDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchSnDetailDto;
|
||||
import com.ruoyi.sip.dto.StatisticsDetailDto;
|
||||
import com.ruoyi.sip.vo.OrderInfoVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
|
@ -76,6 +79,9 @@ public interface ProjectOrderInfoMapper
|
|||
|
||||
int updateProjectOrderInfoByCode(ProjectOrderInfo projectOrderInfo);
|
||||
|
||||
int updateOrderStockingStatusByCode(@Param("orderCode") String orderCode,
|
||||
@Param("orderStockingStatus") String orderStockingStatus);
|
||||
|
||||
void bakData(ProjectOrderInfo projectOrderInfo);
|
||||
|
||||
List<OrderInfoVo> listOrderInfoVo(ProjectOrderInfo queryParams);
|
||||
|
|
@ -93,4 +99,16 @@ public interface ProjectOrderInfoMapper
|
|||
@Param("dutyPhone") String dutyPhone,
|
||||
@Param("projectIds") List<Long> projectIds);
|
||||
|
||||
List<OrderProductMatchDto> selectProductMatchList(@Param("orderCode") String orderCode);
|
||||
|
||||
List<OrderProductMatchBindDto> selectProductMatchBindList(@Param("orderCode") String orderCode,
|
||||
@Param("productCode") String productCode);
|
||||
|
||||
int selectProductMatchSnCountlList(@Param("purchaseNo") String purchaseNo);
|
||||
|
||||
int selectPurchaseOrderMapBindNum(@Param("purchaseNo") String purchaseNo,
|
||||
@Param("orderCode") String orderCode);
|
||||
|
||||
List<OrderProductMatchSnDetailDto> selectProductMatchSnDetailList(@Param("purchaseNo") String purchaseNo);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,4 +11,6 @@ public interface IDataProcessService {
|
|||
|
||||
void generateServiceBillsWhenAllDelivered(String orderCode);
|
||||
|
||||
void projectSendCRM(Long projectId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@ package com.ruoyi.sip.service;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPurchaseOrderMap;
|
||||
import com.ruoyi.sip.domain.ProjectOrderFileLog;
|
||||
import com.ruoyi.sip.domain.ProjectOrderInfo;
|
||||
import com.ruoyi.sip.dto.ApiDataQueryDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchBindDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchDto;
|
||||
import com.ruoyi.sip.dto.OrderProductMatchSnDto;
|
||||
import com.ruoyi.sip.flowable.domain.Todo;
|
||||
import com.ruoyi.sip.dto.HomepageQueryDto;
|
||||
import com.ruoyi.sip.dto.StatisticsDetailDto;
|
||||
|
|
@ -107,4 +111,14 @@ public interface IProjectOrderInfoService
|
|||
|
||||
void approveOrderBatch(Todo todo);
|
||||
|
||||
List<OrderProductMatchDto> selectProductMatchList(String orderCode);
|
||||
|
||||
List<OrderProductMatchBindDto> selectProductMatchBindList(String orderCode, String productCode);
|
||||
|
||||
int savePurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap);
|
||||
|
||||
OrderProductMatchSnDto selectPurchaseSnList(String purchaseNo, String orderCode);
|
||||
|
||||
int bindOrderSnCodes(String orderCode, String productCode, List<String> productSnList);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ public class DataProcessServiceImpl implements IDataProcessService {
|
|||
@Resource
|
||||
private IOmsPayableBillService payableBillService;
|
||||
|
||||
@Resource
|
||||
private IProjectInfoService projectInfoService;
|
||||
|
||||
@Resource
|
||||
private IVendorInfoService vendorInfoService;
|
||||
|
||||
|
|
@ -165,5 +168,10 @@ public class DataProcessServiceImpl implements IDataProcessService {
|
|||
bindShiroUser(1L, "admin", "平台管理员");
|
||||
inventoryDeliveryService.generateServiceBillsWhenAllDelivered(orderCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectSendCRM(Long projectId) {
|
||||
projectInfoService.scheduleOpportunityUpdateByProjectId(projectId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,13 +55,11 @@ import com.ruoyi.common.utils.file.FileUploadUtils;
|
|||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.sip.domain.*;
|
||||
import com.ruoyi.sip.dto.ApiDataQueryDto;
|
||||
import com.ruoyi.sip.dto.*;
|
||||
import com.ruoyi.sip.flowable.domain.Todo;
|
||||
import com.ruoyi.sip.dto.HomepageQueryDto;
|
||||
import com.ruoyi.sip.dto.OrderExcelNumStaticsDto;
|
||||
import com.ruoyi.sip.dto.StatisticsDetailDto;
|
||||
import com.ruoyi.sip.flowable.service.IBuApproveConfigService;
|
||||
import com.ruoyi.sip.llm.tools.ProjectOrderInfoToolProvider;
|
||||
import com.ruoyi.sip.mapper.OmsPurchaseOrderMapMapper;
|
||||
import com.ruoyi.sip.mapper.OmsStockInfoMapper;
|
||||
import com.ruoyi.sip.mapper.ProjectInfoMapper;
|
||||
import com.ruoyi.sip.service.*;
|
||||
|
|
@ -110,6 +108,9 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
|
|||
@Autowired
|
||||
private ProjectOrderInfoMapper projectOrderInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper;
|
||||
|
||||
@Autowired
|
||||
private IProjectOrderFileLogService fileLogService;
|
||||
@Autowired
|
||||
|
|
@ -146,6 +147,9 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
|
|||
@Autowired
|
||||
private IProjectProductInfoBakService projectProductInfoBakService;
|
||||
|
||||
@Autowired
|
||||
private com.ruoyi.sip.mapper.InventoryInfoMapper inventoryInfoMapper;
|
||||
|
||||
private static final List<String> CSS_EMAIL_LIST = Arrays.asList("shiguijuan@pcitech.com", "huiwang@pcitech.com", "zhaoqian1@pcitech.com", "pci-ict@pcitech.com");
|
||||
private static final List<String> REJECT_EMAIL_LIST = Arrays.asList("li.junjie@unisinsight.com", "chen.shenggang@unisinsight.com");
|
||||
|
||||
|
|
@ -2872,4 +2876,92 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
|
|||
XWPFRun run = paragraph.createRun();
|
||||
run.setText(text != null ? text : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderProductMatchDto> selectProductMatchList(String orderCode) {
|
||||
return projectOrderInfoMapper.selectProductMatchList(orderCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderProductMatchBindDto> selectProductMatchBindList(String orderCode, String productCode) {
|
||||
return projectOrderInfoMapper.selectProductMatchBindList(orderCode, productCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int savePurchaseOrderMap(OmsPurchaseOrderMap omsPurchaseOrderMap) {
|
||||
OmsPurchaseOrderMap exist = omsPurchaseOrderMapMapper.selectByOrderIdAndPurchaseId(omsPurchaseOrderMap.getOrderId(), omsPurchaseOrderMap.getPurchaseId());
|
||||
int result;
|
||||
if (exist == null) {
|
||||
result = omsPurchaseOrderMapMapper.insertOmsPurchaseOrderMap(omsPurchaseOrderMap);
|
||||
} else {
|
||||
exist.setBindNum(omsPurchaseOrderMap.getBindNum());
|
||||
result = omsPurchaseOrderMapMapper.updateOmsPurchaseOrderMap(exist);
|
||||
}
|
||||
ProjectOrderInfo projectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(omsPurchaseOrderMap.getOrderId());
|
||||
if (projectOrderInfo != null) {
|
||||
refreshOrderStockingStatus(projectOrderInfo.getOrderCode());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderProductMatchSnDto selectPurchaseSnList(String purchaseNo, String orderCode) {
|
||||
OrderProductMatchSnDto result = new OrderProductMatchSnDto();
|
||||
result.setTotalQuantity(projectOrderInfoMapper.selectProductMatchSnCountlList(purchaseNo));
|
||||
Integer quotaQuantity = projectOrderInfoMapper.selectPurchaseOrderMapBindNum(purchaseNo, orderCode);
|
||||
result.setQuotaQuantity(quotaQuantity == null ? 0 : quotaQuantity);
|
||||
List<OrderProductMatchSnDetailDto> snList = projectOrderInfoMapper.selectProductMatchSnDetailList(purchaseNo);
|
||||
result.setSnList(snList);
|
||||
List<OrderProductMatchWarehouseDto> warehouseList = snList.stream()
|
||||
.collect(Collectors.groupingBy(OrderProductMatchSnDetailDto::getWarehouseName))
|
||||
.entrySet().stream()
|
||||
.map(entry -> new OrderProductMatchWarehouseDto(entry.getKey(), (int) entry.getValue().stream()
|
||||
.filter(item -> orderCode != null && orderCode.equals(item.getOrderCode()))
|
||||
.count()))
|
||||
.collect(Collectors.toList());
|
||||
result.setWarehouseList(warehouseList);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindOrderSnCodes(String orderCode, String productCode, List<String> productSnList) {
|
||||
if (StringUtils.isEmpty(orderCode) || StringUtils.isEmpty(productCode)) {
|
||||
return 0;
|
||||
}
|
||||
inventoryInfoMapper.clearOrderCodeByOrderCodeAndProductCode(orderCode, productCode);
|
||||
int result = 1;
|
||||
if (CollUtil.isNotEmpty(productSnList)) {
|
||||
result = inventoryInfoMapper.updateOrderCodeByProductSnList(productSnList, orderCode);
|
||||
}
|
||||
refreshOrderStockingStatus(orderCode);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void refreshOrderStockingStatus(String orderCode) {
|
||||
if (StringUtils.isEmpty(orderCode)) {
|
||||
return;
|
||||
}
|
||||
List<OrderProductMatchDto> matchList = projectOrderInfoMapper.selectProductMatchList(orderCode);
|
||||
if (CollUtil.isEmpty(matchList)) {
|
||||
return;
|
||||
}
|
||||
int orderNum = matchList.stream().mapToInt(item -> item.getOrderNum() == null ? 0 : item.getOrderNum()).sum();
|
||||
int phNum = matchList.stream().mapToInt(item -> item.getPhNum() == null ? 0 : item.getPhNum()).sum();
|
||||
int bhNum = matchList.stream().mapToInt(item -> item.getBhNum() == null ? 0 : item.getBhNum()).sum();
|
||||
String stockingStatus = null;
|
||||
if (phNum > 0) {
|
||||
stockingStatus = ProjectOrderInfo.OrderStockingStatusEnum.PHZ.getCode();
|
||||
}
|
||||
if (orderNum > 0 && phNum >= orderNum) {
|
||||
stockingStatus = ProjectOrderInfo.OrderStockingStatusEnum.YPH.getCode();
|
||||
if (bhNum > 0) {
|
||||
stockingStatus = ProjectOrderInfo.OrderStockingStatusEnum.BFBH.getCode();
|
||||
}
|
||||
}
|
||||
if (orderNum > 0 && bhNum >= orderNum) {
|
||||
stockingStatus = ProjectOrderInfo.OrderStockingStatusEnum.BHWC.getCode();
|
||||
}
|
||||
projectOrderInfoMapper.updateOrderStockingStatusByCode(orderCode, stockingStatus);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<result property="inventoryStatus" column="inventory_status" />
|
||||
<result property="innerCode" column="inner_code" />
|
||||
<result property="outerCode" column="outer_code" />
|
||||
<result property="orderCode" column="order_code" />
|
||||
<result property="warehouseId" column="warehouse_id" />
|
||||
<result property="innerPrice" column="inner_price" />
|
||||
<result property="outerPrice" column="outer_price" />
|
||||
|
|
@ -22,7 +23,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</resultMap>
|
||||
|
||||
<sql id="selectInventoryInfoVo">
|
||||
select t1.id, t1.product_code, t1.product_sn, t1.license_key, t1.inventory_status, t1.inner_code, t1.outer_code, t1.warehouse_id, t1.inner_price,t1.tax_rate,
|
||||
select t1.id, t1.product_code, t1.product_sn, t1.license_key, t1.inventory_status, t1.inner_code, t1.outer_code, t1.order_code, t1.warehouse_id, t1.inner_price,t1.tax_rate,
|
||||
t1.outer_price, t1.create_by, t1.create_time, t1.update_by, t1.update_time ,
|
||||
t2.warehouse_name,t3.description as 'product_desc',t3.model,t3.type as product_type
|
||||
from oms_inventory_info t1
|
||||
|
|
@ -50,6 +51,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</if>
|
||||
<if test="innerCode != null and innerCode != ''">and t1.inner_code = #{innerCode}</if>
|
||||
<if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if>
|
||||
<if test="orderCode != null and orderCode != ''">and t1.order_code = #{orderCode}</if>
|
||||
<if test="warehouseId != null ">and t1.warehouse_id = #{warehouseId}</if>
|
||||
<if test="innerPrice != null ">and t1.inner_price = #{innerPrice}</if>
|
||||
<if test="outerPrice != null ">and t1.outer_price = #{outerPrice}</if>
|
||||
|
|
@ -213,6 +215,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</foreach>)
|
||||
|
||||
</update>
|
||||
<update id="clearOrderCodeByOrderCodeAndProductCode">
|
||||
update oms_inventory_info
|
||||
set order_code = null,
|
||||
update_time = now()
|
||||
where order_code = #{orderCode}
|
||||
and product_code = #{productCode}
|
||||
</update>
|
||||
|
||||
<update id="updateOrderCodeByProductSnList">
|
||||
update oms_inventory_info
|
||||
set order_code = #{orderCode},
|
||||
update_time = now()
|
||||
where product_sn in
|
||||
<foreach item="productSn" collection="productSnList" separator="," open="(" close=")">
|
||||
#{productSn}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<delete id="deleteInventoryInfoById" parameterType="Long">
|
||||
delete from oms_inventory_info where id = #{id}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.sip.mapper.OmsPurchaseOrderMapMapper">
|
||||
|
||||
<resultMap type="OmsPurchaseOrderMap" id="OmsPurchaseOrderMapResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="orderId" column="order_id"/>
|
||||
<result property="purchaseId" column="purchase_id"/>
|
||||
<result property="bindNum" column="bind_num"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByOrderIdAndPurchaseId" resultMap="OmsPurchaseOrderMapResult">
|
||||
select id, order_id, purchase_id, bind_num
|
||||
from oms_purchase_order_map
|
||||
where order_id = #{orderId}
|
||||
and purchase_id = #{purchaseId}
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<insert id="insertOmsPurchaseOrderMap" parameterType="OmsPurchaseOrderMap" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into oms_purchase_order_map(order_id, purchase_id, bind_num)
|
||||
values (#{orderId}, #{purchaseId}, #{bindNum})
|
||||
</insert>
|
||||
|
||||
<update id="updateOmsPurchaseOrderMap" parameterType="OmsPurchaseOrderMap">
|
||||
update oms_purchase_order_map
|
||||
set bind_num = #{bindNum}
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
|
@ -38,13 +38,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<result property="paymentRatio" column="payment_ratio" />
|
||||
<result property="paymentDescription" column="payment_description" />
|
||||
<result property="operationVersion" column="operation_version" />
|
||||
<result property="orderStockingStatus" column="order_stocking_status" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectProjectOrderInfoVo">
|
||||
select id, project_id,province, city, business_person, business_email, business_phone, order_code, currencyType,
|
||||
shipment_amount, actual_purchase_amount, order_end_time, delivery_time, company_delivery, notifier,finance_status,
|
||||
notifier_email, notifier_phone, duty, duty_email, duty_phone, order_channel, partner_code, supplier,notifier_address,
|
||||
remark, order_status, create_by, create_time, update_by, update_time,version_code,process_type,process_template,discount_fold,
|
||||
remark, order_status, create_by, create_time, update_by, update_time,version_code,process_type,process_template,discount_fold,order_stocking_status,
|
||||
delivery_status,sign_status,outer_status,approve_time,payment_method,payment_ratio,payment_description,order_type,operation_version
|
||||
|
||||
from project_order_info t1
|
||||
|
|
@ -55,7 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
t1.notifier_email, t1.notifier_phone, t1.duty, t1.duty_email, t1.duty_phone, t1.order_channel, t1.partner_code, t1.supplier,
|
||||
t1.remark, t1.order_status, t1.create_by, t1.create_time, t1.update_by, t1.update_time,t1.partner_user_name,t1.partner_email
|
||||
,t1.partner_phone,t1.version_code,t1.process_type,t1.process_template,t1.discount_fold,t1.notifier_address,t1.finance_status,
|
||||
t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description,t1.operation_version
|
||||
t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description,t1.operation_version,t1.order_stocking_status
|
||||
,t2.project_code,t2.project_name,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time
|
||||
,t2.customer_phone,t2.customer_user_name,t2.agent_code,t2.customer_code,t2.partner_name project_partner_name
|
||||
,t3.partner_name,t3.level,t3.system_user_id,t3.address partner_address
|
||||
|
|
@ -122,6 +123,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if>
|
||||
<if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if>
|
||||
<if test="orderStatus != null and orderStatus != ''">and t1.order_status = #{orderStatus}</if>
|
||||
<if test="orderStockingStatus != null and orderStockingStatus != ''">and t1.order_stocking_status = #{orderStockingStatus}</if>
|
||||
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
|
||||
<if test="outerStatus != null and outerStatus != ''">and t1.outer_status = #{outerStatus}</if>
|
||||
<if test="signStatus != null and signStatus != ''">and t1.sign_status = #{signStatus}</if>
|
||||
|
|
@ -411,7 +413,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
t1.notifier_email, t1.notifier_phone, t1.duty, t1.duty_email, t1.duty_phone, t1.order_channel, t1.partner_code, t1.supplier,
|
||||
t1.remark, t1.order_status, t1.create_by, t1.create_time, t1.update_by, t1.update_time,t1.partner_user_name,t1.partner_email
|
||||
,t1.partner_phone,t1.version_code,t1.process_type,t1.process_template,t1.discount_fold,t1.notifier_address,t1.finance_status,
|
||||
t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description,t1.operation_version
|
||||
t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description,t1.operation_version,t1.order_stocking_status
|
||||
,t2.project_code,t2.project_name,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time
|
||||
,t2.customer_phone,t2.customer_user_name,t2.agent_code,t2.customer_code,t2.partner_name project_partner_name
|
||||
,t3.partner_name,t3.level,t3.system_user_id,t3.address partner_address
|
||||
|
|
@ -479,6 +481,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if>
|
||||
<if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if>
|
||||
<if test="orderStatus != null and orderStatus != ''">and t1.order_status = #{orderStatus}</if>
|
||||
<if test="orderStockingStatus != null and orderStockingStatus != ''">and t1.order_stocking_status = #{orderStockingStatus}</if>
|
||||
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
|
||||
<if test="outerStatus != null and outerStatus != ''">and t1.outer_status = #{outerStatus}</if>
|
||||
<if test="signStatus != null and signStatus != ''">and t1.sign_status = #{signStatus}</if>
|
||||
|
|
@ -623,6 +626,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="supplier != null">supplier,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="orderStatus != null">order_status,</if>
|
||||
<if test="orderStockingStatus != null and orderStockingStatus != ''">order_stocking_status,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
|
|
@ -666,6 +670,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="supplier != null">#{supplier},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="orderStatus != null">#{orderStatus},</if>
|
||||
<if test="orderStockingStatus != null and orderStockingStatus != ''">#{orderStockingStatus},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
|
|
@ -806,6 +811,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="supplier != null">supplier = #{supplier},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="orderStatus != null">order_status = #{orderStatus},</if>
|
||||
<if test="orderStockingStatus != null and orderStockingStatus != ''">order_stocking_status = #{orderStockingStatus},</if>
|
||||
<if test="outerStatus != null">outer_status = #{outerStatus},</if>
|
||||
<if test="deliveryStatus != null">delivery_status = #{deliveryStatus},</if>
|
||||
<if test="signStatus != null">sign_status = #{signStatus},</if>
|
||||
|
|
@ -867,6 +873,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="supplier != null">supplier = #{supplier},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="orderStatus != null">order_status = #{orderStatus},</if>
|
||||
<if test="orderStockingStatus != null and orderStockingStatus != ''">order_stocking_status = #{orderStockingStatus},</if>
|
||||
<if test="outerStatus != null">outer_status = #{outerStatus},</if>
|
||||
<if test="deliveryStatus != null">delivery_status = #{deliveryStatus},</if>
|
||||
<if test="signStatus != null">sign_status = #{signStatus},</if>
|
||||
|
|
@ -880,6 +887,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<update id="updatePartnerCodeByCode">
|
||||
update project_order_info set partner_code = #{newValue} where partner_code = #{oldValue}
|
||||
</update>
|
||||
<update id="updateOrderStockingStatusByCode">
|
||||
update project_order_info
|
||||
set order_stocking_status = #{orderStockingStatus},
|
||||
update_time = now()
|
||||
where order_code = #{orderCode}
|
||||
</update>
|
||||
|
||||
<update id="updateDutyByProjectIds">
|
||||
update project_order_info
|
||||
|
|
@ -914,4 +927,100 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
where t1.id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectProductMatchList" resultType="com.ruoyi.sip.dto.OrderProductMatchDto">
|
||||
select
|
||||
t3.product_code as product_code,
|
||||
t3.model,
|
||||
t1.quantity as order_num,
|
||||
sum(ifnull(t5.bind_num, 0)) as ph_num,
|
||||
(select count(1) from oms_inventory_info as tt where t2.order_code = tt.order_code and t3.product_code = tt.product_code) as bh_num,
|
||||
ifnull((select sum(inner_price) from oms_inventory_info as tt where t2.order_code = tt.order_code and t3.product_code = tt.product_code),0) as sum_cost
|
||||
from project_product_info as t1
|
||||
inner join project_order_info as t2
|
||||
on t1.project_id = t2.project_id
|
||||
inner join product_info as t3
|
||||
on t1.product_bom_code = t3.product_code
|
||||
left join oms_purchase_order_item as t4
|
||||
on t3.product_code = t4.product_code
|
||||
left join oms_purchase_order_map as t5
|
||||
on t2.id = t5.order_id and t4.purchase_id = t5.purchase_id
|
||||
where t2.order_code = #{orderCode}
|
||||
and t3.type in (1, 2)
|
||||
group by t3.product_code, t3.model, t1.quantity
|
||||
</select>
|
||||
|
||||
<select id="selectProductMatchBindList" resultType="com.ruoyi.sip.dto.OrderProductMatchBindDto">
|
||||
select
|
||||
t3.product_code,
|
||||
t3.model,
|
||||
t6.id as purchase_id,
|
||||
t6.purchase_no,
|
||||
(select vendor_address from oms_vendor_info as tt where tt.vendor_id = t6.vendor_id) as vendor_address,
|
||||
t4.quantity as cg_num,
|
||||
t4.quantity - ifnull((select sum(bind_num) from oms_purchase_order_map as tt where tt.purchase_id = t5.purchase_id), 0) as ky_num,
|
||||
t5.bind_num as ph_num,
|
||||
t6.status,
|
||||
(
|
||||
select count(1) from oms_inventory_info as tt1
|
||||
inner join oms_inventory_inner as tt2
|
||||
on tt1.inner_code = tt2.inner_code
|
||||
where t2.order_code = tt1.order_code
|
||||
and t3.product_code = tt1.product_code
|
||||
and tt2.purchase_no = t6.purchase_no
|
||||
) as bh_num
|
||||
from project_product_info as t1
|
||||
inner join project_order_info as t2
|
||||
on t1.project_id = t2.project_id
|
||||
inner join product_info as t3
|
||||
on t1.product_bom_code = t3.product_code
|
||||
inner join oms_purchase_order_item as t4
|
||||
on t3.product_code = t4.product_code
|
||||
left join oms_purchase_order_map as t5
|
||||
on t2.id = t5.order_id and t4.purchase_id = t5.purchase_id
|
||||
inner join oms_purchase_order as t6
|
||||
on t6.id = t4.purchase_id
|
||||
where t2.order_code = #{orderCode}
|
||||
and t3.product_code = #{productCode}
|
||||
and t6.approve_status = 2 and t6.confirm_status = 1
|
||||
group by t6.purchase_no
|
||||
</select>
|
||||
|
||||
<select id="selectProductMatchSnCountlList" resultType="java.lang.Integer">
|
||||
select
|
||||
count(1)
|
||||
from oms_inventory_info as t1
|
||||
inner join oms_inventory_inner as t2
|
||||
on t1.inner_code = t2.inner_code
|
||||
left join oms_warehouse_info as t3
|
||||
on t2.warehouse_id = t3.id
|
||||
where t2.purchase_no = #{purchaseNo}
|
||||
</select>
|
||||
|
||||
<select id="selectPurchaseOrderMapBindNum" resultType="java.lang.Integer">
|
||||
select
|
||||
ifnull(t3.bind_num, 0)
|
||||
from oms_purchase_order as t1
|
||||
inner join project_order_info as t2
|
||||
on t2.order_code = #{orderCode}
|
||||
left join oms_purchase_order_map as t3
|
||||
on t2.id = t3.order_id and t1.id = t3.purchase_id
|
||||
where t1.purchase_no = #{purchaseNo}
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectProductMatchSnDetailList" resultType="com.ruoyi.sip.dto.OrderProductMatchSnDetailDto">
|
||||
select
|
||||
t1.product_sn,
|
||||
t3.warehouse_name,
|
||||
t1.order_code,
|
||||
t1.outer_code
|
||||
from oms_inventory_info as t1
|
||||
inner join oms_inventory_inner as t2
|
||||
on t1.inner_code = t2.inner_code
|
||||
left join oms_warehouse_info as t3
|
||||
on t2.warehouse_id = t3.id
|
||||
where t2.purchase_no = #{purchaseNo}
|
||||
order by t1.product_sn
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
|||
Loading…
Reference in New Issue