25. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--预算金额的币种转换

这篇文章的代码和22. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--切换主币种这篇文章的代码大体一样。这篇文章我们简单讲解一下。

既然收支记录都已经支持主币种转换的同时重新计算收支金额了,那预算也要支持切换主币种重新计算预算金额。我们一起来看一下。

一、实现

实现逻辑在这里我就不说了,不清楚的可以参考专栏的第22篇文章。

首先我们需要修改ConfigController控制器中的Update Action,在其中添加发布重新计算预算金额的消息,代码如下:

csharp 复制代码
/// <summary>
/// 更新用户配置
/// </summary>
/// <param name="configViewModel"></param>
/// <returns></returns>
[HttpPut]
[Route("Update")]
public ActionResult<ResponseData<bool>> Update([FromBody] ConfigViewModel configViewModel)
{
    try
    {
       	//more code ....
        //如果切换的是主币种,那么就将以前的所有金额全部转换成新的主币种的金额
        if (configViewModel.ConfigTypeEnum == ConfigTypeEnum.Currency)
        {
            //more code
            _ = _rabbitMqPublisher.Publish<MainCurrency>("UpdateBudgetAmount",
                "UpdateBudgetAmount", new MainCurrency()
                {
                    UserId = userId,
                    Currency = configViewModel.Value,
                    OldCurrency = oldValue
                });
        }

        return Ok(new ResponseData<bool>(HttpStatusCode.OK, data: true));
    }
    catch (Exception ex)
    {
        return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常"));
    }
}

在代码中通过UpdateBudgetAmount路由键向RabbitMQ发送重新计算预算金额的消息。接着我们修改RabbitMQBackgroundService类中的StartAsync方法,在其中添加处理预算金额转换的代码,代码如下:

csharp 复制代码
public async System.Threading.Tasks.Task StartAsync(CancellationToken cancellationToken)
{
   	//more code ...
    //根据新的主币种更新预算金额
    await _subscriberService.SubscribeAsync<MainCurrency>("UpdateBudgetAmount", "UpdateBudgetAmount",
        async (mainCurrency) =>
        {
            //1.获取所有预算
            using var scope = _serviceProvider.CreateScope();
            var budgetServer = scope.ServiceProvider.GetRequiredService<IBudgetServer>();
            var budgets = budgetServer.Query(mainCurrency.UserId);

            //2.将所有预算的金额转换为新的主币种(预算中的币种转换为新的主币种)
            var currencyServer = scope.ServiceProvider.GetRequiredService<ICurrencyServer>();
            var exchangeRateRecordServer = scope.ServiceProvider.GetRequiredService<IExchangeRateRecordServer>();
            Currency? query = currencyServer.Query(mainCurrency.Currency);
            if (query == null)
            {
                return;
            }
            Currency? oldCurrency = currencyServer.Query(mainCurrency.OldCurrency);
            if (oldCurrency == null)
            {
                return;
            }
            //获取预算币种和主币种的汇率
            ExchangeRateRecord? exchangeRateRecord =
                exchangeRateRecordServer.Query($"{oldCurrency.Abbreviation}_{query.Abbreviation}");
            if(exchangeRateRecord == null)
            {
                return;
            }
            for (int i = 0; i < budgets.Count; i++)
            {
                var budget = budgets[i];
                budget.Amount = exchangeRateRecord.ExchangeRate * budget.Amount;
                budget.Remaining = exchangeRateRecord.ExchangeRate * budget.Remaining;
            }

            //3.更新所有预算
            budgetServer.Update(budgets);
        });
}

新增的这段代码的功能是通过订阅RabbitMQ的消息来处理主币种变化后的预算金额更新。首先,SubscribeAsync方法用于订阅"UpdateBudgetAmount"消息,并为每条消息定义一个异步处理逻辑。当消息接收到后,代码会使用依赖注入容器_serviceProvider创建一个新的服务范围scope,以确保在处理期间可以获取所需的服务实例。接下来,代码获取IBudgetServer服务来查询与mainCurrency.UserId关联的所有预算。然后,它使用ICurrencyServerIExchangeRateRecordServer来查询新的和旧的币种信息,以及这两种币种之间的汇率。如果查询失败,比如无法找到币种或汇率记录,处理过程将提前终止。接着,代码循环遍历所有预算,并使用获取到的汇率将每个预算的金额和剩余金额从旧币种转换为新币种。这是通过将原金额和剩余金额乘以汇率来实现的。最后,调用budgetServer.Update方法,将更新后的预算列表保存到数据库中。

二、总结

这篇文章的代码与第22篇文章中的代码基本相同,主要目的是在主币种切换时,支持预算金额的重新计算。首先介绍了ConfigController中的Update方法如何在用户配置更新时,通过RabbitMQ发布"UpdateBudgetAmount"消息,触发预算金额的重新计算。然后,文章讲解了在RabbitMQBackgroundService中新增的代码,如何通过SubscribeAsync方法订阅该消息并处理主币种变化后的预算更新。处理逻辑包括获取用户的所有预算、查询新旧币种及其汇率、将预算金额从旧币种转换为新币种,并最终更新预算数据。

相关推荐
无风听海2 小时前
ASP.NET Core .NET 10 错误响应体系全景:从 BadRequest 到编译器基础设施
后端·asp.net·.net
qq_382949226 小时前
推荐一门不错的微服务实战课:Spring Cloud Alibaba 从入门到落地
微服务·云原生·架构
无聊的老谢7 小时前
DDD 驱动的电信网络优化微服务建模实战
微服务·云原生·架构
_codemonster19 小时前
30分钟快速搭建 Spring Cloud Alibaba 微服务实战(一)
微服务·架构·毕业设计·课程设计
Dongwoo Jeong1 天前
微服务架构(MSA)是如何诞生的?
微服务·云原生·架构
半旧夜夏1 天前
【保姆级】微服务组件环境搭建(Docker Compose版)
java·linux·spring cloud·微服务·云原生·容器
AI行业学习1 天前
.NET Framework 3.5 SP1 完整离线包【2026.5.31】
.net
西凉的悲伤1 天前
Spring Boot 、Spring Cloud 微服务架构认证授权方案
spring boot·spring cloud·微服务·架构·认证授权
学以智用1 天前
.NET Core 完整特性速查表(终极版)
后端·.net
苏渡苇1 天前
Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用
spring boot·docker·微服务·容器·kubernetes·seata·springcloud