|
|
@@ -30,6 +30,10 @@ import org.springframework.stereotype.Service;
|
|
30
|
30
|
import org.springframework.transaction.annotation.Transactional;
|
|
31
|
31
|
import org.springframework.util.StringUtils;
|
|
32
|
32
|
|
|
|
33
|
+import java.math.BigDecimal;
|
|
|
34
|
+import java.text.SimpleDateFormat;
|
|
|
35
|
+import java.time.LocalDateTime;
|
|
|
36
|
+import java.time.format.DateTimeFormatter;
|
|
33
|
37
|
import java.util.Collections;
|
|
34
|
38
|
import java.util.Date;
|
|
35
|
39
|
import java.util.List;
|
|
|
@@ -56,11 +60,12 @@ public class ChangeServiceImpl implements ChangeService {
|
|
56
|
60
|
|
|
57
|
61
|
/**
|
|
58
|
62
|
* 货权转移
|
|
59
|
|
- * 解决:货权转移后Cargo重量不减少、中途return不扣重量、空指针、事务部分提交BUG
|
|
|
63
|
+ * 修复:浮点数精度问题、重复更新问题、逻辑校验问题
|
|
60
|
64
|
*/
|
|
61
|
65
|
@Transactional(rollbackFor = Exception.class)
|
|
62
|
66
|
@Override
|
|
63
|
67
|
public String changeCustomer(String json, String customer, String address, String userId, String belongId) throws Exception {
|
|
|
68
|
+
|
|
64
|
69
|
// 1. 基础参数非空校验
|
|
65
|
70
|
if (!StringUtils.hasText(json) || !StringUtils.hasText(customer) || !StringUtils.hasText(userId) || !StringUtils.hasText(belongId)) {
|
|
66
|
71
|
throw new Exception("传入参数不能为空");
|
|
|
@@ -93,52 +98,79 @@ public class ChangeServiceImpl implements ChangeService {
|
|
93
|
98
|
throw new Exception("原货主不存在");
|
|
94
|
99
|
}
|
|
95
|
100
|
|
|
96
|
|
- // 4. 查询货权配置记录
|
|
|
101
|
+ // 4. 校验新旧货主不能相同
|
|
|
102
|
+ if (oldCustomer.getId().equals(newCustomer.getId())) {
|
|
|
103
|
+ throw new Exception("新旧货主不能相同");
|
|
|
104
|
+ }
|
|
|
105
|
+
|
|
|
106
|
+ // 5. 查询货权配置记录
|
|
97
|
107
|
Cargo cargo = cargoMapper.selectByByFkAndCustomer(oldCustomer.getId(), newCustomer.getId(), belongId);
|
|
98
|
|
- double sumWeight = 0;
|
|
|
108
|
+
|
|
|
109
|
+ // 使用BigDecimal处理重量
|
|
|
110
|
+ BigDecimal availableWeight = BigDecimal.ZERO;
|
|
|
111
|
+ BigDecimal sumWeightBD = BigDecimal.ZERO;
|
|
|
112
|
+
|
|
99
|
113
|
if (cargo != null) {
|
|
100
|
|
- sumWeight = cargo.getSumWeight();
|
|
101
|
|
- // 货权可用重量为0直接拦截
|
|
102
|
|
- if (sumWeight <= 0) {
|
|
|
114
|
+ sumWeightBD = BigDecimal.valueOf(cargo.getSumWeight());
|
|
|
115
|
+ availableWeight = sumWeightBD;
|
|
|
116
|
+ // 货权可用重量为0直接拦截(使用精度比较)
|
|
|
117
|
+ if (availableWeight.compareTo(BigDecimal.ZERO) <= 0) {
|
|
103
|
118
|
throw new Exception("货权信息已维护,可用转移重量为0");
|
|
104
|
119
|
}
|
|
105
|
120
|
}
|
|
106
|
121
|
|
|
107
|
|
- double useWeight = 0;// 已累计使用转移重量
|
|
108
|
|
- int num = 0;// 数据库受影响行数 初始化
|
|
109
|
|
- String recordType;
|
|
|
122
|
+ // 6. 计算需要转移的总重量
|
|
|
123
|
+ BigDecimal needTotalWeight = BigDecimal.ZERO;
|
|
|
124
|
+ for (Store store : storeList) {
|
|
|
125
|
+ if (store != null && store.getWeight() > 0) {
|
|
|
126
|
+ needTotalWeight = needTotalWeight.add(BigDecimal.valueOf(store.getWeight()));
|
|
|
127
|
+ }
|
|
|
128
|
+ }
|
|
|
129
|
+
|
|
|
130
|
+ // 7. 总重量校验(提前校验,避免处理一半才失败)
|
|
|
131
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
|
|
132
|
+ System.out.println("时间"+sdf.format(new Date()));
|
|
|
133
|
+ System.out.println("可用重量"+availableWeight.stripTrailingZeros().toPlainString());
|
|
|
134
|
+ System.out .println("需要总重量"+needTotalWeight.stripTrailingZeros().toPlainString());
|
|
|
135
|
+ if (cargo != null && availableWeight.compareTo(needTotalWeight) < 0) {
|
|
|
136
|
+ throw new Exception(String.format("货权转移重量不足。可用: %s, 转移重量: %s",
|
|
|
137
|
+ availableWeight.stripTrailingZeros().toPlainString(),
|
|
|
138
|
+ needTotalWeight.stripTrailingZeros().toPlainString()));
|
|
|
139
|
+ }
|
|
|
140
|
+ // 8. 循环逐条处理库存转移
|
|
|
141
|
+ BigDecimal usedWeight = BigDecimal.ZERO;
|
|
|
142
|
+ int affectedRows = 0;
|
|
110
|
143
|
|
|
111
|
|
- // 5. 循环逐条处理库存转移
|
|
112
|
144
|
for (Store store : storeList) {
|
|
113
|
145
|
if (store == null || store.getWeight() <= 0) {
|
|
114
|
146
|
continue;
|
|
115
|
147
|
}
|
|
116
|
|
- double currentWeight = store.getWeight();
|
|
117
|
148
|
|
|
118
|
|
- // 重量不足校验
|
|
119
|
|
- if (sumWeight > 0 && (sumWeight - useWeight - currentWeight) < 0) {
|
|
120
|
|
- throw new Exception("货权转移重量不足");
|
|
121
|
|
- }
|
|
|
149
|
+ BigDecimal currentWeight = BigDecimal.valueOf(store.getWeight());
|
|
122
|
150
|
|
|
123
|
|
- // 判断记录类型
|
|
|
151
|
+ // 9. 判断记录类型(如果新货主名跟库存老货主名一样,则记录类型为0)
|
|
|
152
|
+ String recordType;
|
|
124
|
153
|
if (newCustomer.getName().equals(store.getCustomer().getName())) {
|
|
125
|
154
|
recordType = "0";
|
|
126
|
155
|
} else {
|
|
127
|
156
|
recordType = "1";
|
|
128
|
157
|
// 插入账户明细
|
|
129
|
158
|
AccountDetail accountDetail = getAccountDetail(store, userId, belongId);
|
|
130
|
|
- num += accountDetailMapper.insert(accountDetail);
|
|
|
159
|
+ affectedRows += accountDetailMapper.insert(accountDetail);
|
|
131
|
160
|
}
|
|
132
|
161
|
|
|
133
|
|
- // 插入变更记录
|
|
|
162
|
+ // 10. 插入变更记录
|
|
134
|
163
|
ChangeRecord changeRecord = getChangeRecord(recordType, store, newCustomer, address, userId, belongId);
|
|
135
|
|
- num += changeRecordMapper.insert(changeRecord);
|
|
|
164
|
+ affectedRows += changeRecordMapper.insert(changeRecord);
|
|
|
165
|
+
|
|
|
166
|
+ // 11. 保存老货主ID
|
|
|
167
|
+ String oldCustomerId = store.getCustomer().getId();
|
|
136
|
168
|
|
|
137
|
|
- // 修改库存归属
|
|
|
169
|
+ // 12. 修改库存归属
|
|
138
|
170
|
store.setCustomer(newCustomer);
|
|
139
|
|
- store.setFkComponyId(oldCustomer.getId());
|
|
|
171
|
+ store.setFkComponyId(oldCustomerId);
|
|
140
|
172
|
|
|
141
|
|
- // 地址处理
|
|
|
173
|
+ // 13. 地址处理
|
|
142
|
174
|
if (StringUtils.hasText(address)) {
|
|
143
|
175
|
if ("0".equals(address)) {
|
|
144
|
176
|
store.setReceiveAddress("");
|
|
|
@@ -147,41 +179,41 @@ public class ChangeServiceImpl implements ChangeService {
|
|
147
|
179
|
}
|
|
148
|
180
|
}
|
|
149
|
181
|
|
|
150
|
|
- // 更新库存
|
|
151
|
|
- num += storeMapper.updateByPrimaryKey(store);
|
|
152
|
|
- num += storeMapper.updateFkById(store);
|
|
|
182
|
+ // 14. 更新库存(合并为一次更新)
|
|
|
183
|
+ affectedRows += storeMapper.updateByPrimaryKey(store);
|
|
153
|
184
|
|
|
154
|
|
- // 累加已使用重量
|
|
155
|
|
- useWeight += currentWeight;
|
|
|
185
|
+ // 15. 累加已使用重量
|
|
|
186
|
+ usedWeight = usedWeight.add(currentWeight);
|
|
156
|
187
|
|
|
157
|
|
- // ========== 关键修复:逐条实时扣减货权重量,不放到循环外 ==========
|
|
|
188
|
+ // 16. 逐条实时扣减货权重量(使用BigDecimal保证精度)
|
|
158
|
189
|
if (cargo != null) {
|
|
159
|
|
- cargo.setSumWeight(cargo.getSumWeight() - currentWeight);
|
|
160
|
|
- cargo.setUseWeight(cargo.getUseWeight() + currentWeight);
|
|
161
|
|
- // 立即更新数据库,每处理一条扣一条,避免中途中断完全不扣
|
|
162
|
|
- num += cargoMapper.updateByPrimaryKey(cargo);
|
|
|
190
|
+ BigDecimal newSumWeight = BigDecimal.valueOf(cargo.getSumWeight()).subtract(currentWeight);
|
|
|
191
|
+ BigDecimal newUseWeight = BigDecimal.valueOf(cargo.getUseWeight()).add(currentWeight);
|
|
|
192
|
+ cargo.setSumWeight(newSumWeight.doubleValue());
|
|
|
193
|
+ cargo.setUseWeight(newUseWeight.doubleValue());
|
|
|
194
|
+ affectedRows += cargoMapper.updateByPrimaryKey(cargo);
|
|
163
|
195
|
}
|
|
164
|
196
|
}
|
|
165
|
197
|
|
|
166
|
|
- // 6. 批量处理完后 插入货权变更记录
|
|
167
|
|
- if (cargo != null && useWeight > 0) {
|
|
|
198
|
+ // 17. 批量处理完后插入货权变更记录
|
|
|
199
|
+ if (cargo != null && usedWeight.compareTo(BigDecimal.ZERO) > 0) {
|
|
168
|
200
|
CargoChangeRecord cargoChangeRecord = new CargoChangeRecord();
|
|
169
|
201
|
cargoChangeRecord.setUperCustomer(cargo.getUperCustomer());
|
|
170
|
202
|
cargoChangeRecord.setCustomer(cargo.getCustomer());
|
|
171
|
203
|
cargoChangeRecord.setChangeFrom("货权转移");
|
|
172
|
|
- cargoChangeRecord.setWeight(useWeight);
|
|
|
204
|
+ cargoChangeRecord.setWeight(usedWeight.doubleValue());
|
|
173
|
205
|
cargoChangeRecord.setSubStr("减少");
|
|
174
|
206
|
cargoChangeRecord.setModifyTime(new Date());
|
|
175
|
207
|
cargoChangeRecord.setModifyUser(new SysUser(userId));
|
|
176
|
|
-// cargoChangeRecord.setCancelFlag("0");
|
|
177
|
|
- num += cargoChangeRecordMapper.insert(cargoChangeRecord);
|
|
|
208
|
+ affectedRows += cargoChangeRecordMapper.insert(cargoChangeRecord);
|
|
178
|
209
|
}
|
|
179
|
210
|
|
|
180
|
|
- // 7. 返回结果
|
|
181
|
|
- return Tools.moreThanZeroResultJSON(num);
|
|
|
211
|
+ // 18. 返回结果
|
|
|
212
|
+ return Tools.moreThanZeroResultJSON(affectedRows);
|
|
182
|
213
|
}
|
|
183
|
214
|
|
|
184
|
215
|
|
|
|
216
|
+
|
|
185
|
217
|
private ChangeRecord getChangeRecord(String recordType, Store store, Customer customer, String receiveAddress, String userId, String belongId) {
|
|
186
|
218
|
ChangeRecord record = new ChangeRecord();
|
|
187
|
219
|
record.setRecordType(recordType);
|