Changgou Mall (11): Pedido

Estude bastante e progrida todos os dias.

Este artigo foi incluído em meu repositório Github DayDayUP : github.com/RobodLee/DayDayUP, bem-vindo ao Star, por favor vá para a navegação de diretório para mais artigos

Endereço de entrega

Se você fizer um pedido no Jingdong ou no Taobao, você escolherá o endereço de entrega.As informações do endereço de entrega são armazenadas no MySQL, então o primeiro passo é realizar a função de consultar o endereço de entrega. A ideia é consultar o endereço de entrega através do nome do usuário, mas em vez de o front end passar o nome do usuário para o servidor, ele analisa diretamente o Token para obter o nome do usuário e, em seguida, consulta o banco de dados. A vantagem disso é a segurança. A implementação é muito simples, diretamente no código. A classe de ferramenta escrita antes é usada para analisar o token.

//	AddressController
@GetMapping("/user/list")
public Result<List<Address>> list() {
    
    
    String username = tokenDecodeUtil.getUserInfo().get("username");
    List<Address> addresses = addressService.list(username);
    return new Result<>(true,StatusCode.OK,"查询成功",addresses);
}
------------------------------------------------------------------------
//	AddressServiceImpl
@Override
public List<Address> list(String username) {
    
    
    return addressMapper.list(username);
}
-------------------------------------------------------------------------
//	AddressMapper
@Select("select * from tb_address where username = #{username}")
List<Address> list(String username);

Fazer um pedido

Fazer um pedido não significa que o front-end envie as informações do pedido diretamente para o servidor, que cria o pedido diretamente. Existem dois pontos a serem observados aqui:

  • Verificação de preço

    Por exemplo, há um produto para um evento, o preço original é de 99 yuans e o limite de tempo é de 88 yuans. Antes de clicar no botão enviar pedido, o preço havia sido restaurado para 99 yuan, mas o conteúdo da página não foi atualizado e ainda era 88 yuan. Assim, quando a encomenda for mencionada ao servidor, o back-end deve verificar novamente o preço na base de dados e fazer uma verificação, prevalecendo a consulta da base de dados, de forma a evitar prejuízos causados ​​pela variação dos preços.

  • Checagem de inventário

    Verificar o estoque é para evitar vendas excessivas. Por exemplo, quando eu entro na página de detalhes do produto, ela mostra que existem 5 peças restantes. Antes de enviar o pedido, o produto está esgotado, mas como a interface não foi atualizada, mostra que ainda está em estoque. Então, quando o pedido é enviado ao servidor. O back-end primeiro consulta o banco de dados quando ainda há estoque. Se não houver estoque, a criação do pedido falha, caso contrário, é bem-sucedida.

Portanto, nem tudo é passado pelo front-end, você pode consultar as duas tabelas relacionadas ao pedido.

Existem duas tabelas relacionadas a pedidos. Pedidos são registros gerados após clicar em Fazer pedido. Por exemplo, se eu fizer um pedido de 10 itens por vez, é um pedido, mas 10 detalhes do pedido são gerados. Entre eles, o tipo de pagamento , o consignatário , o telefone celular do consignatário e o endereço do consignatário são passados ​​no front-end e outras informações são preenchidas no back-end.

Depois de apresentar esse conteúdo, você pode escrever o código.

@PostMapping
public Result add(@RequestBody Order order){
    
    
    String username = tokenDecodeUtil.getUserInfo().get("username");
    order.setUsername(username);
    orderService.add(order);
    return new Result(true,StatusCode.OK,"添加成功");
}
---------------------------------------------------------------------------
@Override
public synchronized void add(Order order) {
    
    
    order.setId(String.valueOf(idWorker.nextId()));
    BoundHashOperations boundHashOperations = redisTemplate.boundHashOps("Cart_" + order.getUsername());
    int totalNum=0,totalMoney=0;    //总数量,总金额
    LocalDateTime localDateTime = LocalDateTime.now();
    List<OrderItem> orderItems = boundHashOperations.values();   //从购物车中获取订单明细
    if (orderItems == null || orderItems.size()==0) {
    
    
        throw new RuntimeException("购物车数据异常,下单失败");
    }
    List<Sku> skuList = skuFeign.findBySkuIds(order.getSkuIds()).getData(); //数据库中对应的sku集合
    //如果数据库中查询出来的sku集合数量与前端传过来的sku数量不一致,说明数据有误,下单失败
    if (skuList.size() != order.getSkuIds().size()){
    
    
        throw new RuntimeException("sku数据库数据异常,下单失败");
    }
    Map<Long,Sku> skuMap = skuList.stream().collect(Collectors.toMap(Sku::getId,a -> a));
    //遍历购物车中的数据,判断是否是选中的,将选中的订单明细数据补充完整
    for (OrderItem orderItem : orderItems) {
    
    
        if (order.getSkuIds().contains(orderItem.getSkuId())) {
    
         //判断当前遍历到的orderItem是否是选中的
            orderItem.setId(String.valueOf(idWorker.nextId()));
            orderItem.setOrderId(order.getId());
            orderItem.setIsReturn("0");
            Sku sku = skuMap.get(orderItem.getSkuId()); //数据库中的sku
            if (orderItem.getNum() <= sku.getNum()) {
    
       //判断库存是否充足,不足则报异常订单提交失败
                totalNum += orderItem.getNum();
            } else {
    
    
                throw new RuntimeException("库存不足,下单失败");
            }
            totalMoney += sku.getPrice();
        }
    }
    //减库存,删购物车
    for (OrderItem orderItem : orderItems) {
    
    
        if (order.getSkuIds().contains(orderItem.getSkuId())) {
    
    
            Sku sku = skuMap.get(orderItem.getSkuId()); //数据库中的sku
            sku.setNum(sku.getNum() - orderItem.getNum());	//减库存
            boundHashOperations.delete(orderItem.getSkuId());	//删购物车
            orderItemMapper.insertSelective(orderItem); //添加到订单明细表
        }
    }
    skuFeign.updateMap(skuMap); //将sku信息提交到数据库中的sku表
    
    order.setCreateTime(localDateTime);
    order.setUpdateTime(localDateTime);
    order.setTotalNum(totalNum);
    order.setTotalMoney(totalMoney);
    order.setSourceType("1");   //1.web
    order.setOrderStatus("0");
    order.setPayStatus("0");
    order.setIsDelete("0");
    orderMapper.insertSelective(order); //添加到订单表
}

Este trecho de código é um pouco longo. Primeiro, na camada do Controlador, ao analisar o Token, o nome do usuário é obtido e, em seguida, na camada de Serviço. Existe um campo no objeto do pedido

private List<Long> skuIds;  //选中的sku的id

Esta é uma coleção do id do produto selecionado na página. Porque quando você faz um pedido, você pode selecionar alguns produtos no carrinho de compras, não todos os produtos, você pode usar isso para determinar quais são selecionados.

Na camada de serviço, primeiro use skuIds para chamar Feign para obter os dados de coleta de produtos correspondentes. Devido à necessidade de julgamento de estoque, redução de estoque e consulta de preço, podemos obter esses dados. Para a conveniência de uso, eles são convertidos em uma coleção de mapas. Em seguida, consulte todos os dados do carrinho de compras, pois precisamos remover o produto pedido do carrinho de compras.

Em seguida, inicie a primeira travessia das mercadorias no carrinho de compras, o objetivo é determinar o estoque para evitar sobrevenda, calcular a quantidade total e calcular o valor total. Se a quantidade do pedido for maior que o estoque, o pedido falhará.

Se não houver nenhum fenômeno de sobrevenda durante a primeira travessia, você pode realizar a segunda travessia do carrinho de compras, o objetivo é reduzir o estoque, excluir as mercadorias que foram pedidas no carrinho de compras e adicionar os detalhes do pedido à lista de pedidos. Após a conclusão da travessia, envie as informações de sku do inventário alterado para o banco de dados. A razão para usar dois ciclos em vez de um é que, enquanto houver estoque insuficiente de um item, o pedido deve ser malsucedido, os dados no carrinho de compras não são modificados e um ciclo não pode atender à demanda.

Por fim, preencha as informações do pedido e adicione-as à tabela de pedidos. Neste ponto, o pedido é criado.

Neste código, várias situações anormais são tratadas.

  • Se os dados no carrinho de compras forem 0, isso significa que o front end pode passar o token errado e não há informações do produto sob o nome de usuário analisado. Nesse momento, o pedido falha.
  • Use a coleção skuId para consultar a coleção sku correspondente no banco de dados. Se a quantidade de dados for inconsistente, isso significa que um determinado skuId transmitido do front end está errado ou os dados no banco de dados estão errados, o pedido falha.
  • Estoque insuficiente, falha no pedido.
  • Para garantir a segurança do thread, a palavra-chave synchronized é adicionada.

Bem, a função de fazer um pedido está completa.

Também existe uma função de pontos do usuário.Isto é relativamente simples.É chamar o método no UserController através do Feign, e então modificar os dados dos pontos de acordo com o nome do usuário.Não há nada a dizer, o código não será postado.

Resumindo

Este artigo termina aqui. O conteúdo é relativamente pequeno. Existem apenas dois. Um é consultar o endereço de colheita com base no nome do usuário e o outro é a função de ordenação. A função de ordenação não é complicada, mas podem ocorrer alguns problemas. Vários pontos precisam ser abordados. Como você pode fazer um pedido sem a função de pagamento? O próximo artigo irá implementar a função de pagamento. Nos vemos na próxima!

A palavra-código não é fácil. Se você puder, dê-me um polegar para cima, favorito e siga.

Se você gostar do meu artigo, siga a conta pública do WeChat " R o b o d " e leia-o o mais rápido possível.

Código: https://github.com/RobodLee/changgou

Acho que você gosta

Origin blog.csdn.net/weixin_43461520/article/details/108319715
Recomendado
Clasificación