当前位置: 首页 > news >正文

22. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--切换主币种

这篇文章我们将结合主币种设置以及收支记录实现切换主币种后重新计算以前记录的转换后的金额。那么,为什么要在切换主币种后要重新计算转换后的金额呢?有以下两个原因:

  1. 统一的币种,方便我们统计数据
  2. 方便用户按照当地的币种查看收支

下面我们就一起来实现吧。

一、实现逻辑

我们先来看一下要实现这个功能所需要的数据:

  1. 新的主币种
  2. 转换前币种
  3. 转换前金额
    接着我们一起把实现的思路写出来。首先我们要修改主币种配置,将旧的主币种替换成新的主币种,主币种配置修改成后,我们会利用消息队列发送一条主币种修改通知,负责重新计算转换后的金额的代码订阅这个通知,当它收到通知后就开始执行重新计算记录转换后的金额。负责重新计算转换后的金额的代码会先去查询当前用户全部记录,然后对账本中每条记录进行重新计算转换后的金额,最后将修改结果更新到数据库。

二、实现

我们根据上一小节的思路,先自己实现切换主币种的全部功能,然后把自己的代码和下面的代码核对一下,看看哪里不一样。这里提醒一下,我们订阅主币种修改通知的代码应放在RabbitMQBackgroundService类中。

2.1 修改主币种

ConfigController

/// <summary>
/// 更新用户配置
/// </summary>
/// <param name="configViewModel"></param>
/// <returns></returns>
[HttpPut]
[Route("Update")]
public ActionResult<ResponseData<bool>> Update([FromBody] ConfigViewModel configViewModel)
{try{string userId = GetUserId();bool isExist = _configServer.IsExist(userId, configViewModel.Id);if (!isExist){return Ok(new ResponseData<bool>(HttpStatusCode.NotFound, "用户配置不存在"));}_configServer.Update(userId, configViewModel.Id, configViewModel.Value);//如果切换的是主币种,那么就将以前的所有金额全部转换成新的主币种的金额if (configViewModel.ConfigTypeEnum == ConfigTypeEnum.Currency){_ = _rabbitMqPublisher.Publish<MainCurrency>("UpdateConversionAmount", "UpdateConversionAmount",new MainCurrency(){UserId = userId,Currency = configViewModel.Value});}return Ok(new ResponseData<bool>(HttpStatusCode.OK, data: true));}catch (Exception ex){return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常"));}
}

这段代码的作用是更新用户配置,并在特定条件下触发与主币种切换相关的业务逻辑。首先,代码通过 GetUserId() 方法获取当前操作用户的唯一标识符 userId。随后,通过 _configServer.IsExist 方法检查用户配置是否存在。如果配置不存在,返回包含 NotFound 状态的响应,提示“用户配置不存在”。如果配置存在,调用 _configServer.Update 方法,更新指定的配置值 configViewModel.Value。接着,代码进一步判断 configViewModel.ConfigTypeEnum 是否为 Currency 类型,即当前更新的配置是否为主币种。当更新的配置是主币种时,通过 _rabbitMqPublisher.Publish 方法向消息队列发送一条 UpdateConversionAmount 消息,其中包含用户 Id 和新的主币种Id。这一步的目的是通知其他系统或模块,执行与主币种切换相关的金额转换逻辑。

2.2 重新计算转换后的金额

RabbitMQBackgroundService

//more codeawait _subscriberService.SubscribeAsync<MainCurrency>("UpdateConversionAmount", "UpdateConversionAmount",
async (mainCurrency) =>
{//1.获取所有收支记录var recordService = _serviceProvider.GetRequiredService<IIncomeExpenditureRecordServer>();var records = recordService.QueryByUserId(mainCurrency.UserId);//2.将所有记录的金额转换为新的主币种(记录中的币种转换为新的主币种)var currencyServer = _serviceProvider.GetRequiredService<ICurrencyServer>();var exchangeRateRecordServer = _serviceProvider.GetRequiredService<IExchangeRateRecordServer>();Currency? query = currencyServer.Query( mainCurrency.Currency);if (query == null){return;}for (int i = 0; i < records.Count; i++){var record = records[i];var currency = record.Currency;//获取记录币种和主币种的汇率ExchangeRateRecord? exchangeRateRecord =exchangeRateRecordServer.Query($"{query.Abbreviation}_{currency.Abbreviation}");if (exchangeRateRecord != null)record.AfterAmount = exchangeRateRecord.ExchangeRate * record.BeforAmount;}//3.更新所有记录recordService.UpdateRecord(records);
});//more code

这段代码实现了一个异步消息订阅和处理的逻辑,用于在主币种发生变更时更新所有收支记录的金额。代码逻辑通过订阅消息队列中的 UpdateConversionAmount 主题来触发。 核心流程是:通过 _subscriberService.SubscribeAsync 方法订阅名为 UpdateConversionAmount 的消息,并注册一个异步处理函数。在处理函数中,首先从依赖注入容器中获取 IIncomeExpenditureRecordServer 服务,查询出指定用户的所有收支记录。接着,使用 ICurrencyServer 查询新的主币种信息,确保其存在;然后通过 IExchangeRateRecordServer 获取当前记录的币种和新的主币种之间的汇率。如果汇率数据存在,则将记录中的金额 (BeforAmount) 转换为以新的主币种为单位的金额 (AfterAmount)。最后,通过 recordService.UpdateRecord 将更新后的记录批量保存到数据库中。

三、总结

通过主币种切换的业务场景,探讨了如何在用户更改主币种配置后重新计算历史收支记录的转换金额。这一功能的实现基于两个核心需求:统一币种便于统计数据,以及方便用户按照本地币种查看收支信息。实现过程中,首先修改主币种配置,当用户设置新的主币种后,系统通过消息队列发送变更通知。相关处理逻辑通过 RabbitMQBackgroundService 订阅该通知,触发重新计算金额的操作。具体流程包括:查询当前用户的所有收支记录,获取新的主币种和原币种之间的汇率,并根据汇率计算每条记录的转换金额,最后更新数据库中的记录。
该方案采用分层设计和异步消息机制,将主币种的配置管理与金额转换逻辑解耦,提升了系统的可扩展性和维护性。整体流程清晰,代码实现规范,为类似场景的开发提供了良好的参考。

相关文章:

22. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--切换主币种

这篇文章我们将结合主币种设置以及收支记录实现切换主币种后重新计算以前记录的转换后的金额。那么&#xff0c;为什么要在切换主币种后要重新计算转换后的金额呢&#xff1f;有以下两个原因&#xff1a; 统一的币种&#xff0c;方便我们统计数据方便用户按照当地的币种查看收…...

01.02周四F34-Day43打卡

文章目录 1. 地是湿的。昨晚估计下雨了。2. 你可能把包丢在餐厅里了吧?3. 她说他可能误了航班。4. 我本来应该早点来的,但路上特别堵。5. 约翰可能在那次事故中受了重伤。6. 这是一个情景对话7. 我本可以走另一条路的。8. 我准是瘦了不少,你看我这裤子现在多肥。9. 钱没了!会…...

行业商机信息付费小程序系统开发方案

行业商机信息付费小程序系统&#xff0c;主要是整合优质行业资源&#xff0c;实时更新的商机信息。在当今信息爆炸的时代&#xff0c;精准、高效地获取行业商机信息对于企业和个人创业者而言至关重要。 一、使用场景 日常浏览&#xff1a;用户在工作间隙或闲暇时间&#xff0c…...

cut-命令详解

一、命令 1.cut列截取命令 cut命令的默认分隔符是制表符 2.参数&#xff1a; -f 列号 #提取第几列-d 分隔符 #按照指定分隔符分割列-c 字符范围 #不依赖分隔符来区分列&#xff0c;而是通过字符范围&#xff08;行首为0&#xff09;来进行字段提取。“n-”表…...

Apache MINA 反序列化漏洞CVE-2024-52046

漏洞描述&#xff1a; Apache MINA 是一个功能强大、灵活且高性能的网络应用框架。它通过抽象网络层的复杂性&#xff0c;提供了事件驱动架构和灵活的 Filter 链机制&#xff0c;使得开发者可以更容易地开发各种类型的网络应用。 Apache MINA 框架的 ObjectSerializationDeco…...

二、AI知识(神经网络)

二、AI知识&#xff08;神经网络&#xff09; 1.常用算法 FNN CNN RNN LSTM DNN GRU 2.深度学习中概念及算法 1. 感知机 感知机&#xff08;Perceptron&#xff09;是一种最早的人工神经网络模型之一&#xff0c;通常用来解决二分类问题。它由弗兰克罗森布拉特&#…...

node.js之---子线程(child_process)模块

为什么需要子线程&#xff08;child_process&#xff09;模块 Worker Threads 的基本概念 如何使用 Worker Threads Worker Threads 的性能 Worker 线程的优势和限制 进阶用法&#xff1a;共享内存 为什么需要子线程&#xff08;child_process&#xff09;模块 在 Node.js…...

Json字符串解析失败

通过第三方服务&#xff0c;拿到响应体的data对象&#xff08;拿到的时候对象是有值的&#xff09; 通过JSON.parseObject方法&#xff0c;拿到的对象&#xff0c;值为null 通过查看对应的json字符串&#xff0c;发现命名不一样... JSONField SeriealizedName注解是用来解析j…...

LeetCode算法题——螺旋矩阵ll

题目描述 给你一个正整数n&#xff0c;生成一个包含1到n2所有元素&#xff0c;且元素按顺时针顺序螺旋排列的n x n正方形矩阵matrix 。 示例 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]题解 思路&#xff1a; 将整个过程分解为逐圈填充的过程&#xf…...

【开源社区openEuler实践】hpcrunner

title: 探索 Hpcrunner&#xff1a;高性能计算的得力助手 date: ‘2024-12-31’ category: blog tags: Hpcrunner高性能计算任务调度资源优化 sig: HPC archives: ‘2024-12’ author:way_back summary: Hpcrunner 作为高性能计算领域的一款实用工具&#xff0c;专注于优化任务…...

linux下安装达梦数据库v8详解

目录 操作系统、数据库 1、下载达梦数据库 2、安装前准备 2.1、建立数据库用户和组 2.2、修改文件打开最大数 2.3、挂载镜像 2.4、新建安装目录 3、数据库安装 4、配置环境变量 5、初始化数据库实例 6、注册服务 7、使用数据库 8、卸载数据库 9、多实例管理 10、…...

Redis的常用命令

Redis中文字典网站 redis 命令手册https://redis.com.cn/commands.html Keys * 查看当前库所有的key exists ke 判断某个key是否存在 type key查看你的key是什么类型 Del key删除执行的key数据 unlink key非阻塞删除&#xff0c;仅仅将keys从keyspace元数据中删除&#xf…...

Docker入门常用命令总结

1.从远程仓库拉取一个纯净的镜像 docker pull docker .io/centos 2.创建并进入容器&#xff08;左外右内&#xff09; docker run --name xxx -dit 镜像id&#xff08;镜像名称:Tag&#xff09; /bin/bash 【参数必须放在镜像ID之前】 -i 让Docker分配一个伪终端&#xff0c;并…...

【Qt】容器控件、布局管理控件

目录 容器控件 QGroupBox QTabWidget 布局管理控件 QVBoxLayout 例子&#xff1a; QHBoxLayout 例子&#xff1a; QGridLayout 例子&#xff1a; 例子&#xff1a; QFormLayout 例子&#xff1a; QSpacerItem 例子&#xff1a; 容器控件 QGroupBox 表示一个带有…...

cesium小知识:常见的20多种property详解

要详细解释 Cesium 中所有的 Property 类,内容确实会非常丰富且详尽。 Property 基础 Property 是 Cesium 中用于表示随时间或条件变化的值的基础类。它允许你定义属性值如何根据时间、用户交互或其他逻辑动态改变。Property 的设计使得你可以创建复杂的动画和交互效果,而…...

图数据库 | 17、高可用分布式设计(上)

我们在前面的文章中&#xff0c;探索了多种可能的系统扩展方式&#xff0c;以及每种扩展方式的优劣。 本篇文章将通过具体的架构设计方案来对每一种方案的设计、投入产出比、各项指标与功能&#xff0c;以及孰优孰劣等进行评价。 在设计高性能、高可用图数据库的时候&#xf…...

1.运控概述

以下并不是我原创&#xff08;包括图片&#xff09;&#xff0c;都是来源于网络收集。如CSDN博主&#xff0c;朝夕教育&#xff0c;AI等。 什么是运动控制 运控是指“控制移动”之意&#xff0c;可以利用各种电机进行位置控制等操作&#xff0c;让机器听懂你的指令。 什么是…...

DuckDB:密钥管理器及其应用

密钥管理器(Secrets Manager)为所有使用密钥的后端提供了统一的用户界面。密钥信息可以被限定范围&#xff0c;因此不同的存储前缀可以有不同的密钥信息&#xff0c;例如允许在单个查询中连接跨组织的数据。密钥也可以持久化&#xff0c;这样就不需要在每次启动DuckDB时都指定它…...

单元测试4.0+思路总结

Jmockit使用笔记_增加代码覆盖率_覆盖try catch_使用new MockUp私有方法-CSDN博客 一般使用new MockUp模拟被测试代码中的私有方法(常用&#xff09; 使用new Expetations模拟被测试代码中的方法?...

epoll 水平ET跟边缘LT触发的区别是什么

epoll默认的是水平触发 意思就是当我们depoll默认的是水平触发 LT 模式&#xff08;水平触发&#xff09; 工作机制&#xff1a;在 LT 模式下&#xff0c;只要文件描述符&#xff08;例如套接字&#xff09;对应的 I/O 缓冲区中有数据可读或者可写空间&#xff08;对于写操作…...

基于YOLOv8深度学习的花卉识别检测系统(YOLOv8+YOLO数据集+UI界面+Python项目源码+模型)

一、项目介绍 随着计算机视觉技术的快速发展&#xff0c;基于深度学习的图像识别技术在植物分类与识别领域展现出巨大的应用潜力。本系统基于先进的YOLOv8目标检测算法&#xff0c;构建了一个高效准确的花卉识别检测系统&#xff0c;能够实现对13种不同花卉的实时检测与识别。…...

从POC到EXP:深入拆解CVE-2025-0282利用链中的三大‘拦路虎’(NX/PIE、虚函数、内存释放)与绕过思路

从POC到EXP&#xff1a;深入拆解CVE-2025-0282利用链中的三大‘拦路虎’&#xff08;NX/PIE、虚函数、内存释放&#xff09;与绕过思路 现代漏洞利用已演变为攻防双方在二进制层面的精密博弈。当安全研究员发现一个栈溢出漏洞时&#xff0c;真正的挑战往往始于漏洞验证之后——…...

手把手教你用Qt6和Arduino Uno打造实时数据监控面板(附串口数据粘包处理源码)

基于Qt6与Arduino Uno的工业级数据可视化系统开发实战 在工业物联网和智能硬件开发领域&#xff0c;实时数据监控是核心需求之一。想象一下这样的场景&#xff1a;车间里的温度传感器阵列通过Arduino采集数据&#xff0c;工程师在办公室的PC端就能实时查看温度曲线波动&#x…...

浏览器插件:让Markdown预览效率提升300%的秘密武器

浏览器插件&#xff1a;让Markdown预览效率提升300%的秘密武器 【免费下载链接】markdown-viewer Markdown Viewer / Browser Extension 项目地址: https://gitcode.com/gh_mirrors/ma/markdown-viewer 作为开发者、学生或技术写作者&#xff0c;你是否经常遇到这些困扰…...

GitHub下载加速终极指南:3分钟让你的克隆速度提升100倍

GitHub下载加速终极指南&#xff1a;3分钟让你的克隆速度提升100倍 【免费下载链接】Fast-GitHub 国内Github下载很慢&#xff0c;用上了这个插件后&#xff0c;下载速度嗖嗖嗖的~&#xff01; 项目地址: https://gitcode.com/gh_mirrors/fa/Fast-GitHub 如果你经常需要…...

Wangle客户端开发实战:从零开始构建高效网络应用

Wangle客户端开发实战&#xff1a;从零开始构建高效网络应用 【免费下载链接】wangle Wangle is a framework providing a set of common client/server abstractions for building services in a consistent, modular, and composable way. 项目地址: https://gitcode.com/g…...

实战避坑:用Playwright+Selenium绕过电商网站验证码的3种方法(附Python代码)

实战避坑&#xff1a;用PlaywrightSelenium绕过电商网站验证码的3种方法&#xff08;附Python代码&#xff09; 电商平台的反爬虫机制日益复杂&#xff0c;验证码作为核心防线之一&#xff0c;已经从简单的图文识别升级到行为验证、智能风控等多维度拦截。本文将聚焦淘宝、京东…...

ViT图像分类-中文-日常物品完整指南:4090D单卡环境配置与中文类别映射说明

ViT图像分类-中文-日常物品完整指南&#xff1a;4090D单卡环境配置与中文类别映射说明 想试试用AI模型来识别你手机里的照片吗&#xff1f;比如&#xff0c;拍一张桌上的水杯、键盘或者零食&#xff0c;让模型告诉你它是什么。今天要介绍的这个工具&#xff0c;就能帮你轻松实…...

告别重复劳动:用快马ai生成高效openclaw脚本提升安卓测试效率

告别重复劳动&#xff1a;用快马AI生成高效OpenClaw脚本提升安卓测试效率 在安卓自动化测试中&#xff0c;编写重复性的设备操作脚本往往是最耗时耗力的环节。每次测试新版本&#xff0c;我们都需要重复编写类似的点击、滑动、输入等操作代码&#xff0c;不仅效率低下&#xf…...

Windows 10 64位系统下Neo4j社区版与桌面版安装全攻略(2023最新版)

1. Neo4j简介与安装准备 如果你正在寻找一款强大的图数据库来管理复杂的关系数据&#xff0c;Neo4j绝对是个不错的选择。作为目前最流行的开源图数据库&#xff0c;它用起来就像在画一张巨大的网络图——每个节点代表实体&#xff08;比如人或产品&#xff09;&#xff0c;每条…...