| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- package com.etotem.cfc.controller.special;
- import com.etotem.cfc.common.Result;
- import com.etotem.cfc.entity.SpecialPriceDeal;
- import com.etotem.cfc.service.SpecialPriceService;
- import com.etotem.cfc.util.ParamUtils;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import javax.annotation.Resource;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * 限时特价(扫码闪购)小程序端接口。
- * 设计见 docs/superpowers/specs/2026-10-20-limited-time-special-price-design.md
- *
- * <p>注意:{@code /api/special-price/info} 处于白名单(免登录),{@code JwtInterceptor} 命中
- * PUBLIC_PATHS 后直接 return true,不写入任何 request attribute(连匿名 userId 也不写)。
- * 因此本控制器禁止使用 {@code @RequestAttribute("userId")},{@code userPurchased/userRemaining}
- * 恒为 0;每人限购由下单接口 {@code ProductOrderService.createSpecialDealOrder} 兜底校验。</p>
- */
- @RestController
- @RequestMapping("/api/special-price")
- public class SpecialPriceController {
- @Resource
- private SpecialPriceService specialPriceService;
- /**
- * 查询特价活动信息(公开)。
- * 请求体:{@code {dealId}}
- * 返回 data 字段:id, productId, name, specialPrice, startTime, endTime, runStatus,
- * totalQuantity, soldQuantity, remainingQuantity, perUserLimit, allowCoupon,
- * userPurchased, userRemaining。runStatus 严格取值
- * DRAFT/ACTIVE/NOT_STARTED/SOLD_OUT/ENDED/DISABLED/INVALID。
- */
- @PostMapping("/info")
- public Result<Map<String, Object>> info(@RequestBody Map<String, Object> params) {
- Long dealId = ParamUtils.getLong(params.get("dealId"));
- Map<String, Object> data = new HashMap<>();
- data.put("dealId", dealId);
- if (dealId == null) {
- data.put("runStatus", "INVALID");
- data.put("message", "活动不存在");
- return Result.success(data);
- }
- SpecialPriceDeal deal = specialPriceService.getById(dealId);
- if (deal == null) {
- data.put("runStatus", "INVALID");
- data.put("message", "活动不存在");
- return Result.success(data);
- }
- int total = deal.getTotalQuantity() != null ? deal.getTotalQuantity() : 0;
- int sold = deal.getSoldQuantity() != null ? deal.getSoldQuantity() : 0;
- String runStatus = SpecialPriceService.computeRunStatus(
- deal.getStatus(), deal.getStartTime(), deal.getEndTime(), sold, total);
- data.put("id", deal.getId());
- data.put("productId", deal.getProductId());
- data.put("name", deal.getName());
- data.put("specialPrice", deal.getSpecialPrice());
- data.put("startTime", deal.getStartTime());
- data.put("endTime", deal.getEndTime());
- data.put("runStatus", runStatus);
- data.put("totalQuantity", total);
- data.put("soldQuantity", sold);
- data.put("remainingQuantity", Math.max(total - sold, 0));
- data.put("perUserLimit", deal.getPerUserLimit() != null ? deal.getPerUserLimit() : 1);
- data.put("allowCoupon", deal.getAllowCoupon() != null ? deal.getAllowCoupon() : 0);
- // 白名单路径不注入用户属性:恒为 0,每人限购由下单接口兜底校验
- data.put("userPurchased", 0);
- data.put("userRemaining", 0);
- return Result.success(data);
- }
- }
|