feat:订单打印购物车查询

This commit is contained in:
dzc committed 2026-09-07 10:19:52 +08:00
1 parent a7c505e9fc
commit ec39c72f7e
4 files changed
+77 -3

No files matched your search

@@ -105,6 +105,16 @@ public interface RemoteCanteenSpuService {
@PostMapping("/canteenSpu/ad/getComboItemsBySpuIds")
R<Map<Long, List<OnlineSpuComboItemVO>>> getComboItemsBySpuIds(@RequestBody List<Long> spuIds);
/**
* 供 Hardware 异步打印任务等无用户上下文的服务间调用批量查询套餐组成。
*
* @param spuIds 套餐 SPU 主键列表,空列表返回空映射
* @return 套餐 SPU ID 与已按配置顺序排列的组成菜品映射
*/
@PostMapping("/canteenSpu/inner/getComboItemsBySpuIds")
@NoToken
R<Map<Long, List<OnlineSpuComboItemVO>>> getInnerComboItemsBySpuIds(@RequestBody List<Long> spuIds);
/**
* 购物车效验库存
* @param spuId
@@ -444,6 +444,18 @@ public class CanteenSpuController {
return R.ok(canteenSpuService.loadComboItemVos(spuIds));
}
/**
* 为无用户令牌的 Hardware 异步打印任务提供套餐组成查询,复用管理端相同的数据装配逻辑。
*
* @param spuIds 套餐 SPU 主键列表,空列表返回空映射
* @return 套餐 SPU ID 与组成菜品列表的映射
*/
@Inner
@PostMapping("/inner/getComboItemsBySpuIds")
public R<Map<Long, List<OnlineSpuComboItemVO>>> getInnerComboItemsBySpuIds(@RequestBody List<Long> spuIds) {
return R.ok(canteenSpuService.loadComboItemVos(spuIds));
}
@ApiCryptoAes
@GetMapping("/app/checkSpuStock")
@@ -799,20 +799,21 @@ public class HardInvoiceServiceImpl extends ServiceImpl<HardInvoiceMapper, HardI
}
/**
* 批量加载套餐类型和组成项;远程失败时按普通单品降级。
* 批量加载套餐类型和组成项;异步任务没有用户令牌,必须通过内部接口查询,远程失败时按普通单品降级。
*/
private Map<Long, ProductMetadata> loadProductMetadata(List<HardCarVo> cars) {
List<Long> productIds = cars.stream().map(HardCarVo::getProductId).filter(Objects::nonNull).distinct().toList();
if (productIds.isEmpty()) return Map.of();
try {
R<List<CanteenSpuEntity>> result = remoteCanteenSpuService.getSpuListByIds(productIds);
R<List<CanteenSpuEntity>> result = remoteCanteenSpuService.getInnerSpuListByIds(productIds);
if (result == null || !result.isOk() || result.getData() == null) return Map.of();
List<Long> comboIds = result.getData().stream()
.filter(item -> item != null && Objects.equals(item.getSpuType(), 2))
.map(CanteenSpuEntity::getId).toList();
Map<Long, List<OnlineSpuComboItemVO>> comboItems = Map.of();
if (!comboIds.isEmpty()) {
R<Map<Long, List<OnlineSpuComboItemVO>>> comboResult = remoteCanteenSpuService.getComboItemsBySpuIds(comboIds);
R<Map<Long, List<OnlineSpuComboItemVO>>> comboResult =
remoteCanteenSpuService.getInnerComboItemsBySpuIds(comboIds);
if (comboResult != null && comboResult.isOk() && comboResult.getData() != null) comboItems = comboResult.getData();
}
Map<Long, ProductMetadata> metadata = new LinkedHashMap<>();
@@ -7,6 +7,9 @@ import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.bsd.pjcloud.admin.api.dto.user.SysUserStudentDto;
import com.bsd.pjcloud.admin.api.dto.user.SysUserTeacherDto;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.canteen.api.feign.RemoteCanteenSpuService;
import com.bsd.pjcloud.canteen.entity.CanteenSpuEntity;
import com.bsd.pjcloud.canteen.vo.app.OnlineSpuComboItemVO;
import com.bsd.pjcloud.hard.api.constant.HardPrintStatusEnum;
import com.bsd.pjcloud.hard.api.constant.HardPrintTypeEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
@@ -34,6 +37,7 @@ import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Answers.CALLS_REAL_METHODS;
@@ -54,6 +58,9 @@ class HardInvoiceServiceImplTest {
private final HardOrderService orderService = mock(HardOrderService.class);
private final HardManagerService managerService = mock(HardManagerService.class);
private final HardPrinterService printerService = mock(HardPrinterService.class);
/** 无用户上下文的食堂商品内部查询客户端。 */
private final RemoteCanteenSpuService remoteCanteenSpuService = mock(RemoteCanteenSpuService.class);
private final ThreadPoolTaskExecutor taskExecutor = mock(ThreadPoolTaskExecutor.class);
private final HardInvoiceServiceImpl service = mock(HardInvoiceServiceImpl.class, CALLS_REAL_METHODS);
@@ -67,6 +74,7 @@ class HardInvoiceServiceImplTest {
ReflectionTestUtils.setField(service, "orderService", orderService);
ReflectionTestUtils.setField(service, "hardManagerService", managerService);
ReflectionTestUtils.setField(service, "printerService", printerService);
ReflectionTestUtils.setField(service, "remoteCanteenSpuService", remoteCanteenSpuService);
ReflectionTestUtils.setField(service, "hardTaskExecutor", taskExecutor);
}
@@ -242,6 +250,49 @@ class HardInvoiceServiceImplTest {
assertEquals("三年级二班", fields.get("班级"));
}
/** 兑换券异步生成必须使用无用户令牌的内部接口识别套餐及其组成,避免统一降级为单品。 */
@Test
void voucherMetadataUsesInnerSpuAndComboQueries() {
HardCarVo car = new HardCarVo();
car.setProductId(501L);
CanteenSpuEntity combo = new CanteenSpuEntity();
combo.setId(501L);
combo.setSpuType(2);
OnlineSpuComboItemVO item = new OnlineSpuComboItemVO();
item.setName("糖醋排骨");
item.setQuantity(1);
when(remoteCanteenSpuService.getInnerSpuListByIds(List.of(501L))).thenReturn(R.ok(List.of(combo)));
when(remoteCanteenSpuService.getInnerComboItemsBySpuIds(List.of(501L)))
.thenReturn(R.ok(Map.of(501L, List.of(item))));
@SuppressWarnings("unchecked")
Map<Long, Object> metadata = ReflectionTestUtils.invokeMethod(service, "loadProductMetadata", List.of(car));
Object product = metadata.get(501L);
assertNotNull(product);
assertTrue((Boolean) ReflectionTestUtils.invokeMethod(product, "combo"));
assertEquals(List.of(item), ReflectionTestUtils.invokeMethod(product, "items"));
verify(remoteCanteenSpuService).getInnerSpuListByIds(List.of(501L));
verify(remoteCanteenSpuService).getInnerComboItemsBySpuIds(List.of(501L));
verify(remoteCanteenSpuService, never()).getSpuListByIds(any());
verify(remoteCanteenSpuService, never()).getComboItemsBySpuIds(any());
}
/** 商品内部查询暂时不可用时应保持原有降级策略,避免已完成核销因打印资料失败而回滚。 */
@Test
void voucherMetadataFallsBackToSingleProductWhenInnerQueryFails() {
HardCarVo car = new HardCarVo();
car.setProductId(501L);
when(remoteCanteenSpuService.getInnerSpuListByIds(List.of(501L)))
.thenThrow(new RuntimeException("canteen service unavailable"));
@SuppressWarnings("unchecked")
Map<Long, Object> metadata = ReflectionTestUtils.invokeMethod(service, "loadProductMetadata", List.of(car));
assertTrue(metadata.isEmpty());
verify(remoteCanteenSpuService, never()).getInnerComboItemsBySpuIds(any());
}
private static HardOrderEntity order() {
return HardOrderEntity.builder().id(1L).hardId(10L).merchantId(30L).deptId(40L).tenantId(50L).build();
}