修改人力成本管理

master
OathK1per 2021-11-19 10:41:53 +08:00
parent fbf20a65c9
commit da81395309
9 changed files with 157 additions and 54 deletions

View File

@ -95,9 +95,11 @@ public class HumanCostController extends BaseController{
Page<ProjectUserTime> project = humanCostService.project(searchInfo, admin, pageNumber, pageSize);
List<ProjectUserTime> staff = humanCostService.staff(searchInfo, admin);
Map<String, BigDecimal> map = humanCostService.map(searchInfo, admin, pageNumber, pageSize);
BigDecimal total = humanCostService.sum(searchInfo, admin);
model.put("pager", project);
model.put("staff", staff);
model.put("map", map);
model.put("total", total);
return "admin/human_cost_list";
}
@ -152,9 +154,8 @@ public class HumanCostController extends BaseController{
@RequestMapping("/batchImport")
@ResponseBody
public String batchImport(MultipartFile file) {
public String batchImport(MultipartFile file, @RequestParam(value = "date",required = false) String date) {
try {
String date = "2021-11";
Map<String, String> title = new HashMap<>();
Collection<Map> maps = ExcelUtil.importHumanCost(Map.class, file.getInputStream(),
title,0);

View File

@ -37,7 +37,7 @@ public class ProjectUserTime {
private String userName;
@Column(name = "time")
private Date time;
private String time;
@Column(name = "created_by")
private int createdBy;
@ -107,11 +107,11 @@ public class ProjectUserTime {
this.userName = userName;
}
public Date getTime() {
public String getTime() {
return time;
}
public void setTime(Date time) {
public void setTime(String time) {
this.time = time;
}

View File

@ -1,16 +1,26 @@
package cn.palmte.work.model;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* @author Yuanping Zhang
* @date 2021/11/1
*/
@Transactional(rollbackFor = Exception.class)
public interface ProjectUserTimeRepository extends JpaRepository<ProjectUserTime, Integer> {
@Query(value = "select * from project_user_time where user_id = ? and project_id = ? and time = ? limit 1", nativeQuery = true)
public ProjectUserTime findByUserIdAndProjectIdAndTime(int userId, int projectId, Date time);
@Query(value = "select * from project_user_time where user_id = ?1 and project_id = ?2 and time = ?3 limit 1", nativeQuery = true)
ProjectUserTime findByUserIdAndProjectIdAndTime(int userId, int projectId, String time);
@Query(value = "select * from project_user_time where time = ?1", nativeQuery = true)
List<ProjectUserTime> findAllByTime(String time);
@Modifying
@Query(value = "delete from project_user_time where time = ?1", nativeQuery = true)
int deleteByTime(String date);
}

View File

@ -2,6 +2,7 @@ package cn.palmte.work.model;
import top.jfunc.common.db.bean.Page;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@ -18,4 +19,6 @@ public interface ProjectUserTimeRepositoryCustom {
List<ProjectUserTime> list(ConcurrentHashMap<String, String> searchInfo, Admin admin, int pageNumber, int pageSize);
Page<ProjectUserTime> individual(ConcurrentHashMap<String, String> searchInfo, Integer id, int pageNumber, int pageSize);
List<ProjectUserTime> sum(ConcurrentHashMap<String, String> searchInfo, Admin admin);
}

View File

@ -53,13 +53,22 @@ public class ProjectUserTimeRepositoryImpl implements ProjectUserTimeRepositoryC
public Page<ProjectUserTime> individual(ConcurrentHashMap<String, String> searchInfo, Integer id, int pageNumber, int pageSize) {
QueryHelper helper = new QueryHelper("select put.*", "from project_user_time put");
helper.addCondition("put.user_id = ?", id);
helper.addCondition(searchInfo.containsKey("time"),"put.time = ?", searchInfo.get("time") + "-01 00:00:00");
helper.addCondition(searchInfo.containsKey("time"),"put.time = ?", searchInfo.get("time"));
helper.addOrderProperty("created_time", false);
return pagination.paginate(helper.getSql(), ProjectUserTime.class, pageNumber, pageSize);
}
@Override
public List<ProjectUserTime> sum(ConcurrentHashMap<String, String> searchInfo, Admin admin) {
QueryHelper helper = new QueryHelper("select put.user_salary, put.user_cost", "from project_user_time put");
helper.leftJoin("project proj", "put.project_id = proj.id");
helper.leftJoin("dept", "proj.dept_id = dept.id");
searchQuery(helper, searchInfo, admin);
return pagination.find(helper.getSql(), ProjectUserTime.class);
}
private QueryHelper searchQuery(QueryHelper helper, ConcurrentHashMap<String, String> searchInfo, Admin admin) {
helper.addCondition(searchInfo.containsKey("time"),"put.time = ?", searchInfo.get("time") + "-01 00:00:00");
helper.addCondition(searchInfo.containsKey("time"),"put.time = ?", searchInfo.get("time"));
helper.addCondition(searchInfo.containsKey("projectId") && !"-1".equals(searchInfo.get("projectId")), "put.project_id = ?", searchInfo.get("projectId"));
helper.addCondition(searchInfo.containsKey("deptId") && !"-1".equals(searchInfo.get("deptId")), "dept.id = ?", searchInfo.get("deptId"));
helper.addCondition(searchInfo.containsKey("userName"), "put.user_name like ?", "%'" + searchInfo.get("userName") + "'%");

View File

@ -2,7 +2,6 @@ package cn.palmte.work.service;
import cn.palmte.work.bean.ResponseMsg;
import cn.palmte.work.model.*;
import cn.palmte.work.utils.DateKit;
import cn.palmte.work.utils.InterfaceUtil;
import cn.palmte.work.utils.StrKit;
import org.slf4j.Logger;
@ -11,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.jfunc.common.db.bean.Page;
import top.jfunc.common.utils.CollectionUtil;
import java.math.BigDecimal;
import java.util.*;
@ -101,7 +101,7 @@ public class HumanCostService {
Project project = projectRepository.findByProjectName(projectName);
if (project == null) {
throw new Exception(projectName + "不存在");
} else if (project.getStatus() != 15 || project.getApproveStatusSettle() == 1 || project.getApproveStatusSettle() == 2) {
} else if (project.getStatus() != Project.STATUS_SETTLE || project.getApproveStatusSettle() == 1 || project.getApproveStatusSettle() == 2) {
throw new Exception(projectName + "不在项目结算的可编辑状态");
}
if (projectSet.contains(projectName)) {
@ -136,17 +136,15 @@ public class HumanCostService {
} else {
throw new Exception(projectName + " " + key + "的成本需为大于0的最多两位小数的的数字");
}
ProjectUserTime put = projectUserTimeRepository.findByUserIdAndProjectIdAndTime(admin.getId(), project.getId(), DateKit.getDate(date + "-01 00:00:00", DateKit.TIME_FORMAT));
if (put == null) {
put = new ProjectUserTime();
// ProjectUserTime put = projectUserTimeRepository.findByUserIdAndProjectIdAndTime(admin.getId(), project.getId(), date);
ProjectUserTime put = new ProjectUserTime();
put.setCreatedBy(InterfaceUtil.getAdminId());
put.setCreatedTime(new Date());
put.setTime(DateKit.getDate(date, "yyyy-MM"));
put.setTime(date);
put.setProjectId(project.getId());
put.setProjectName(project.getName());
put.setUserName(admin.getRealName());
put.setUserId(admin.getId());
}
put.setUserCost(userCost);
put.setUserSalary(userSalary);
@ -173,6 +171,8 @@ public class HumanCostService {
}
}
if (errorCount == 0) {
int row = projectUserTimeRepository.deleteByTime(date);
logger.info("删除重复条目:" + row + "条");
projectUserTimeRepository.save(saveList);
}
final ResponseMsg msg = ResponseMsg.buildSuccessMsg(String.format("成功:%d, 失败:%d", successCount, errorCount));
@ -205,4 +205,13 @@ public class HumanCostService {
}
return columns;
}
public BigDecimal sum(ConcurrentHashMap<String, String> searchInfo, Admin admin) {
List<ProjectUserTime> sum = projectUserTimeRepositoryImpl.sum(searchInfo, admin);
if(CollectionUtil.isNotEmpty(sum)){
BigDecimal result = sum.stream().map((ProjectUserTime t) -> t.getUserCost().multiply(t.getUserSalary())).reduce(BigDecimal.ZERO, BigDecimal::add);
return result;
}
return new BigDecimal(0);
}
}

View File

@ -29,16 +29,14 @@
<td colspan="2">
<div align='right'>
<#-- <@shiro.hasPermission name="HUMAN_QUERY">-->
<@shiro.hasPermission name="HUMAN_QUERY">
<button type="button" class="am-btn am-btn-default am-btn-sm am-text-secondary"
id="submit-btn">搜索
</button>
<#-- </@shiro.hasPermission>-->
<#-- <@shiro.hasPermission name="HUMAN_EXPORT">-->
<button type="button" class="am-btn am-btn-default am-btn-sm am-text-secondary"
id="submit-btn-export">导出
</button>
<#-- </@shiro.hasPermission>-->
</@shiro.hasPermission>
</div>
</td>
</tr>

View File

@ -85,23 +85,21 @@
<div class="am-u-sm-10">
<div class="am-form am-form-inline">
<div class="am-form-group am-form-icon">
<input type="text" id="time" autocomplete="off" value="${time!}">
<input type="text" id="time" autocomplete="off" readonly value="${time!}">
</div>
</div>
</div>
</td>
<td colspan="4">
<div align='right'>
<#-- <@shiro.hasPermission name="HUMAN_COST_QUERY">-->
<@shiro.hasPermission name="HUMAN_COST_QUERY">
<button type="button" class="am-btn am-btn-default am-btn-sm am-text-secondary"
id="submit-btn">搜索
</button>
<#-- </@shiro.hasPermission>-->
<#-- <@shiro.hasPermission name="HUMAN_COST_QUERY">-->
<button type="button" class="am-btn am-btn-default am-btn-sm am-text-secondary"
id="submit-btn-export">导出
</button>
<#-- </@shiro.hasPermission>-->
</@shiro.hasPermission>
</div>
</td>
</tr>
@ -113,19 +111,18 @@
<div class="am-u-sm-12 am-u-md-12" style="padding:0 1.6rem 1.6rem 1rem;margin:0;">
<div class="am-btn-toolbar" style="padding-left:.5rem;">
<div class="am-btn-group am-btn-group-xs">
<#-- <@shiro.hasPermission name="HUMAN_COST_IMPORT">-->
<@shiro.hasPermission name="HUMAN_COST_IMPORT">
<div class="am-btn-group am-btn-group-xs am-form-file">
<button type="button" id="importAccount" class="am-btn am-btn-default"><span
<button type="button" id="importAccount" onclick="windows()" class="am-btn am-btn-default"><span
class="am-icon-archive"></span> 批量导入
</button>
<input id="doc-form-file" type="file" name="file"
onChange="ajaxUploadFile('doc-form-file','${base}/humanCost/batchImport')"
multiple>
</div>
<button type="button" id="importTemplate" class="am-btn am-btn-default" >
<span class="am-icon-arrow-circle-down"></span> 导入模板
</button>
<#-- </@shiro.hasPermission>-->
</@shiro.hasPermission>
成本总计:${(total!0)?string("0.##")}
</div>
</div>
</div>
@ -182,7 +179,6 @@
</div>
</div>
<footer class="admin-content-footer">
<hr>
</footer>
@ -190,7 +186,7 @@
</@defaultLayout.layout>
<script src="../assets/js/jquery.ajaxfileupload.js"></script>
<script src="../assets/js/amazeui.switch.js"></script>
<script src="${base}/layui/layui.js"></script>
<script src="../layui/layui.js"></script>
<script type="text/javascript">
layui.use('laydate', function(){
var laydate = layui.laydate;
@ -206,6 +202,33 @@
});
});
function windows() {
layui.use('layer', function(){
var layer = layui.layer;
var html = '<input type="text" name="layTime" id="layTime" class="form-control layer-date" readonly required value="${time!}">\n' +
'<input id="doc-form-file" type="file" name="file" onChange="ajaxUploadFile(\'doc-form-file\',\'${base}/humanCost/batchImport\')">'
layer.open({
type: 1,
title: "选择导入时间",
offset: '0px',
id: 'layerDemo',
content: html,
area: ['400px', '400px'],
success: function (layero, index) {
layui.laydate.render({
elem: "#layTime",
type: 'month',
btns: ['confirm'],
trigger: 'click',
ready: function(date){
console.log(date);
}
});
}
});
});
};
/**
*导入模板下载
*/
@ -214,22 +237,15 @@
});
function ajaxUploadFile(id, url) {
// if ($('#modal')) {
// $('#modal').modal('open');
// $('#span-' + id).html("&nbsp;&nbsp;&nbsp;&nbsp;数据正在导入,请等待");
// }
$("#exportFaildButton").hide();
var date = $("#layTime").val();
console.log("date:" + date);
$.ajaxFileUpload({
url: url,
url: url + '?date=' + date,
secureuri: false,
fileElementId: id,// file标签的id
dataType: 'json',// 返回数据的类型
success: function (data, status) {
console.log("--------success---------" + data)
// if($('#modal')){
// $('#modal').modal('close');
// $('#span-'+id).html("导入完成");
// }
if(data.status ==0) {
var list = data.data;
var content = '';
@ -251,9 +267,6 @@
error: function (data, status, e) {
console.log("--------error---------" + data)
alert("-----------------" + data);
if ($('#modal')) {
$('#modal').modal('close');
}
alert(e);
$("#" + id).val("");
}

View File

@ -62,7 +62,7 @@
<td><input name="incomeDeviceBudgetTotal" type="number" value="${Utils.format(budgetBean.incomeDeviceTaxExclude,'0')}" required readonly title="设备类预算总额"></td>
<td><input name="incomeDeviceFormerSettleTotal" type="number" value="${Utils.format(formerBean.incomeDeviceTaxExclude,'0')}" required readonly title="设备类上月结算总额"></td>
<td><input type="number" min="0.00" max="99999999.99" step="0.01" name="incomeDevice" required title="本月结算金额"></td>
<td><input type="number" name="incomeDeviceSettleTotal" readonly title="设备类结算总额"></td>
<td><input type="number" name="incomeDeviceSettleTotal" readonly title="设备类结算总额" data-validate-async data-validation-message="结算总额不能大于预算总额" ></td>
</tr>
<tr>
<td>收入</td>
@ -411,6 +411,66 @@
<script src="${base}/assets/js/project_common.js"></script>
<script src="${base}/assets/js/project_settle.js"></script>
<script>
$(function () {
/*表单验证begin*/
//自定义规则用法验证元素上加class="js-pattern-sort"
if ($.AMUI && $.AMUI.validator) {
$.AMUI.validator.patterns.sort = /^([0-9]+)$/;
}
$("#tmpForm").validator({
// 域通过验证时回调
onValid: function (validity) {
$(validity.field).closest('.am-form-group').find('.am-alert').hide();
},
// 域验证通过时添加的操作,通过该接口可定义各种验证提示
markValid: function (validity) {
// this is Validator instance
var $field = $(validity.field);
//add by zxl只对有required属性的字段进行验证
if (typeof ($field.attr("required")) != "undefined") {
var options = this.options;
var $parent = $field.closest('.am-form-group');
$field.addClass(options.validClass).removeClass(options.inValidClass);
$parent.addClass('am-form-success').removeClass('am-form-error');
options.onValid.call(this, validity);
}
},
// 验证出错时的回调, validity 对象包含相关信息,格式通 H5 表单元素的 validity 属性
onInValid: function (validity) {
var $field = $(validity.field);
var $group = $field.closest('.am-form-group');
var $alert = $group.find('.am-alert');
// 使用自定义的提示信息 或 插件内置的提示信息
var msg = $field.data('validationMessage') || this.getValidationMessage(validity);
if (!$alert.length) {
$alert = $("<div class='am-alert am-alert-danger'></div>").hide().appendTo($group.find(".input-msg"));
}
console.log("onInValid : " + $field.val());
$alert.html(msg).show();
},
//自定义验证
validate: function (validity) {
var $field = $(validity.field);
var validityIdCard = function () {
var settle = $("#incomeDeviceSettleTotal").val();
var budget = $("#incomeDeviceBudgetTotal").val();
if (settle > budget) {
$myField = $field;
myMsg = "身份证信息不合法!";
validity.valid = false;
}
};
if ($(validity.field).is('#incomeDeviceSettleTotal')) {
validityIdCard();
};
}
});
/*表单验证end*/
});
// layui.use('laydate', function(){
// var laydate = layui.laydate;