导出同事特权,增加和修正表字段
This commit is contained in:
@@ -62,6 +62,7 @@ public class LbOrderRowController {
|
|||||||
@RequestParam(defaultValue = "1") Integer current,
|
@RequestParam(defaultValue = "1") Integer current,
|
||||||
@RequestParam(defaultValue = "10") Integer size,
|
@RequestParam(defaultValue = "10") Integer size,
|
||||||
@RequestParam(required = false) String isResell,
|
@RequestParam(required = false) String isResell,
|
||||||
|
@Parameter(description = "数据类型") @RequestParam(required = false) String dataType,
|
||||||
@RequestParam(required = false) String orderSn,
|
@RequestParam(required = false) String orderSn,
|
||||||
@RequestParam(required = false) Long buyerId,
|
@RequestParam(required = false) Long buyerId,
|
||||||
@RequestParam(required = false) Long sellerId,
|
@RequestParam(required = false) Long sellerId,
|
||||||
@@ -69,7 +70,7 @@ public class LbOrderRowController {
|
|||||||
@RequestParam(required = false) Long merchandiseId) {
|
@RequestParam(required = false) Long merchandiseId) {
|
||||||
Map<String, Object> result =
|
Map<String, Object> result =
|
||||||
lbOrderRowService.pageQuery(
|
lbOrderRowService.pageQuery(
|
||||||
current, size, isResell, orderSn, buyerId, sellerId, status, merchandiseId);
|
current, size, isResell, dataType, orderSn, buyerId, sellerId, status, merchandiseId);
|
||||||
Boolean success = (Boolean) result.get("success");
|
Boolean success = (Boolean) result.get("success");
|
||||||
if (success != null && success) {
|
if (success != null && success) {
|
||||||
return ResponseEntity.ok(result);
|
return ResponseEntity.ok(result);
|
||||||
@@ -88,7 +89,8 @@ public class LbOrderRowController {
|
|||||||
request.getBuyTimeStart(),
|
request.getBuyTimeStart(),
|
||||||
request.getBuyTimeEnd(),
|
request.getBuyTimeEnd(),
|
||||||
request.getTenantId(),
|
request.getTenantId(),
|
||||||
request.getIsResell());
|
request.getIsResell(),
|
||||||
|
request.getDataType());
|
||||||
Boolean success = (Boolean) result.get("success");
|
Boolean success = (Boolean) result.get("success");
|
||||||
if (success != null && success) {
|
if (success != null && success) {
|
||||||
return ResponseEntity.ok(result);
|
return ResponseEntity.ok(result);
|
||||||
|
|||||||
@@ -155,6 +155,21 @@ public class LbPurchaseApplyController {
|
|||||||
return ResponseEntity.badRequest().body(result);
|
return ResponseEntity.badRequest().body(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/exportColleagueVip")
|
||||||
|
@Operation(summary = "导出同事特权开通提醒Excel",
|
||||||
|
description = "筛选逻辑与 syncHxrAdminColleagueVip 一致:仅导出申请人当日有进货记录、"
|
||||||
|
+ "且具备同事手机号的可开通记录,列含昵称、手机号、特权开通日期、开通日期")
|
||||||
|
public void exportColleagueVip(
|
||||||
|
@Parameter(description = "申请开始日期(yyyy-MM-dd)", required = true)
|
||||||
|
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate applyDateStart,
|
||||||
|
@Parameter(description = "申请结束日期(yyyy-MM-dd)", required = true)
|
||||||
|
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate applyDateEnd,
|
||||||
|
@Parameter(description = "租户ID", required = true)
|
||||||
|
@RequestParam String tenantId,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
lbPurchaseApplyService.exportColleagueVipExcel(applyDateStart, applyDateEnd, tenantId, response);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/export")
|
@GetMapping("/export")
|
||||||
@Operation(summary = "导出进货申请Excel", description = "按租户ID与申请日期范围导出,按申请日分组并合并首列")
|
@Operation(summary = "导出进货申请Excel", description = "按租户ID与申请日期范围导出,按申请日分组并合并首列")
|
||||||
public void export(
|
public void export(
|
||||||
|
|||||||
@@ -21,4 +21,7 @@ public class LbOrderRowSyncFromHxrRequest {
|
|||||||
|
|
||||||
@Schema(description = "转卖状态筛选(对应后台 is_resell)", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "转卖状态筛选(对应后台 is_resell)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private Integer isResell;
|
private Integer isResell;
|
||||||
|
|
||||||
|
@Schema(description = "写入 lb_order_row.data_type;为空时默认使用 isResell 的字符串值")
|
||||||
|
private String dataType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@@ -31,6 +32,10 @@ public class LbOrderRow implements Serializable {
|
|||||||
@Schema(description = "租户ID")
|
@Schema(description = "租户ID")
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
|
|
||||||
|
@TableField("data_type")
|
||||||
|
@Schema(description = "数据类型")
|
||||||
|
private String dataType;
|
||||||
|
|
||||||
@TableField("seller_id")
|
@TableField("seller_id")
|
||||||
@Schema(description = "卖家 id")
|
@Schema(description = "卖家 id")
|
||||||
private Long sellerId;
|
private Long sellerId;
|
||||||
@@ -44,8 +49,8 @@ public class LbOrderRow implements Serializable {
|
|||||||
private String orderSn;
|
private String orderSn;
|
||||||
|
|
||||||
@TableField("total_money")
|
@TableField("total_money")
|
||||||
@Schema(description = "总金额(接口为字符串)")
|
@Schema(description = "总金额")
|
||||||
private String totalMoney;
|
private BigDecimal totalMoney;
|
||||||
|
|
||||||
@TableField("pay_time")
|
@TableField("pay_time")
|
||||||
@Schema(description = "支付时间(原样字符串)")
|
@Schema(description = "支付时间(原样字符串)")
|
||||||
@@ -110,4 +115,16 @@ public class LbOrderRow implements Serializable {
|
|||||||
@TableField("updated_at")
|
@TableField("updated_at")
|
||||||
@Schema(description = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private String updatedAt;
|
private String updatedAt;
|
||||||
|
|
||||||
|
@TableField("today_total_money_sum")
|
||||||
|
@Schema(description = "汇总后的总金额")
|
||||||
|
private BigDecimal todayTotalMoneySum;
|
||||||
|
|
||||||
|
@TableField("today_unresell_count")
|
||||||
|
@Schema(description = "当天没有寄卖的单数总和")
|
||||||
|
private Integer todayUnresellCount;
|
||||||
|
|
||||||
|
@TableField("today_order_count")
|
||||||
|
@Schema(description = "当天交易单数")
|
||||||
|
private Integer todayOrderCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ public interface ILbOrderRowService extends IService<LbOrderRow> {
|
|||||||
Map<String, Object> pageQuery(
|
Map<String, Object> pageQuery(
|
||||||
Integer current,
|
Integer current,
|
||||||
Integer size,
|
Integer size,
|
||||||
String tenantId,
|
String isResell,
|
||||||
|
String dataType,
|
||||||
String orderSn,
|
String orderSn,
|
||||||
Long buyerId,
|
Long buyerId,
|
||||||
Long sellerId,
|
Long sellerId,
|
||||||
@@ -27,5 +28,9 @@ public interface ILbOrderRowService extends IService<LbOrderRow> {
|
|||||||
* 按条件调用 hxrd 后台订单列表接口拉取数据,并 upsert 到 {@code lb_order_row}。
|
* 按条件调用 hxrd 后台订单列表接口拉取数据,并 upsert 到 {@code lb_order_row}。
|
||||||
*/
|
*/
|
||||||
Map<String, Object> syncFromHxrAdmin(
|
Map<String, Object> syncFromHxrAdmin(
|
||||||
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell);
|
String buyTimeStart,
|
||||||
|
String buyTimeEnd,
|
||||||
|
String tenantId,
|
||||||
|
Integer isResell,
|
||||||
|
String dataType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,10 @@ public interface ILbPurchaseApplyService extends IService<LbPurchaseApply> {
|
|||||||
* 按申请日期区间与租户导出进货申请 Excel(按申请日分组,首列合并单元格)。
|
* 按申请日期区间与租户导出进货申请 Excel(按申请日分组,首列合并单元格)。
|
||||||
*/
|
*/
|
||||||
void exportExcel(LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response);
|
void exportExcel(LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出与 {@link #syncHxrAdminColleagueVipByApplyDateRange} 相同筛选条件下的同事特权开通提醒 Excel。
|
||||||
|
*/
|
||||||
|
void exportColleagueVipExcel(
|
||||||
|
LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -139,6 +140,7 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
Integer current,
|
Integer current,
|
||||||
Integer size,
|
Integer size,
|
||||||
String isResell,
|
String isResell,
|
||||||
|
String dataType,
|
||||||
String orderSn,
|
String orderSn,
|
||||||
Long buyerId,
|
Long buyerId,
|
||||||
Long sellerId,
|
Long sellerId,
|
||||||
@@ -157,6 +159,9 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
if (isResell != null && !isResell.trim().isEmpty()) {
|
if (isResell != null && !isResell.trim().isEmpty()) {
|
||||||
w.eq(LbOrderRow::getIsResell, isResell.trim());
|
w.eq(LbOrderRow::getIsResell, isResell.trim());
|
||||||
}
|
}
|
||||||
|
if (dataType != null && !dataType.trim().isEmpty()) {
|
||||||
|
w.eq(LbOrderRow::getDataType, dataType.trim());
|
||||||
|
}
|
||||||
if (orderSn != null && !orderSn.trim().isEmpty()) {
|
if (orderSn != null && !orderSn.trim().isEmpty()) {
|
||||||
w.like(LbOrderRow::getOrderSn, orderSn.trim());
|
w.like(LbOrderRow::getOrderSn, orderSn.trim());
|
||||||
}
|
}
|
||||||
@@ -193,7 +198,7 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Map<String, Object> syncFromHxrAdmin(
|
public Map<String, Object> syncFromHxrAdmin(
|
||||||
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell) {
|
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell, String dataType) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||||
@@ -223,12 +228,18 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
}
|
}
|
||||||
|
|
||||||
String tid = tenantId.trim();
|
String tid = tenantId.trim();
|
||||||
|
String rowDataType = resolveSyncDataType(dataType, isResell);
|
||||||
|
BigDecimal todayTotalMoneySum = parseMoney(body.allMoney());
|
||||||
|
int todayOrderCount = body.count();
|
||||||
|
int todayUnresellCount = countUnresell(rows);
|
||||||
List<LbOrderRow> entities = new ArrayList<>(rows.size());
|
List<LbOrderRow> entities = new ArrayList<>(rows.size());
|
||||||
for (HxrOrderRow row : rows) {
|
for (HxrOrderRow row : rows) {
|
||||||
entities.add(toLbOrderRow(row, tid));
|
entities.add(toLbOrderRow(
|
||||||
|
row, tid, rowDataType, todayTotalMoneySum, todayOrderCount, todayUnresellCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean ok = this.saveOrUpdateBatch(entities);
|
boolean ok = this.saveOrUpdateBatch(entities);
|
||||||
|
// boolean ok = this.saveBatch(entities);
|
||||||
result.put("success", ok);
|
result.put("success", ok);
|
||||||
result.put("message", ok ? "同步完成" : "批量保存失败");
|
result.put("message", ok ? "同步完成" : "批量保存失败");
|
||||||
result.put("synced", ok ? entities.size() : 0);
|
result.put("synced", ok ? entities.size() : 0);
|
||||||
@@ -243,15 +254,54 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LbOrderRow toLbOrderRow(HxrOrderRow row, String tenantId) {
|
private static String resolveSyncDataType(String dataType, Integer isResell) {
|
||||||
|
if (dataType != null && !dataType.trim().isEmpty()) {
|
||||||
|
return dataType.trim();
|
||||||
|
}
|
||||||
|
return isResell == null ? null : String.valueOf(isResell);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int countUnresell(List<HxrOrderRow> rows) {
|
||||||
|
int n = 0;
|
||||||
|
for (HxrOrderRow row : rows) {
|
||||||
|
if (row.isResell() == 0) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigDecimal parseMoney(String money) {
|
||||||
|
if (money == null || money.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new BigDecimal(money.trim());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LbOrderRow toLbOrderRow(
|
||||||
|
HxrOrderRow row,
|
||||||
|
String tenantId,
|
||||||
|
String dataType,
|
||||||
|
BigDecimal todayTotalMoneySum,
|
||||||
|
Integer todayOrderCount,
|
||||||
|
Integer todayUnresellCount) {
|
||||||
LbOrderRow e = new LbOrderRow();
|
LbOrderRow e = new LbOrderRow();
|
||||||
e.setId(row.id());
|
e.setId(row.id());
|
||||||
|
e.setDataType("detail_data");
|
||||||
e.setOldId(row.oldId());
|
e.setOldId(row.oldId());
|
||||||
e.setTenantId(tenantId);
|
e.setTenantId(tenantId);
|
||||||
|
e.setDataType(dataType);
|
||||||
|
e.setTodayTotalMoneySum(todayTotalMoneySum);
|
||||||
|
e.setTodayOrderCount(todayOrderCount);
|
||||||
|
e.setTodayUnresellCount(todayUnresellCount);
|
||||||
e.setSellerId(row.sellerId());
|
e.setSellerId(row.sellerId());
|
||||||
e.setBuyerId(row.buyerId());
|
e.setBuyerId(row.buyerId());
|
||||||
e.setOrderSn(row.orderSn());
|
e.setOrderSn(row.orderSn());
|
||||||
e.setTotalMoney(row.totalMoney());
|
e.setTotalMoney(parseMoney(row.totalMoney()));
|
||||||
e.setPayTime(row.payTime());
|
e.setPayTime(row.payTime());
|
||||||
e.setPayImg(row.payImg());
|
e.setPayImg(row.payImg());
|
||||||
e.setStatus(row.status());
|
e.setStatus(row.status());
|
||||||
|
|||||||
@@ -79,6 +79,11 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
/** 试用期包含的工作日天数(周一至周五),周六日不计入。 */
|
/** 试用期包含的工作日天数(周一至周五),周六日不计入。 */
|
||||||
private static final int TRIAL_WEEKDAY_COUNT = 3;
|
private static final int TRIAL_WEEKDAY_COUNT = 3;
|
||||||
|
|
||||||
|
/** 同事特权开通提醒中「特权开通日期」包含的工作日天数(与 syncHxrAdminColleagueVip 的 viptime 规则一致)。 */
|
||||||
|
private static final int COLLEAGUE_PRIVILEGE_WEEKDAY_COUNT = 2;
|
||||||
|
|
||||||
|
private static final String COLLEAGUE_VIP_GROUP_LABEL = "开通特权提醒";
|
||||||
|
|
||||||
private static final String PARSE_SYSTEM_PROMPT = """
|
private static final String PARSE_SYSTEM_PROMPT = """
|
||||||
你是信息抽取助手。用户会提供一段「进货申请」相关的自然语言订货信息。
|
你是信息抽取助手。用户会提供一段「进货申请」相关的自然语言订货信息。
|
||||||
请只输出一个 JSON 对象,不要 markdown 代码块,不要解释性文字。
|
请只输出一个 JSON 对象,不要 markdown 代码块,不要解释性文字。
|
||||||
@@ -651,28 +656,14 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId) {
|
LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
if (applyDateStart == null || applyDateEnd == null) {
|
ColleagueVipContext ctx = resolveColleagueVipContext(applyDateStart, applyDateEnd, tenantId);
|
||||||
|
if (ctx.validationError() != null) {
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
result.put("message", "申请开始日期与结束日期不能为空");
|
result.put("message", ctx.validationError());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (applyDateEnd.isBefore(applyDateStart)) {
|
List<LbPurchaseApply> rows = ctx.rows();
|
||||||
result.put("success", false);
|
if (rows.isEmpty()) {
|
||||||
result.put("message", "结束日期不能早于开始日期");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "租户id不能为空");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LambdaQueryWrapper<LbPurchaseApply> q = new LambdaQueryWrapper<>();
|
|
||||||
q.eq(LbPurchaseApply::getTenantId, tenantId.trim())
|
|
||||||
.ge(LbPurchaseApply::getApplyDate, applyDateStart)
|
|
||||||
.le(LbPurchaseApply::getApplyDate, applyDateEnd);
|
|
||||||
List<LbPurchaseApply> rows = this.list(q);
|
|
||||||
if (rows == null || rows.isEmpty()) {
|
|
||||||
result.put("success", true);
|
result.put("success", true);
|
||||||
result.put("message", "该条件下无申请记录,未调用第三方");
|
result.put("message", "该条件下无申请记录,未调用第三方");
|
||||||
result.put("totalRecords", 0);
|
result.put("totalRecords", 0);
|
||||||
@@ -683,26 +674,7 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> ApplyUserNames = new HashSet<>();
|
Set<String> tradeMatchedNicknames = ctx.tradeMatchedNicknames();
|
||||||
for (LbPurchaseApply row : rows) {
|
|
||||||
if (row.getColleagueName() != null && !row.getColleagueName().trim().isEmpty()) {
|
|
||||||
ApplyUserNames.add(row.getApplyUser().trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Set<String> tradeMatchedNicknames = new HashSet<>();
|
|
||||||
if (!ApplyUserNames.isEmpty()) {
|
|
||||||
LambdaQueryWrapper<LbDailyUserTrade> tradeQuery = new LambdaQueryWrapper<>();
|
|
||||||
tradeQuery.eq(LbDailyUserTrade::getTenantId, tenantId.trim())
|
|
||||||
.in(LbDailyUserTrade::getNickname, ApplyUserNames)
|
|
||||||
.select(LbDailyUserTrade::getNickname);
|
|
||||||
List<LbDailyUserTrade> matchedTrades = lbDailyUserTradeMapper.selectList(tradeQuery);
|
|
||||||
for (LbDailyUserTrade trade : matchedTrades) {
|
|
||||||
if (trade.getNickname() != null && !trade.getNickname().trim().isEmpty()) {
|
|
||||||
tradeMatchedNicknames.add(trade.getNickname().trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<String, Object>> details = new ArrayList<>();
|
List<Map<String, Object>> details = new ArrayList<>();
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
@@ -714,30 +686,10 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
one.put("applyUserName", applyUserName);
|
one.put("applyUserName", applyUserName);
|
||||||
String phone = row.getColleaguePhone() != null ? row.getColleaguePhone().trim() : "";
|
String phone = row.getColleaguePhone() != null ? row.getColleaguePhone().trim() : "";
|
||||||
one.put("colleaguePhone", phone);
|
one.put("colleaguePhone", phone);
|
||||||
if (applyUserName.isEmpty()) {
|
String skipReason = colleagueVipSkipReason(row, tradeMatchedNicknames);
|
||||||
|
if (skipReason != null) {
|
||||||
one.put("success", false);
|
one.put("success", false);
|
||||||
one.put("message", "colleague_name 为空,跳过");
|
one.put("message", skipReason);
|
||||||
fail++;
|
|
||||||
details.add(one);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!tradeMatchedNicknames.contains(applyUserName)) {
|
|
||||||
one.put("success", false);
|
|
||||||
one.put("message", "申请人姓名在 lb_daily_user_trade 中未找到 ,说明今天没进货 ,推荐人不能享受特权,跳过开通特权");
|
|
||||||
fail++;
|
|
||||||
details.add(one);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (phone.isEmpty()) {
|
|
||||||
one.put("success", false);
|
|
||||||
one.put("message", "colleague_phone 为空,跳过");
|
|
||||||
fail++;
|
|
||||||
details.add(one);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (row.getApplyDate() == null) {
|
|
||||||
one.put("success", false);
|
|
||||||
one.put("message", "applyDate 为空,跳过");
|
|
||||||
fail++;
|
fail++;
|
||||||
details.add(one);
|
details.add(one);
|
||||||
continue;
|
continue;
|
||||||
@@ -803,6 +755,168 @@ public class LbPurchaseApplyServiceImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exportColleagueVipExcel(
|
||||||
|
LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
ColleagueVipContext ctx = resolveColleagueVipContext(applyDateStart, applyDateEnd, tenantId);
|
||||||
|
if (ctx.validationError() != null) {
|
||||||
|
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ctx.validationError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LbPurchaseApply> exportRows = new ArrayList<>();
|
||||||
|
for (LbPurchaseApply row : ctx.rows()) {
|
||||||
|
if (colleagueVipSkipReason(row, ctx.tradeMatchedNicknames()) == null) {
|
||||||
|
exportRows.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Workbook workbook = new XSSFWorkbook()) {
|
||||||
|
Sheet sheet = workbook.createSheet("开通特权提醒");
|
||||||
|
|
||||||
|
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||||
|
CellStyle groupStyle = createGroupStyle(workbook);
|
||||||
|
CellStyle dataStyle = createDataStyle(workbook);
|
||||||
|
|
||||||
|
String[] headers = {"", "昵称", "手机号", "特权开通日期", "开通日期"};
|
||||||
|
Row headerRow = sheet.createRow(0);
|
||||||
|
headerRow.setHeightInPoints(22);
|
||||||
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
createExportCell(headerRow, i, headers[i], headerStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowIndex = 1;
|
||||||
|
if (!exportRows.isEmpty()) {
|
||||||
|
int groupStartRow = rowIndex;
|
||||||
|
for (LbPurchaseApply item : exportRows) {
|
||||||
|
Row row = sheet.createRow(rowIndex);
|
||||||
|
row.setHeightInPoints(20);
|
||||||
|
createExportCell(row, 1, formatColleagueVipNickname(item), dataStyle);
|
||||||
|
createExportCell(row, 2, nullToEmpty(item.getColleaguePhone()), dataStyle);
|
||||||
|
createExportCell(row, 3, formatColleaguePrivilegeRange(item.getApplyDate()), dataStyle);
|
||||||
|
createExportCell(row, 4, formatActivationDate(item.getApplyDate()), dataStyle);
|
||||||
|
rowIndex++;
|
||||||
|
}
|
||||||
|
int groupEndRow = rowIndex - 1;
|
||||||
|
Row firstRow = sheet.getRow(groupStartRow);
|
||||||
|
createExportCell(firstRow, 0, COLLEAGUE_VIP_GROUP_LABEL, groupStyle);
|
||||||
|
if (groupEndRow > groupStartRow) {
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(groupStartRow, groupEndRow, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustExportColumnWidths(sheet, headers);
|
||||||
|
|
||||||
|
String filename = "开通特权提醒_" + LocalDateTime.now().format(EXPORT_FILENAME_TS) + ".xlsx";
|
||||||
|
String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
||||||
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded);
|
||||||
|
|
||||||
|
try (ServletOutputStream os = response.getOutputStream()) {
|
||||||
|
workbook.write(os);
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同事特权开通提醒导出异常", e);
|
||||||
|
try {
|
||||||
|
response.reset();
|
||||||
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||||
|
response.setContentType("text/plain;charset=UTF-8");
|
||||||
|
response.getWriter().write("导出异常:" + e.getMessage());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record ColleagueVipContext(
|
||||||
|
String validationError,
|
||||||
|
List<LbPurchaseApply> rows,
|
||||||
|
Set<String> tradeMatchedNicknames) {}
|
||||||
|
|
||||||
|
private ColleagueVipContext resolveColleagueVipContext(
|
||||||
|
LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId) {
|
||||||
|
if (applyDateStart == null || applyDateEnd == null) {
|
||||||
|
return new ColleagueVipContext("申请开始日期与结束日期不能为空", List.of(), Set.of());
|
||||||
|
}
|
||||||
|
if (applyDateEnd.isBefore(applyDateStart)) {
|
||||||
|
return new ColleagueVipContext("结束日期不能早于开始日期", List.of(), Set.of());
|
||||||
|
}
|
||||||
|
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||||
|
return new ColleagueVipContext("租户id不能为空", List.of(), Set.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<LbPurchaseApply> q = new LambdaQueryWrapper<>();
|
||||||
|
q.eq(LbPurchaseApply::getTenantId, tenantId.trim())
|
||||||
|
.ge(LbPurchaseApply::getApplyDate, applyDateStart)
|
||||||
|
.le(LbPurchaseApply::getApplyDate, applyDateEnd);
|
||||||
|
List<LbPurchaseApply> rows = this.list(q);
|
||||||
|
if (rows == null) {
|
||||||
|
rows = List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> applyUserNames = new HashSet<>();
|
||||||
|
for (LbPurchaseApply row : rows) {
|
||||||
|
if (row.getColleagueName() != null && !row.getColleagueName().trim().isEmpty()
|
||||||
|
&& row.getApplyUser() != null && !row.getApplyUser().trim().isEmpty()) {
|
||||||
|
applyUserNames.add(row.getApplyUser().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set<String> tradeMatchedNicknames = new HashSet<>();
|
||||||
|
if (!applyUserNames.isEmpty()) {
|
||||||
|
LambdaQueryWrapper<LbDailyUserTrade> tradeQuery = new LambdaQueryWrapper<>();
|
||||||
|
tradeQuery.eq(LbDailyUserTrade::getTenantId, tenantId.trim())
|
||||||
|
.in(LbDailyUserTrade::getNickname, applyUserNames)
|
||||||
|
.select(LbDailyUserTrade::getNickname);
|
||||||
|
List<LbDailyUserTrade> matchedTrades = lbDailyUserTradeMapper.selectList(tradeQuery);
|
||||||
|
for (LbDailyUserTrade trade : matchedTrades) {
|
||||||
|
if (trade.getNickname() != null && !trade.getNickname().trim().isEmpty()) {
|
||||||
|
tradeMatchedNicknames.add(trade.getNickname().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ColleagueVipContext(null, rows, tradeMatchedNicknames);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String colleagueVipSkipReason(LbPurchaseApply row, Set<String> tradeMatchedNicknames) {
|
||||||
|
String applyUserName = row.getApplyUser() != null ? row.getApplyUser().trim() : "";
|
||||||
|
if (applyUserName.isEmpty()) {
|
||||||
|
return "colleague_name 为空,跳过";
|
||||||
|
}
|
||||||
|
if (!tradeMatchedNicknames.contains(applyUserName)) {
|
||||||
|
return "申请人姓名在 lb_daily_user_trade 中未找到 ,说明今天没进货 ,推荐人不能享受特权,跳过开通特权";
|
||||||
|
}
|
||||||
|
String phone = row.getColleaguePhone() != null ? row.getColleaguePhone().trim() : "";
|
||||||
|
if (phone.isEmpty()) {
|
||||||
|
return "colleague_phone 为空,跳过";
|
||||||
|
}
|
||||||
|
if (row.getApplyDate() == null) {
|
||||||
|
return "applyDate 为空,跳过";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatColleagueVipNickname(LbPurchaseApply item) {
|
||||||
|
String colleagueName = item.getColleagueName();
|
||||||
|
if (colleagueName != null && !colleagueName.trim().isEmpty()) {
|
||||||
|
return colleagueName.trim();
|
||||||
|
}
|
||||||
|
return item.getApplyUser() == null ? "" : item.getApplyUser().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatColleaguePrivilegeRange(LocalDate applyDate) {
|
||||||
|
if (applyDate == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
LocalDate start = firstWeekdayOnOrAfter(applyDate);
|
||||||
|
LocalDate endDate = endOfInclusiveWeekdaySpan(start, COLLEAGUE_PRIVILEGE_WEEKDAY_COUNT, null);
|
||||||
|
return start.format(PRIVILEGE_RANGE_FMT) + "-" + endDate.format(PRIVILEGE_RANGE_FMT);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exportExcel(LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response) {
|
public void exportExcel(LocalDate applyDateStart, LocalDate applyDateEnd, String tenantId, HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user