From 864536b2f15b73eacbd3acff7b52d17eceb144b1 Mon Sep 17 00:00:00 2001 From: wangzhikun Date: Sat, 25 Mar 2023 16:12:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=AD=E8=AF=81=E5=90=8C=E6=AD=A5=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../erp/controller/InterfaceController.java | 41 ++- .../com/dxhy/erp/dao/VoucherRecordDao.java | 21 ++ .../dxhy/erp/dao/VoucherRecordItemDao.java | 17 ++ .../com/dxhy/erp/entity/VoucherRecord.java | 95 +++++++ .../dxhy/erp/entity/VoucherRecordItem.java | 115 ++++++++ .../erp/service/VoucherRecordItemService.java | 14 + .../erp/service/VoucherRecordService.java | 15 + .../service/impl/InvoiceAuthServiceImpl.java | 6 +- .../impl/VoucherRecordItemServiceImpl.java | 24 ++ .../impl/VoucherRecordServiceImpl.java | 118 ++++++++ .../dxhy/erp/utils/DistributedKeyMaker.java | 256 ++++++++++++++++++ .../main/resources/mapper/VoucherRecord.xml | 33 +++ .../resources/mapper/VoucherRecordItem.xml | 13 + 13 files changed, 761 insertions(+), 7 deletions(-) create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordDao.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordItemDao.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecord.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecordItem.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordItemService.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordService.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordItemServiceImpl.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordServiceImpl.java create mode 100644 dxhy-erp/src/main/java/com/dxhy/erp/utils/DistributedKeyMaker.java create mode 100644 dxhy-erp/src/main/resources/mapper/VoucherRecord.xml create mode 100644 dxhy-erp/src/main/resources/mapper/VoucherRecordItem.xml diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/controller/InterfaceController.java b/dxhy-erp/src/main/java/com/dxhy/erp/controller/InterfaceController.java index 8866fd7d..b05aa4f1 100644 --- a/dxhy-erp/src/main/java/com/dxhy/erp/controller/InterfaceController.java +++ b/dxhy-erp/src/main/java/com/dxhy/erp/controller/InterfaceController.java @@ -28,10 +28,7 @@ import com.dxhy.common.utils.R; import com.dxhy.common.utils.TripleDesUtil; import com.dxhy.common.vo.UserInfo; import com.dxhy.erp.dao.SysDeptDao; -import com.dxhy.erp.entity.BaseInvoiceEditVO; -import com.dxhy.erp.entity.SalesInvoicePushInfos; -import com.dxhy.erp.entity.SysDeptEntity; -import com.dxhy.erp.entity.TDxInvoiceReimburse; +import com.dxhy.erp.entity.*; import com.dxhy.erp.entity.V5.CheckResult; import com.dxhy.erp.entity.V5.DxhyInterfaceRequest; import com.dxhy.erp.entity.V5.DxhyInterfaceResponse; @@ -109,6 +106,8 @@ public class InterfaceController extends AbstractController { private boolean checkIp; @Resource private IReceiptOutService iReceiptOutService; + @Resource + private VoucherRecordService voucherRecordService; /** * @@ -1148,10 +1147,44 @@ public class InterfaceController extends AbstractController { //进项税转出 }else if("FI849".equals(requestParam.getIS_INPUT().getIFYWID())){ resultString = transferOut(requestParam); + }else if("FI848".equals(requestParam.getIS_INPUT().getIFYWID())){ + resultString = insertVouncherRecord(requestParam); } return resultString; } + private String insertVouncherRecord(ErpInvoiceData requestParam) { + OutPut outPut = new OutPut(); + String zdata = requestParam.getIS_INPUT().getZDATA(); + List voucherRecords = JSON.parseArray(zdata, VoucherRecord.class); + DynamicContextHolder.push("business"+ DbConstant.BUSINESS_READ); + try{ + boolean b = voucherRecordService.addVoucherRecords(voucherRecords); + EsOutPutResp esOutPutResp = new EsOutPutResp(); + esOutPutResp.setBSKEY(requestParam.getIS_INPUT().getBSKEY()); + esOutPutResp.setSAPKEY(requestParam.getIS_INPUT().getSAPKEY()); + if(b){ + esOutPutResp.setZTYPE("S"); + esOutPutResp.setZMESSAGE("处理成功"); + }else { + esOutPutResp.setZTYPE("E"); + esOutPutResp.setZMESSAGE("处理失败"); + } + outPut.setES_OUTPUT(esOutPutResp); + return JsonUtils.getInstance().toJsonString(outPut); + }catch (Exception e){ + e.printStackTrace(); + EsOutPutResp esOutPutResp = new EsOutPutResp(); + esOutPutResp.setBSKEY(requestParam.getIS_INPUT().getBSKEY()); + esOutPutResp.setSAPKEY(requestParam.getIS_INPUT().getSAPKEY()); + esOutPutResp.setZTYPE("E"); + esOutPutResp.setZMESSAGE("程序内部错误"); + outPut.setES_OUTPUT(esOutPutResp); + return JsonUtils.getInstance().toJsonString(outPut); + } + + } + @PostMapping("receiveErpInvoiceMessage") public String receiveErpInvoiceMessage(@RequestBody ErpInvoiceData erpInvoiceData){ diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordDao.java b/dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordDao.java new file mode 100644 index 00000000..6808456e --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordDao.java @@ -0,0 +1,21 @@ +package com.dxhy.erp.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dxhy.erp.entity.VoucherRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Author wangzhikun + * @Date 2023/3/23 2023/3/23 + */ +@Mapper +public interface VoucherRecordDao extends BaseMapper { + List selectRepeat(@Param("belnr") String s); + + void deleteBatch(@Param("deleteKeys") List deleteKeys); + + List selectRepeatByBelnr(@Param("belnrs") List belnrs); +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordItemDao.java b/dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordItemDao.java new file mode 100644 index 00000000..34840733 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/dao/VoucherRecordItemDao.java @@ -0,0 +1,17 @@ +package com.dxhy.erp.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dxhy.erp.entity.VoucherRecordItem; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Author wangzhikun + * @Date 2023/3/25 2023/3/25 + */ +@Mapper +public interface VoucherRecordItemDao extends BaseMapper { + void deleteByRelationid(@Param("ids") List ids); +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecord.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecord.java new file mode 100644 index 00000000..20961ecc --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecord.java @@ -0,0 +1,95 @@ +package com.dxhy.erp.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +/** + * @Author wangzhikun + * @Date 2023/3/23 2023/3/23 + */ +@Data +@TableName("voucher_record") +public class VoucherRecord { + @TableId(type= IdType.AUTO) + private String id; + @JsonProperty(value = "BUKRS") + //公司代码 + private String bukrs; + //公司代码名称 + @JsonProperty(value = "BUTXT") + private String butxt; + //会计凭证号码 + @JsonProperty(value = "BELNR") + private String belnr; + @JsonProperty(value = "GJAHR") + private String gjahr; + @JsonProperty(value = "MONAT") + private String monat; + @JsonProperty(value = "BLART") + private String blart; + @JsonProperty(value = "BUDAT") + private String budat; + @JsonProperty(value = "USNAM") + private String usnam; + @JsonProperty(value = "WAERS") + private String waers; + @JsonProperty(value = "KURSF") + private String kursf; + @JsonProperty(value = "BKTXT") + private String bktxt; + @JsonProperty(value = "XBLNR") + private String xblnr; + @JsonProperty(value = "ZBZDH") + private String zbzdh; + @JsonProperty(value = "ZJSDH") + private String zjsdh; + @JsonProperty(value = "XREVERSAL") + private String xreversal; + @JsonProperty(value = "STBLG") + private String stblg; + @JsonProperty(value = "STJAH") + private String stjah; + @JsonProperty(value = "AWKEY") + private String awkey; + @JsonProperty(value = "ZYWLX") + private String zywlx; + @JsonProperty(value = "ZLXMC") + private String zlxmc; + @JsonProperty(value = "ZBZCG") + private String zbzcg; + @JsonProperty(value = "ZBZCGT") + private String zbzcgt; + @JsonProperty(value = "ZBZXS") + private String zbzxs; + @JsonProperty(value = "ZBZXST") + private String zbzxst; + @JsonProperty(value = "ZBZDZT") + private String zbzdzt; + @JsonProperty(value = "ZCXDH") + private String zcxdh; + @JsonProperty(value = "BCXDH") + private String bcxdh; + @JsonProperty(value = "ZFLDH1") + private String zfldh1; + @JsonProperty(value = "ZFLDH2") + private String zfldh2; + @JsonProperty(value = "ZFLDH3") + private String zfldh3; + @JsonProperty(value = "ZFLDH4") + private String zfldh4; + @JsonProperty(value = "ZFLDH5") + private String zfldh5; + + private String relationId; + @JsonProperty(value = "ZITEM") + @TableField(exist = false) + private List ZITEM; + + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecordItem.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecordItem.java new file mode 100644 index 00000000..77cd7842 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/VoucherRecordItem.java @@ -0,0 +1,115 @@ +package com.dxhy.erp.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * @Author wangzhikun + * @Date 2023/3/23 2023/3/23 + */ +@Data +@TableName("voucher_record_item") +public class VoucherRecordItem { + @TableId + private Long id; + @JsonProperty(value = "DOCLN") + private String docln; + @JsonProperty(value = "DRCRK") + private String drcrk; + @JsonProperty(value = "ZDRCRK") + private String zdrcrk; + @JsonProperty(value = "RACCT") + private String racct; + @JsonProperty(value = "TXT50") + private String txt50; + @JsonProperty(value = "ZWSLJ") + private String zwslj; + @JsonProperty(value = "ZWSLD") + private String zwsld; + @JsonProperty(value = "RWCUR") + private String rwcur; + @JsonProperty(value = "ZHSLJ") + private String zhslj; + @JsonProperty(value = "ZHSLD") + private String zhsld; + @JsonProperty(value = "RHCUR") + private String rhcur; + @JsonProperty(value = "LIFNR") + private String lifnr; + @JsonProperty(value = "ZNAME1") + private String zname1; + @JsonProperty(value = "KUNNR") + private String kunnr; + @JsonProperty(value = "ZNAME2") + private String zname2; + @JsonProperty(value = "MATNR") + private String matnr; + @JsonProperty(value = "MAKTX") + private String maktx; + @JsonProperty(value = "MSL") + private String msl; + @JsonProperty(value = "RUNIT") + private String runit; + @JsonProperty(value = "MWSKZ") + private String mwskz; + @JsonProperty(value = "KBETR") + private String kbetr; + @JsonProperty(value = "RCNTR") + private String rcntr; + @JsonProperty(value = "KTEXT") + private String ktext; + @JsonProperty(value = "PS_POSID") + private String ps_posid; + @JsonProperty(value = "POST1") + private String post1; + @JsonProperty(value = "ZUFNR") + private String aufnr; + @JsonProperty(value = "ZKTEXT") + private String zktext; + @JsonProperty(value = "KDAUF") + private String kdauf; + @JsonProperty(value = "KDPOS") + private String kdpos; + @JsonProperty(value = "ZZJCFLAG") + private String zzjcflag; + @JsonProperty(value = "ANLN1") + private String anln1; + @JsonProperty(value = "ZAATXT50") + private String zaatxt50; + @JsonProperty(value = "RFAREA") + private String rfarea; + @JsonProperty(value = "FKBTX") + private String fkbtx; + @JsonProperty(value = "KTYPE") + private String ktype; + @JsonProperty(value = "ZKNAME") + private String zkname; + @JsonProperty(value = "ZZFLD1") + private String zzfld1; + @JsonProperty(value = "ZZFLD2") + private String zzfld2; + @JsonProperty(value = "ZZFLD3") + private String zzfld3; + @JsonProperty(value = "ZZFLD4") + private String zzfld4; + @JsonProperty(value = "ZZFLD5") + private String zzfld5; + @JsonProperty(value = "ZZFLD6") + private String zzfld6; + @JsonProperty(value = "ZZFLD7") + private String zzfld7; + @JsonProperty(value = "ZZFLD8") + private String zzfld8; + @JsonProperty(value = "ZZFLD9") + private String zzfld9; + @JsonProperty(value = "ZZFLD10") + private String zzfld10; + + private String relationId; + + + + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordItemService.java b/dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordItemService.java new file mode 100644 index 00000000..47e206f4 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordItemService.java @@ -0,0 +1,14 @@ +package com.dxhy.erp.service; + +import com.dxhy.erp.entity.VoucherRecordItem; + +import java.util.List; + +/** + * @Author wangzhikun + * @Date 2023/3/25 2023/3/25 + */ +public interface VoucherRecordItemService { + + public boolean inserBatch(Listitems); +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordService.java b/dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordService.java new file mode 100644 index 00000000..1a0c0b6d --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/service/VoucherRecordService.java @@ -0,0 +1,15 @@ +package com.dxhy.erp.service; + +import com.dxhy.common.service.MpBaseService; +import com.dxhy.erp.entity.VoucherRecord; + +import java.util.List; + +/** + * @Author wangzhikun + * @Date 2023/3/23 2023/3/23 + */ +public interface VoucherRecordService extends MpBaseService { + + boolean addVoucherRecords(List voucherRecords); +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/InvoiceAuthServiceImpl.java b/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/InvoiceAuthServiceImpl.java index ff95c202..cbcc8b1f 100644 --- a/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/InvoiceAuthServiceImpl.java +++ b/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/InvoiceAuthServiceImpl.java @@ -357,11 +357,11 @@ public class InvoiceAuthServiceImpl extends MpBaseServiceImpl0){ diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordItemServiceImpl.java b/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordItemServiceImpl.java new file mode 100644 index 00000000..c49f1407 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordItemServiceImpl.java @@ -0,0 +1,24 @@ +package com.dxhy.erp.service.impl; + +import com.dxhy.common.service.impl.MpBaseServiceImpl; +import com.dxhy.erp.dao.VoucherRecordItemDao; +import com.dxhy.erp.entity.VoucherRecordItem; +import com.dxhy.erp.service.VoucherRecordItemService; +import com.dxhy.erp.service.VoucherRecordService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @Author wangzhikun + * @Date 2023/3/25 2023/3/25 + */ +@Service +public class VoucherRecordItemServiceImpl extends MpBaseServiceImpl implements VoucherRecordItemService { + + + @Override + public boolean inserBatch(List items) { + return this.saveBatch(items); + } +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordServiceImpl.java b/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordServiceImpl.java new file mode 100644 index 00000000..5664e8c7 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/service/impl/VoucherRecordServiceImpl.java @@ -0,0 +1,118 @@ +package com.dxhy.erp.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.dxhy.common.constant.DbConstant; +import com.dxhy.common.datasource.config.DynamicContextHolder; +import com.dxhy.common.service.impl.MpBaseServiceImpl; +import com.dxhy.erp.dao.VoucherRecordDao; +import com.dxhy.erp.dao.VoucherRecordItemDao; +import com.dxhy.erp.entity.VoucherRecord; +import com.dxhy.erp.entity.VoucherRecordItem; +import com.dxhy.erp.service.VoucherRecordItemService; +import com.dxhy.erp.service.VoucherRecordService; +import com.dxhy.erp.utils.DistributedKeyMaker; +import com.dxhy.erp.utils.IdUtils; +import com.rabbitmq.client.AMQP; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @Author wangzhikun + * @Date 2023/3/23 2023/3/23 + */ +@Service +public class VoucherRecordServiceImpl extends MpBaseServiceImpl implements VoucherRecordService { + @Resource + private VoucherRecordDao voucherRecordDao; + + @Resource + private VoucherRecordItemDao voucherRecordItemDao; + @Resource + private VoucherRecordItemService voucherRecordItemService; + @Override + /** + * 接口推送的凭证接收数据逻辑 + * 1.先根据推送数据的公司代码+会计年度+期间分组 然后查询出符合条件的数据取出主键 + * 然后比对推送的数据是否有相同的,如果有相同的删除重新新增 + * + */ + @Transactional(rollbackFor = Exception.class) + public boolean addVoucherRecords(List voucherRecords) { + boolean b = false; + if(!CollectionUtils.isEmpty(voucherRecords)){ + //新推送的记录。直接入库 + List newRecordList = new ArrayList<>(); + //重复的记录,删除之后重新入库 + List repeatRecordList = new ArrayList<>(); + Map> collect = voucherRecords.stream().collect(Collectors.groupingBy(v -> v.getBukrs() + v.getGjahr() + v.getMonat())); + Set key = collect.keySet(); + for(String s:key){ + //根据公司代码+年份+月份查出主键 + List repeatList =voucherRecordDao.selectRepeat(s); + List voucherRecords1 = collect.get(s); + Map> collect1 = voucherRecords1.stream().collect(Collectors.groupingBy(v -> v.getBukrs() + v.getBelnr() + v.getGjahr())); + Set belnrs = collect1.keySet(); + for(String belnr:belnrs){ + if(repeatList.contains(belnr)){ + repeatRecordList.addAll(collect1.get(belnr)); + }else { + newRecordList.addAll(collect1.get(belnr)); + } + } + } + List addItems = new ArrayList<>(); + for(VoucherRecord voucherRecordNew:newRecordList){ + String s = DistributedKeyMaker.generateShotKey(); + voucherRecordNew.setId(s); + for(VoucherRecordItem voucherRecordItem:voucherRecordNew.getZITEM()){ + voucherRecordItem.setRelationId(s); + } + addItems.addAll(voucherRecordNew.getZITEM()); + } + List deleteRecord = new ArrayList<>(); + for(VoucherRecord voucherRecordRepeat:repeatRecordList){ + VoucherRecord deleteVoucher = new VoucherRecord(); + deleteVoucher.setBukrs(voucherRecordRepeat.getBukrs()); + deleteVoucher.setBelnr(voucherRecordRepeat.getBelnr()); + deleteVoucher.setGjahr(voucherRecordRepeat.getGjahr()); + String s = DistributedKeyMaker.generateShotKey(); + voucherRecordRepeat.setId(s); + for(VoucherRecordItem item:voucherRecordRepeat.getZITEM()){ + item.setRelationId(s); + } + addItems.addAll(voucherRecordRepeat.getZITEM()); + deleteRecord.add(deleteVoucher); + } + if(!CollectionUtils.isEmpty(deleteRecord)){ + //根据主键查出对应明细数据的关联id,然后根据id删除明细 + List list = new ArrayList<>(); + for(VoucherRecord voucherRecord:deleteRecord){ + String str = voucherRecord.getBukrs()+voucherRecord.getBelnr()+voucherRecord.getGjahr(); + list.add(str); + } + List ids=voucherRecordDao.selectRepeatByBelnr(list); + if(!CollectionUtils.isEmpty(ids)){ + voucherRecordItemDao.deleteByRelationid(ids); + } + voucherRecordDao.deleteBatch(deleteRecord); + } + this.saveBatch(newRecordList); + this.saveBatch(repeatRecordList); + b = voucherRecordItemService.inserBatch(addItems); + } + return b; + } + + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/utils/DistributedKeyMaker.java b/dxhy-erp/src/main/java/com/dxhy/erp/utils/DistributedKeyMaker.java new file mode 100644 index 00000000..290f1cb3 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/utils/DistributedKeyMaker.java @@ -0,0 +1,256 @@ +package com.dxhy.erp.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemUtils; + +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.UnknownHostException; + + +/** + * 分布式主键生成器 + * + * @author Acmen + */ +@Slf4j +public final class DistributedKeyMaker { + + /** + * 开始时间截 (2015-01-01) + */ + private final long twepoch = 1489111610226L; + + /** + * 机器id所占的位数 + */ + private final long workerIdBits = 5L; + + /** + * 数据标识id所占的位数 + */ + private final long dataCenterIdBits = 5L; + + /** + * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) + */ + private final long maxWorkerId = ~(-1L << workerIdBits); + + /** + * 支持的最大数据标识id,结果是31 + */ + private final long maxDataCenterId = ~(-1L << dataCenterIdBits); + + /** + * 序列在id中占的位数 + */ + private final long sequenceBits = 12L; + + /** + * 机器ID向左移12位 + */ + private final long workerIdShift = sequenceBits; + + /** + * 数据标识id向左移17位(12+5) + */ + private final long dataCenterIdShift = sequenceBits + workerIdBits; + + /** + * 时间截向左移22位(5+5+12) + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits; + + /** + * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) + */ + private final long sequenceMask = ~(-1L << sequenceBits); + + /** + * 工作机器ID(0~31) + */ + private final long workerId; + + /** + * 数据中心ID(0~31) + */ + private final long dataCenterId; + + /** + * 毫秒内序列(0~4095) + */ + private long sequence = 0L; + + /** + * 上次生成ID的时间截 + */ + private long lastTimestamp = -1L; + + private static final DistributedKeyMaker ID_WORKER; + + static { + ID_WORKER = new DistributedKeyMaker(getWorkId(), getDataCenterId()); + } + + //==============================Constructors===================================== + + /** + * 构造函数 + * + * @param workerId 工作ID (0~31) + * @param dataCenterId 数据中心ID (0~31) + */ + public DistributedKeyMaker(long workerId, long dataCenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId)); + } + if (dataCenterId > maxDataCenterId || dataCenterId < 0) { + throw new IllegalArgumentException(String.format("dataCenterId can't be greater than %d or less than 0", maxDataCenterId)); + } + this.workerId = workerId; + this.dataCenterId = dataCenterId; + } + + // ==============================Methods========================================== + + /** + * 获得下一个ID (该方法是线程安全的) + * + * @return SnowflakeId + */ + private synchronized long nextId() { + long timestamp = timeGen(); + + //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 + if (timestamp < lastTimestamp) { + throw new RuntimeException( + String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); + } + + //如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + //毫秒内序列溢出 + if (sequence == 0) { + //阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + //时间戳改变,毫秒内序列重置 + else { + sequence = 0L; + } + + //上次生成ID的时间截 + lastTimestamp = timestamp; + + //移位并通过或运算拼到一起组成64位的ID + return ((timestamp - twepoch) << timestampLeftShift) + | (dataCenterId << dataCenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + /** + * 阻塞到下一个毫秒,直到获得新的时间戳 + * + * @param lastTimestamp 上次生成ID的时间截 + * @return 当前时间戳 + */ + private long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** + * 返回以毫秒为单位的当前时间 + * + * @return 当前时间(毫秒) + */ + protected long timeGen() { + return System.currentTimeMillis(); + } + + /** + * workId使用服务器hostName生成 + * + * @return + */ + private static Long getWorkId() { + try { + String hostAddress = Inet4Address.getLocalHost().getHostAddress(); + log.info("获取到的系统地址:{}", hostAddress); + if ("127.0.0.1".equals(hostAddress)) { + hostAddress = getMacAddress(); + log.info("重新获取到的系统地址:{}", hostAddress); + } + int[] ints = StringUtils.toCodePoints(hostAddress); + log.info("转换成十六进制的int数组:{}", ints); + int sums = 0; + for (int b : ints) { + sums += b; + } + return (long) (sums % 32); + } catch (UnknownHostException e) { + // 如果获取失败,则使用随机数备用 + return RandomUtils.nextLong(0, 31); + } + } + + /** + * dataCenterId使用IP生成 + * + * @return + */ + private static Long getDataCenterId() { + String hostName = SystemUtils.getHostName(); + log.info("获取到的主机地址:{}", hostName); + if (StringUtils.isBlank(hostName)) { + hostName = SystemUtils.USER_NAME; + log.info("默认获取到的主机地址:{}", hostName); + } + int[] ints = StringUtils.toCodePoints(hostName); + log.info("获取到的十六进制主机地址:{}", ints); + + int sums = 0; + for (int i : ints) { + sums += i; + } + return (long) (sums % 32); + } + + /** + * 获取mac地址 + * + * @return + */ + private static String getMacAddress() { + String macAddress = ""; + try { + NetworkInterface networkInterface = NetworkInterface.getByInetAddress(Inet4Address.getLocalHost()); + byte[] hardwareAddress = networkInterface.getHardwareAddress(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hardwareAddress.length; i++) { + sb.append(String.format("%02X%s", hardwareAddress[i], (i < hardwareAddress.length - 1) ? "-" : "")); + } + macAddress = sb.toString(); + } catch (Exception e) { + macAddress = SystemUtils.getUserName(); + } + log.info("获取到的主机地址:{}", macAddress); + return macAddress; + } + + /** + * 生成主键 + */ + public static String generateShotKey() { + return String.valueOf(ID_WORKER.nextId()); + } + +} diff --git a/dxhy-erp/src/main/resources/mapper/VoucherRecord.xml b/dxhy-erp/src/main/resources/mapper/VoucherRecord.xml new file mode 100644 index 00000000..0b188496 --- /dev/null +++ b/dxhy-erp/src/main/resources/mapper/VoucherRecord.xml @@ -0,0 +1,33 @@ + + + + + + + + + delete from voucher_record where + + + bukrs= #{key.bukrs} + + + and belnr = #{key.belnr} + + + and gjahr = #{key.gjahr} + + + + + + diff --git a/dxhy-erp/src/main/resources/mapper/VoucherRecordItem.xml b/dxhy-erp/src/main/resources/mapper/VoucherRecordItem.xml new file mode 100644 index 00000000..9ac19eb6 --- /dev/null +++ b/dxhy-erp/src/main/resources/mapper/VoucherRecordItem.xml @@ -0,0 +1,13 @@ + + + + + delete from voucher_record_item where relation_id in + + #{key} + + + + +