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方法订阅该消息并处理主币种变化后的预算更新。处理逻辑包括获取用户的所有预算、查询新旧币种及其汇率、将预算金额从旧币种转换为新币种,并最终更新预算数据。

相关推荐
大鹏说大话7 小时前
PHP 微服务架构实战:从单体应用到分布式系统的演进之路
微服务·架构·php
kyle~9 小时前
.NET 软件开发平台
.net
zhangjw3410 小时前
第43篇:微服务网关:Spring Cloud Gateway,统一接口入口
微服务·云原生·架构
一个帅气昵称啊11 小时前
.Net C# AI智能体开发-AI智能体
人工智能·c#·.net
智码看视界11 小时前
Day58-K8s部署Spring Boot微服务:ConfigMap+Secret+HPA
spring boot·微服务·云原生·kubernetes·k8s·hpa
星期一研究室1 天前
为什么有些文档你永远不想打开第二次
微服务·产品·设计
码农刚子1 天前
用 .NET 8 + uni-app 做一套多租户畜牧 SaaS:我们在秦巴牧云踩过的 6 个坑
uni-app·.net·saas
lisin-lee-cooper2 天前
简单聊聊 OpenFeign 框架源码
java·微服务
星期一研究室2 天前
长文里的观点太容易混在一起?用引用块把重点分清楚
微服务·产品·设计
宝桥南山3 天前
Blazor Web Assembly - 体验一下Authentication State从Server共享给Client
microsoft·微软·c#·asp.net·.net·.netcore