Commit a6cfb4b8 by HlQ

[add]

1.项目资料文件导出
2.新增合同列表接口
[fix] 合同更新bug修改
1 parent 8112bb65
......@@ -59,6 +59,12 @@ public class ContractController {
return contractService.listPart(dto);
}
@GetMapping("/contractMain")
@SaCheckPermission(value = "contract:listMain", orRole = "admin")
public Page<ContractVO> listMain(ContractDTO dto) {
return contractService.listByMain(dto);
}
@GetMapping("/contract/{id}")
@SaCheckPermission(value = "contract:query", orRole = "admin")
public ContractVO getById(@PathVariable Long id) {
......@@ -73,7 +79,7 @@ public class ContractController {
@PostMapping("/contract/{id}")
@SaCheckPermission(value = "contract:edit", orRole = "admin")
public String updateById(@PathVariable Long id, @RequestBody ContractDTO dto) {
public String updateById(@PathVariable Long id, ContractDTO dto) {
return contractService.updateById(id, null, dto);
}
......
......@@ -5,6 +5,7 @@ import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.github.linpeilie.Converter;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.array.ArrayUtil;
......@@ -239,4 +240,11 @@ public class StoreController {
Assert.notEmpty(userIdStr, "未选择提醒人");
return storeService.fileNotify(storeName, contractNo, sourceName, fileNameArr, userIdStr) ? "钉钉提醒成功" : "钉钉提醒失败";
}
@PostMapping("/store/file/export")
@SaCheckPermission(value = "store:file:export", orRole = "admin")
public void storeFileExport(StoreDTO data, @RequestBody(required = false) List<OrderItem> orderItemList,
HttpServletResponse response) {
storeService.storeFileExport(data, orderItemList, response);
}
}
......@@ -340,7 +340,7 @@ public class ContractRunner {
var jsonR = JSONUtil.ofObj()
.set("sortMap", JSONUtil.ofObj()
.set("field", "updateTime")
.set("order", "desc"))
.set("sort", "desc"))
.set("conditions", JSONUtil.ofArray()
.put(JSONUtil.ofObj()
.set("attr", "date_3")
......
......@@ -25,6 +25,8 @@ public interface IContractService extends MPJBaseService<Contract> {
Page<ContractVO> listPart(ContractDTO dto);
Page<ContractVO> listByMain(ContractDTO dto);
ContractVO getVOById(Long id);
ContractVO getByNo(@PathVariable String no);
......
......@@ -3,6 +3,7 @@ package vion.service;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestParam;
import vion.dto.StatusDTO;
import vion.dto.StoreDTO;
......@@ -38,4 +39,8 @@ public interface IStoreService extends MPJBaseService<Store> {
Boolean fileNotify(String storeName, String contractNo, String sourceName, String[] fileNameArr, String[] userIdStr);
void storeFileExport(StoreDTO data, List<OrderItem> orderItemList, HttpServletResponse response);
}
......@@ -12,6 +12,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.bean.copier.CopyOptions;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.collection.set.SetUtil;
......@@ -33,14 +34,15 @@ import org.dromara.hutool.http.meta.Method;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vion.dto.ContractDTO;
import vion.dto.RContractTeamDTO;
import vion.mapper.ContractMapper;
import vion.mapper.SettlementDiffMapper;
import vion.model.*;
import vion.model.Dictionary;
import vion.model.*;
import vion.service.*;
import vion.third.DingMod;
import vion.vo.*;
......@@ -141,6 +143,63 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
return Page.<ContractVO>of(contractList.getCurrent(), contractList.getSize(), contractList.getTotal()).setRecords(contractVOList);
}
@Override
public Page<ContractVO> listByMain(ContractDTO dto) {
Result result = getResult(dto);
Page<ContractVO> page = Page.of(dto.getPageNum(), dto.getPageSize());
Opt.ofNullable(dto.getOrderItem())
.ifPresent(page::addOrder);
Page<ContractVO> contractVOList = this.selectJoinListPage(page, ContractVO.class, result.wrapper);
var idList = Opt.ofEmptyAble(contractVOList.getRecords())
.map(r -> r.stream().map(ContractVO::getId).collect(Collectors.toList()))
.orElse(ListUtil.empty());
var contractStoreList = contractStoreService.lambdaQuery().in(RContractStore::getContractId, idList).list();
var contractId2StoresMap = Opt.ofEmptyAble(contractStoreList)
.map(l -> l.stream().collect(Collectors.groupingBy(RContractStore::getContractId,
Collectors.mapping(RContractStore::getStoreId, Collectors.toList()))))
.orElse(Map.of());
var storeMap = Opt.ofEmptyAble(contractStoreList)
.map(cs -> cs.stream().map(RContractStore::getStoreId).toList())
.map(storeIds -> Db.listByIds(storeIds, Store.class).stream().collect(Collectors.toMap(Store::getId, Function.identity())))
.orElse(Map.of());
// 结算差异
Opt.ofEmptyAble(idList)
.map(l -> settlementDiffMapper.selectList(Wrappers.<SettlementDiff>lambdaQuery()
.in(SettlementDiff::getContractId, l)))
.map(list -> list.stream().collect(Collectors.groupingBy(SettlementDiff::getContractId, Collectors.reducing(BigDecimal.ZERO, SettlementDiff::getSettlementDiff, BigDecimal::add))))
.ifPresent(map -> contractVOList.getRecords().forEach(vo -> vo.setDiffAmount(map.getOrDefault(vo.getId(), BigDecimal.ZERO))));
// 合同绑定销售
Opt.ofEmptyAble(idList)
.map(l -> contractUserService.lambdaQuery()
.in(RContractUser::getContractId, l)
.list())
.map(list -> list.stream().collect(Collectors.groupingBy(RContractUser::getContractId)))
.ifPresent(map -> contractVOList.getRecords().forEach(vo -> map.getOrDefault(vo.getId(), ListUtil.empty()).stream()
.max(Comparator.comparing(RContractUser::getEnterDate))
.map(RContractUser::getUsername)
.ifPresent(vo::setSaleName)));
contractVOList.getRecords().forEach(vo -> {
vo.setCustomerName(null);
vo.setTotalAmount(null);
vo.setPaidAmount(null);
vo.setReceivableAmount(null);
vo.setOutstandingAmount(null);
vo.setInvoiceAmount(null);
vo.setDiffAmount(null);
var collect = contractId2StoresMap.getOrDefault(vo.getId(), List.of()).stream()
.map(storeMap::get)
.collect(Collectors.toList());
vo.setStoreVOS(converter.convert(collect, StoreVO.class));
});
completeStoreName(contractVOList.getRecords());
return contractVOList;
}
/**
* 查出合同关联的项目名
*
......@@ -221,9 +280,11 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
}
Assert.isFalse(BeanUtil.isEmpty(existContract), "合同不存在");
// todo 如果当前合同进度在要修改的进度前,此时不能修改合同进度。e.g 当前合同进度是项目验收,此时传参过来到货,那么不能修改
Contract contract = converter.convert(dto, Contract.class);
// 如果当前合同进度在要修改的进度前,此时不能修改合同进度。e.g 当前合同进度是项目验收,此时传参过来到货,那么不能修改
if (contract.getStatus() < existContract.getStatus()) {
contract.setStatus(null);
}
Long contractId = existContract.getId();
String existContractNo = existContract.getContractNo();
contract.setId(contractId);
......@@ -240,6 +301,10 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
Contract finalExistContract = existContract;
Opt.ofNullable(dto.getStatus())
.ifPresent(status -> {
// 当前合同进度在要修改的进度前,不再推送钉钉消息和记录日志
if (ObjUtil.isNull(contract.getStatus())) {
return;
}
String useridStr = Opt.ofEmptyAble(contractUserService.lambdaQuery()
.eq(RContractUser::getContractNo, existContractNo).list())
.map(l -> l.stream().map(RContractUser::getContractNo).collect(Collectors.joining(",")))
......@@ -247,27 +312,27 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
ContractLog contractLog = new ContractLog();
contractLog.setContractNo(existContractNo);
if (status == 1) {
if (status.equals(1)) {
contractLog.setContent("合同:已签订");
} else if (status == 2) {
} else if (status.equals(2)) {
contractLog.setContent("合同:已到货");
} else if (status == 3) {
} else if (status.equals(3)) {
contractLog.setContent("合同:系统验收");
dingMod.workMsg(buildMsg(useridStr, dto, finalExistContract, "系统验收(初验)"));
} else if (status == 4) {
} else if (status.equals(4)) {
contractLog.setContent("合同:项目验收");
dingMod.workMsg(buildMsg(useridStr, dto, finalExistContract, "项目验收(终验)"));
} else if (status == 5) {
} else if (status.equals(5)) {
contractLog.setContent("合同:质保");
} else if (status == 6) {
} else if (status.equals(6)) {
contractLog.setContent("合同:第一笔维保款");
} else if (status == 7) {
} else if (status.equals(7)) {
contractLog.setContent("合同:第二笔维保款");
} else if (status == 8) {
} else if (status.equals(8)) {
contractLog.setContent("合同:第三笔维保款");
} else if (status == 9) {
} else if (status.equals(9)) {
contractLog.setContent("合同:维保进度款");
} else if (status == 10) {
} else if (status.equals(10)) {
contractLog.setContent("合同:维保验收款");
}
contractLog.setOperator(userVO.getId());
......@@ -777,23 +842,18 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
}
/*
* todo
* 1.校验合同数量,以及合同编号
* 2.校验合同金额
* */
public JSONObject ver() {
var contractNoList = this.listObjs(v -> ((Contract) v).getContractNo());
@Scheduled(cron = "0 0 8 * * ?")
public void verifyNum() {
var contractNoList = this.listObjs(Wrappers.<Contract>lambdaQuery().select(Contract::getContractNo),
Object::toString);
var json = JSONUtil.ofObj()
.set("sortMap", JSONUtil.ofObj()
.set("field", "updateTime")
.set("sort", "desc"))
.set("conditions", JSONUtil.ofArray()
.put(JSONUtil.ofObj()
.set("attr", "date_3")
.set("symbol", "greaterequal")
.set("value", new String[]{"1715356800"}))
)
.set("corpid", corpId)
.set("formId", 8429903)
.set("pageSize", 100);
......@@ -805,13 +865,11 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
var jobO = JSONUtil.parseObj(res.bodyStr());
if (jobO.getInt("code") != 1) {
log.error("获取合同列表失败,错误原因:{}", jobO);
return json;
}
Integer cnt = jobO.getJSONObject("result").getInt("totalCount");
Integer page = jobO.getJSONObject("result").getInt("totalPage");
if (NumberUtil.equals(cnt, 0)) {
log.info("没有需要插入或更新的合同");
return json;
}
var jsonArray = jobO.getJSONObject("result").getJSONArray("list");
// 合同编号
......@@ -822,13 +880,7 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
var jsonR = JSONUtil.ofObj()
.set("sortMap", JSONUtil.ofObj()
.set("field", "updateTime")
.set("order", "desc"))
.set("conditions", JSONUtil.ofArray()
.put(JSONUtil.ofObj()
.set("attr", "date_3")
.set("symbol", "greaterequal")
.set("value", new String[]{"1715356800"}))
)
.set("sort", "desc"))
.set("corpid", corpId)
.set("formId", 8429903)
.set("page", i)
......@@ -848,122 +900,199 @@ public class ContractServiceImpl extends MPJBaseServiceImpl<ContractMapper, Cont
var unsyncedList = CollUtil.subtractToList(dataIdSet, contractNoList);
// 返回项目运维管理平台存在,但销帮帮不存在的合同(可能销帮帮对该合同删除了)
var extraList = CollUtil.subtractToList(contractNoList, dataIdSet);
return JSONUtil.ofObj().set("unsynced", unsyncedList).set("extra", extraList);
// 两平台共存的合同
log.info("合同编号验证:{}", JSONUtil.ofObj().set("unsynced", unsyncedList).set("extra", extraList));
var sameList = CollUtil.intersectionDistinct(dataIdSet, contractNoList);
contractDiff(sameList);
}
public JSONObject contractDiff(String contractNo) {
var platContract = this.lambdaQuery().eq(Contract::getContractNo, contractNo).one();
/**
* 校验两系统都存在的合同的差异,记录差异合同
*/
public void contractDiff(Set<String> contractNoList) {
for (String contractNo : contractNoList) {
var wrapper = new MPJLambdaWrapper<Contract>()
.selectCollection(ContractPayment.class, ContractVO::getContractPayments)
.leftJoin(ContractPayment.class, ContractPayment::getContractId, Contract::getId)
.eq(Contract::getContractNo, contractNo);
var platContractVO = this.selectJoinOne(ContractVO.class, wrapper);
var platContract = Opt.ofEmptyAble(platContractVO.getContractPayments())
.map(cps -> {
var contract = converter.convert(platContractVO, Contract.class);
cps.forEach(cp -> {
if (ObjUtil.equals(cp.getPaymentType(), 1) && ObjUtil.notEquals(cp.getPaymentRatio(),
BigDecimal.ZERO)) {
contract.setSignRatio(cp.getPaymentRatio());
contract.setSignDate1(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 2) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setArriveRatio(cp.getPaymentRatio());
contract.setArriveDate(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 3) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setSystemCheckRatio(cp.getPaymentRatio());
contract.setSystemCheckDate(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 4) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setProjectCheckRatio(cp.getPaymentRatio());
contract.setProjectCheckDate(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 5) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setWarrantyRatio(cp.getPaymentRatio());
contract.setWarrantyDate(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 6) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setMaintainRatio1(cp.getPaymentRatio());
contract.setMaintainDate1(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 7) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setMaintainRatio2(cp.getPaymentRatio());
contract.setMaintainDate2(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 8) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setMaintainRatio3(cp.getPaymentRatio());
contract.setMaintainDate3(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 9) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setMaintainProgressRatio(cp.getPaymentRatio());
contract.setMaintainProgressDate(cp.getPaymentDate());
} else if (ObjUtil.equals(cp.getPaymentType(), 10) && ObjUtil.notEquals(cp.getPaymentRatio(), BigDecimal.ZERO)) {
contract.setMaintainAcceptanceRatio(cp.getPaymentRatio());
contract.setMaintainAcceptanceDate(cp.getPaymentDate());
}
});
return contract;
}).orElse(new Contract());
var copyOptions = CopyOptions.of().setIgnoreProperties(Contract::getId, Contract::getStatus,
Contract::getPaidAmount,
Contract::getReceivableAmount, Contract::getOutstandingAmount, Contract::getSubject,
Contract::getRemark, Contract::getCreateUser, Contract::getModifyUser, Contract::getCreateTime,
Contract::getModifyTime, Contract::getFinalDate, Contract::getInvoiceAmount,
Contract::getFinancialStatus, Contract::getOriginalModTime)
.ignoreNullValue();
var platMap = BeanUtil.beanToMap(platContract, new HashMap<>(), copyOptions);
var json = JSONUtil.ofObj()
.set("conditions", JSONUtil.ofArray()
.put(JSONUtil.ofObj()
.set("attr", "serialNo")
.set("symbol", "equal")
.set("value", new String[]{contractNo}))
)
.set("corpid", corpId)
.set("formId", 8429903)
.set("pageSize", 100);
var res = Request.of("https://proapi.xbongbong.com/pro/v2/api/contract/list")
.header("sign", SecureUtil.sha256(json.toString() + token))
.body(json.toString())
.method(Method.POST)
.send();
var jobO = JSONUtil.parseObj(res.bodyStr());
if (jobO.getInt("code") != 1) {
log.error("获取合同列表失败,错误原因:{}", jobO);
}
var jsonArray = jobO.getJSONObject("result").getJSONArray("list");
// 合同记录唯一 dataId
var dataIdSet = jsonArray.stream().map(v -> JSONUtil.parseObj(v).getInt("dataId")).collect(Collectors.toSet());
var json = JSONUtil.ofObj()
.set("conditions", JSONUtil.ofArray()
.put(JSONUtil.ofObj()
.set("attr", "serialNo")
.set("symbol", "equal")
.set("value", new String[]{contractNo}))
)
.set("corpid", corpId)
.set("formId", 8429903)
.set("pageSize", 100);
var res = Request.of("https://proapi.xbongbong.com/pro/v2/api/contract/list")
.header("sign", SecureUtil.sha256(json.toString() + token))
.body(json.toString())
.method(Method.POST)
.send();
var jobO = JSONUtil.parseObj(res.bodyStr());
if (jobO.getInt("code") != 1) {
log.error("获取合同列表失败,错误原因:{}", jobO);
return json;
var json1 = JSONUtil.ofObj()
.set("corpid", corpId)
.set("dataId", CollUtil.getFirst(dataIdSet));
var res1 = Request.of("https://proapi.xbongbong.com/pro/v2/api/contract/detail")
.header("sign", SecureUtil.sha256(json1.toString() + token))
.body(json1.toString())
.method(Method.POST)
.send();
var jobj1 = JSONUtil.parseObj(res1.bodyStr());
if (jobj1.getInt("code") != 1) {
log.error("获取合同详情失败,错误原因:{}", jobj1);
}
var result = jobj1.getJSONObject("result");
var jsonObj1 = result.getJSONObject("data");
Map<String, Integer> contractTypeMap = Db.list(Wrappers.lambdaQuery(Dictionary.class).eq(Dictionary::getType,
"contract_type"))
.stream()
.collect(Collectors.toMap(Dictionary::getValue, Dictionary::getKey));
Contract xbongContract = new Contract();
xbongContract.setName(jsonObj1.getStr("text_14"));
xbongContract.setContractNo(jsonObj1.getStr("serialNo"));
xbongContract.setType(contractTypeMap.getOrDefault(jsonObj1.getJSONObject("text_17").getStr("text"), 0));
xbongContract.setSignDate(DateUtil.date(jsonObj1.getLong("date_1") * 1000).toJdkDate());
xbongContract.setMaintainSdate(Opt.ofNullable(jsonObj1.getLong("date_4")).map(sec -> DateUtil.date(sec * 1000).toJdkDate()).orElse(null));
xbongContract.setMaintainEdate(Opt.ofNullable(jsonObj1.getLong("date_5")).map(sec -> DateUtil.date(sec * 1000).toJdkDate()).orElse(null));
String warrantyPeriod = Opt.ofNullable(jsonObj1.getJSONObject("text_23")).map(wp -> wp.getStr("text")).orElse("");
if (StrUtil.isNotBlank(warrantyPeriod) && warrantyPeriod.contains("个月")) {
String substring = warrantyPeriod.substring(0, (warrantyPeriod.length() - 2));
xbongContract.setWarrantyPeriod(Integer.parseInt(substring));
}
xbongContract.setStatus(1);
xbongContract.setTotalAmount(jsonObj1.getBigDecimal("num_1"));
xbongContract.setPaidAmount(BigDecimal.ZERO);
xbongContract.setReceivableAmount(BigDecimal.ZERO);
xbongContract.setOutstandingAmount(jsonObj1.getBigDecimal("num_1"));
var paymentForm = jsonObj1.getJSONArray("subForm_1");
if (!paymentForm.isEmpty()) {
paymentForm.forEach(pf -> {
var pfObj = JSONUtil.parseObj(pf);
var ratio = NumberUtil.div(BigDecimal.valueOf(Double.parseDouble(pfObj.getStr("text_1"))), 100);
var date = DateUtil.date(pfObj.getLong("date_1") * 1000);
var stage = pfObj.getJSONObject("text_2").getStr("text");
if (StrUtil.equals(stage, "预付款")) {
xbongContract.setSignRatio(ratio);
xbongContract.setSignDate1(date);
} else if (StrUtil.equals(stage, "到货款")) {
xbongContract.setArriveRatio(ratio);
xbongContract.setArriveDate(date);
} else if (StrUtil.equals(stage, "系统验收款")) {
xbongContract.setSystemCheckRatio(ratio);
xbongContract.setSystemCheckDate(date);
} else if (StrUtil.equals(stage, "项目终验款")) {
xbongContract.setProjectCheckRatio(ratio);
xbongContract.setProjectCheckDate(date);
} else if (StrUtil.equals(stage, "质保款")) {
xbongContract.setWarrantyRatio(ratio);
xbongContract.setWarrantyDate(date);
} else if (StrUtil.equals(stage, "维保第一笔款")) {
xbongContract.setMaintainRatio1(ratio);
xbongContract.setMaintainDate1(date);
} else if (StrUtil.equals(stage, "维保第二笔款")) {
xbongContract.setMaintainRatio2(ratio);
xbongContract.setMaintainDate2(date);
} else if (StrUtil.equals(stage, "维保第三笔款")) {
xbongContract.setMaintainRatio3(ratio);
xbongContract.setMaintainDate3(date);
} else if (StrUtil.equals(stage, "维保进度款")) {
xbongContract.setMaintainProgressRatio(ratio);
xbongContract.setMaintainProgressDate(date);
} else if (StrUtil.equals(stage, "维保验收款")) {
xbongContract.setMaintainAcceptanceRatio(ratio);
xbongContract.setMaintainAcceptanceDate(date);
}
});
}
xbongContract.setSubject("北京文安智能技术股份有限公司");
xbongContract.setCustomerName(jsonObj1.getJSONObject("text_2").getStr("name"));
xbongContract.setSaleName(jsonObj1.getJSONObject("text_8").getStr("name"));
xbongContract.setCreateUser(-1L);
xbongContract.setModifyUser(-1L);
xbongContract.setEntryTime(DateUtil.date(result.getLong("addTime") * 1000).toJdkDate());
xbongContract.setOriginalModTime(DateUtil.date(result.getLong("updateTime") * 1000).toJdkDate());
var bongMap = BeanUtil.beanToMap(xbongContract, new HashMap<>(), copyOptions);
if (!mapEqual(platMap, bongMap)) {
log.info("不一致的合同:{}", contractNo);
}
}
var jsonArray = jobO.getJSONObject("result").getJSONArray("list");
// 合同记录唯一 dataId
var dataIdSet = jsonArray.stream().map(v -> JSONUtil.parseObj(v).getInt("dataId")).collect(Collectors.toSet());
}
var json1 = JSONUtil.ofObj()
.set("corpid", corpId)
.set("dataId", CollUtil.getFirst(dataIdSet));
var res1 = Request.of("https://proapi.xbongbong.com/pro/v2/api/contract/detail")
.header("sign", SecureUtil.sha256(json1.toString() + token))
.body(json1.toString())
.method(Method.POST)
.send();
var jobj1 = JSONUtil.parseObj(res1.bodyStr());
if (jobj1.getInt("code") != 1) {
log.error("获取合同详情失败,错误原因:{}", jobj1);
return json;
public <K, V> boolean mapEqual(Map<K, V> map1, Map<K, V> map2) {
if (map1.size() != map2.size()) {
return false;
}
var result = jobj1.getJSONObject("result");
var jsonObj1 = result.getJSONObject("data");
Map<String, Integer> contractTypeMap = Db.list(Wrappers.<Dictionary>lambdaQuery().eq(Dictionary::getType, "contract_type"))
.stream()
.collect(Collectors.toMap(Dictionary::getValue, Dictionary::getKey));
Contract xbongContract = new Contract();
xbongContract.setName(jsonObj1.getStr("text_14"));
xbongContract.setContractNo(jsonObj1.getStr("serialNo"));
xbongContract.setType(contractTypeMap.getOrDefault(jsonObj1.getJSONObject("text_17").getStr("text"), 0));
xbongContract.setSignDate(DateUtil.date(jsonObj1.getLong("date_1") * 1000));
xbongContract.setMaintainSdate(Opt.ofNullable(jsonObj1.getLong("date_4")).map(sec -> DateUtil.date(sec * 1000)).orElse(null));
xbongContract.setMaintainEdate(Opt.ofNullable(jsonObj1.getLong("date_5")).map(sec -> DateUtil.date(sec * 1000)).orElse(null));
String warrantyPeriod = Opt.ofNullable(jsonObj1.getJSONObject("text_23")).map(wp -> wp.getStr("text")).orElse("");
if (StrUtil.isNotBlank(warrantyPeriod) && warrantyPeriod.contains("个月")) {
String substring = warrantyPeriod.substring(0, (warrantyPeriod.length() - 2));
xbongContract.setWarrantyPeriod(Integer.parseInt(substring));
}
xbongContract.setStatus(1);
xbongContract.setTotalAmount(jsonObj1.getBigDecimal("num_1"));
xbongContract.setPaidAmount(BigDecimal.ZERO);
xbongContract.setReceivableAmount(BigDecimal.ZERO);
xbongContract.setOutstandingAmount(jsonObj1.getBigDecimal("num_1"));
var paymentForm = jsonObj1.getJSONArray("subForm_1");
if (!paymentForm.isEmpty()) {
paymentForm.forEach(pf -> {
var pfObj = JSONUtil.parseObj(pf);
var ratio = NumberUtil.div(BigDecimal.valueOf(Double.parseDouble(pfObj.getStr("text_1"))), 100);
var date = DateUtil.date(pfObj.getLong("date_1") * 1000);
var stage = pfObj.getJSONObject("text_2").getStr("text");
if (StrUtil.equals(stage, "预付款")) {
xbongContract.setSignRatio(ratio);
xbongContract.setSignDate1(date);
} else if (StrUtil.equals(stage, "到货款")) {
xbongContract.setArriveRatio(ratio);
xbongContract.setArriveDate(date);
} else if (StrUtil.equals(stage, "系统验收款")) {
xbongContract.setSystemCheckRatio(ratio);
xbongContract.setSystemCheckDate(date);
} else if (StrUtil.equals(stage, "项目终验款")) {
xbongContract.setProjectCheckRatio(ratio);
xbongContract.setProjectCheckDate(date);
} else if (StrUtil.equals(stage, "质保款")) {
xbongContract.setWarrantyRatio(ratio);
xbongContract.setWarrantyDate(date);
} else if (StrUtil.equals(stage, "维保第一笔款")) {
xbongContract.setMaintainRatio1(ratio);
xbongContract.setMaintainDate1(date);
} else if (StrUtil.equals(stage, "维保第二笔款")) {
xbongContract.setMaintainRatio2(ratio);
xbongContract.setMaintainDate2(date);
} else if (StrUtil.equals(stage, "维保第三笔款")) {
xbongContract.setMaintainRatio3(ratio);
xbongContract.setMaintainDate3(date);
} else if (StrUtil.equals(stage, "维保进度款")) {
xbongContract.setMaintainProgressRatio(ratio);
xbongContract.setMaintainProgressDate(date);
} else if (StrUtil.equals(stage, "维保验收款")) {
xbongContract.setMaintainAcceptanceRatio(ratio);
xbongContract.setMaintainAcceptanceDate(date);
}
});
for (Map.Entry<K, V> entry : map1.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
if (!map2.containsKey(key) || ObjUtil.notEquals(value, map2.get(key))) {
return false;
}
}
xbongContract.setSubject("北京文安智能技术股份有限公司");
xbongContract.setCustomerName(jsonObj1.getJSONObject("text_2").getStr("name"));
xbongContract.setSaleName(jsonObj1.getJSONObject("text_8").getStr("name"));
xbongContract.setCreateUser(-1L);
xbongContract.setModifyUser(-1L);
xbongContract.setEntryTime(DateUtil.date(result.getLong("addTime") * 1000));
xbongContract.setOriginalModTime(DateUtil.date(result.getLong("updateTime") * 1000));
return JSONUtil.ofObj().set("platform", platContract).set("xbongbong", xbongContract);
return true;
}
}
\ No newline at end of file
......@@ -5,9 +5,13 @@ import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.github.liaochong.myexcel.core.DefaultExcelBuilder;
import com.github.liaochong.myexcel.core.watermark.Watermark;
import com.github.liaochong.myexcel.utils.WatermarkUtil;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.array.ArrayUtil;
......@@ -39,13 +43,16 @@ import vion.mapper.TaskMapper;
import vion.model.*;
import vion.service.*;
import vion.third.DingMod;
import vion.utils.excel.AttachmentExportUtil;
import vion.vo.ContractVO;
import vion.vo.StoreVO;
import vion.vo.TagVO;
import vion.vo.UserVO;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
......@@ -541,6 +548,79 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
return StrUtil.containsIgnoreCase(pushRes, "ok");
}
@Override
public void storeFileExport(StoreDTO data, List<OrderItem> orderItemList, HttpServletResponse response) {
UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
Page<StoreVO> voPage = this.getStoreList(data, orderItemList);
try (DefaultExcelBuilder<Map> defaultExcelBuilder = DefaultExcelBuilder.of(Map.class)) {
var records = voPage.getRecords();
var storeIds = records.stream().map(StoreVO::getId).toList();
var titles = List.of("项目", "合同编号",
"前期勘察", "点位表",
"竣工图纸", "验收报告",
"项目总结", "巡检报告",
"结算资料", "其它");
var files = fileService.lambdaQuery()
.in(FileInfo::getSourceId, storeIds)
.in(FileInfo::getStoreId, storeIds)
.in(FileInfo::getSourceType, 1, 24, 25, 26, 27, 28, 29, 30)
.list();
var contractId2NoMap = Opt.ofEmptyAble(files)
.map(f -> f.stream().map(FileInfo::getContractId).toList())
.map(contractService::listByIds)
.filter(CollUtil::isNotEmpty)
.map(contractList -> contractList.stream().collect(Collectors.toMap(Contract::getId, Contract::getContractNo)))
.orElse(Map.of());
// storeId -> <contractId -> <sourceType -> cnt>>
var storeId2CntMap = Opt.ofEmptyAble(files)
.map(fs -> fs.stream().collect(Collectors.groupingBy(FileInfo::getStoreId,
Collectors.groupingBy(f -> Opt.ofNullable(f.getContractId()).orElse(-1L),
Collectors.groupingBy(FileInfo::getSourceType,
Collectors.counting())))))
.orElse(Map.of());
List<Map> dataList = new ArrayList<>();
storeId2CntMap.forEach((storeId, contractMap) -> {
var store = records.stream().filter(v -> v.getId().equals(storeId)).findFirst().orElse(null);
if (ObjUtil.isNull(store)) {
return;
}
contractMap.forEach((contractId, typeCntMap) -> {
var map = MapUtil.<String, Object>builder("a", store.getName())
.put("b", contractId2NoMap.getOrDefault(contractId, "暂无"))
.put("c", typeCntMap.getOrDefault(28, 0L))
.put("d", typeCntMap.getOrDefault(26, 0L))
.put("e", typeCntMap.getOrDefault(25, 0L))
.put("f", typeCntMap.getOrDefault(24, 0L))
.put("g", typeCntMap.getOrDefault(27, 0L))
.put("h", typeCntMap.getOrDefault(29, 0L))
.put("i", typeCntMap.getOrDefault(30, 0L))
.put("j", typeCntMap.getOrDefault(1, 0L))
.build();
dataList.add(map);
});
});
var workbook = defaultExcelBuilder.sheetName("项目资料")
.titles(titles)
.widths(10, 20)
.fieldDisplayOrder(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"))
.build(dataList);
// 水印添加指定字体,并在服务器上安装 SimSun 字体,解决中文字体变成方块的问题
Watermark watermark = new Watermark();
watermark.setText(user.getUsername() + "-" + user.getPhone());
watermark.setFont(new Font("SimSun", Font.PLAIN, 16));
WatermarkUtil.addWatermark(workbook, watermark);
AttachmentExportUtil.export(workbook, StrUtil.format("项目资料_{}", DateUtil.formatDateTime(new Date())),
response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
JSONObject buildMsg(String storeName, String userid) {
var jsonObj = JSONUtil.ofObj()
.set("agent_id", 2358374016L)
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!