惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
博客园_首页
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
罗磊的独立博客
V
Visual Studio Blog
Know Your Adversary
Know Your Adversary
Hacker News - Newest:
Hacker News - Newest: "LLM"
美团技术团队
L
LINUX DO - 最新话题
The Last Watchdog
The Last Watchdog
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
云风的 BLOG
云风的 BLOG
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
I
InfoQ
Last Week in AI
Last Week in AI
V2EX - 技术
V2EX - 技术
量子位
S
Secure Thoughts
L
LangChain Blog
The Hacker News
The Hacker News
H
Help Net Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
K
Kaspersky official blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
I
Intezer
Vercel News
Vercel News
Hacker News: Ask HN
Hacker News: Ask HN
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
S
Securelist
阮一峰的网络日志
阮一峰的网络日志
G
Google Developers Blog
Help Net Security
Help Net Security
Martin Fowler
Martin Fowler
爱范儿
爱范儿
Y
Y Combinator Blog
C
Check Point Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Мультивалютность в ERP — считаем деньги в тенге, SOLANA и Theter одновременно [Go]
mainbotan · 2026-06-26 · via Все публикации подряд на Хабре

Средний

5 мин

0

Статья не про 1С, можно позволить себе расслабиться и поесть. Удалены все ссылки на проект, кроме исходников на Github, чтобы особенно самоотверженные модераторы в очередной раз не приняли годную техническую статью за рекламу… но кто хочет, тот всегда найдёт. Приятного чтения.

А помните, было время…

Трансграничные переводы USDT в 2026 году в российских реалиях — уже давно не новость для микро- и малого бизнеса нашей страны. Сотни и тысячи автосервисов, сервисно-производственных предприятий и в целом любой бизнес, имеющий дело с закупкой сырья из-за границы, рано или поздно сталкивается с необходимостью оплаты закупок в чём угодно (хоть натурой), но не в рублях. В ход идут казахские тенге, tether (USDT), Solana и прочие экстравагантные монетки.

Помимо бизнеса этих сегментов, трансграничные переводы в криптовалюте всё чаще применяются для оплаты услуг аутсорса — привет, разработчик на Rust, попивающий чаёк на Кипре (в то время как я гнию в московской панельке). Кроме этого, не будем забывать про граждан, намеренно укрывающихся от уплаты налогов и привыкших принимать и оплачивать 80% оборота, например, тем же USDT.

Добро пожаловать в 2026

Добро пожаловать в 2026

Так получилось, что я родился скромным Goфером и год назад начал работу над самописной ERP-подобной учётной системой для микробизнеса РФ [Go + pgx | Next.js + TS]. Пару месяцев назад я столкнулся с задачей адаптировать финансовый модуль Kroncl (название платформы) для мультивалютного учёта. Проблема практически любого предприятия малого масштаба, ведущего бизнес более чем в двух рабочих валютах, очень проста — деньги уходят, деньги приходят, курсы меняются, а мы учитываем только рублёвые активы (в лучшем случае). При этом все наши операции по криптокошелькам представляют собой мистические артефакты, которые вроде как есть, но не попадают даже во внутреннюю отчётность для владельца бизнеса.

В результате пары бессонных ночей фин. модуль начал поддерживать 16 валют для создания операций — как фиатных, так и крипто — и научился рассчитывать рублёвый баланс организации, исходя из операций во всех валютах по курсу на момент их создания. Посему в этой статье речь пойдёт о реализации мультивалютности на Go, курсах ЦБ и CoinGecko и разных подходах к решению одной и той же проблемы.

Github | Apache 2.0

...

...

Для начала

…для начала поймём, с чем мы работаем. Основа фин. ядра в большинстве учётных систем — транзакции двух направлений: трата или доход. В сухом остатке движение средств в любой организации определяется именно операциями этих двух видов. Каждая операция, в свою очередь, что и логично, помимо направления имеет как минимум сумму. В случае с мультивалютностью мы не можем обойтись только этим значением — нам необходимо понимать, в какой валюте была произведена операция. По этой причине мы просто добавляем ячейку типа CURRENCY_CODE для операций и храним в ней ISO-код валюты.

Всё, на этом можно было бы заканчивать и прощаться, ведь, по большому счёту, мультивалютностью можно назвать саму возможность указывать для операций код валюты. Так, к слову, выглядит мультивалютность в представлении систем вроде Битрикс24 и …

Но на основании только кодов и сумм операций можно сделать разве что свод балансов в каждой конкретной валюте. Мы же не так просты и, что ещё более важно, любой здравый человек с большой вероятностью захочет иметь представление о всех своих активах в одной конкретной валюте, например рублях. Тогда у нас возникнет необходимость в возможности конвертации сумм всех операций во все нужные нам валюты, чтобы на их основании можно было рассчитывать единый баланс.

Конвертация

Мы скажем: хорошо, при запросах к сводке будем рассчитывать баланс организации на основании операций и курса всех валют на текущий момент. Подобное решение стало бы по меньшей мере роковой ошибкой, грозящей возможными исками владельцев компаний-клиентов. Ведь достаточно взглянуть на динамику изменения курса доллара (или, что ещё лучше, BTC) и понять, что расчёт баланса организации по текущим курсам приведёт к огромным кассовым разрывам.

Поэтому для проведения корректной конвертации номиналов (сумм) операций нам необходимо брать курс её валюты на момент создания записи, а не на сегодня. Но как лучше? Конвертировать сумму во все нужные валюты непосредственно в момент создания или рассчитывать динамически, опираясь на историю изменения курсов?

Конвертируем сразу

На момент создания операции берём курс выбранной валюты и пересчитываем сумму во все нужные нам валюты. Таким образом, если нужно поддерживать 8 валют — плюс 8 дополнительных ячеек, для 40 — 40 и так далее. Вместо простой связи AMOUNT + CURRENCY_CODE у нас будут добавляться ячейки по типу: IN_RUB, IN_BTC, IN_USDT и т.д.

В какой-то момент такое ведение проекта приведёт к неконтролируемому кашмару, в котором для добавления новой валюты придётся лезть в миграции. Помимо неудобства, не будем забывать про конечный ресурс нашей базы данных, который будет улетать по мере накопления истории операций. Да, используя такой подход, мы получаем лучшую скорость на этапе расчёта баланса, ведь всё необходимое уже посчитано, но минусы данного подхода всё же перевешивают.

Конвертируем при расчёте баланса

Гораздо более аккуратным решением будет динамический расчёт баланса на основании истории операций и истории изменения курсов всех валют (кэш в оперативке). Работает это по следующему принципу:

  • отдельная таблица вида currency_rates, хранящая историю изменения курсов необходимых нам валют. Структура таблицы крайне проста: id (ISO-код), rate NUMERIC(18, 8) (курс валюты в базовой, мы русские, значит, православный RUB), timestamp (время обновления), source (источник: ваши провайдеры курсов);

  • из провайдеров (о них ещё пойдёт речь) регулярно по указанному периоду подгружаются курсы интересующих нас валют в рублях, полученные значения сохраняются в таблицу (для каждой валюты отдельная запись) и помечаются датой + временем обновления;

  • при запросе баланса организации в рублях отдельный сервис получает историю изменения курсов из памяти в оперативке и «накладывает» её на историю операций организации, находя для каждой операции самый ближайший курс её валюты; после пересчёта мы получаем операции с суммами в базовой валюте;

  • полученные суммы операций просто суммируются, и — пам-пам-пам — мы имеем баланс на основе истории операций, пересчитанных в базовую валюту по курсам, соответствующим курсам валют на момент создания каждой конкретной операции.

Полная реализация пакета currency, отвечающего за конвертацию валют, представлена здесь, его методы вызываются из пакета модуля fm, представленного здесь. Интересным (для меня) моментом во всём этом деле является работа с кэшем, представленным в виде USD_2026-06-23:73.44 для фиатных валют и BTC_2026-06-23_15:4712189 для крипто (для фиата период обновления меньше — один день). Кроме того, если возьмётесь за это дело, не накосячьте с часовыми поясами операций и записей кэша или получите рассинхрон в несколько часов (ближайшим курсом для отдельной валюты будет считаться не самый близкий курс).

Теперь о провайдерах

Допустим, но откуда брать курсы валют и как, собственно, обновлять? Для фиата ответ очевиден — ЦБ РФ: https://www.cbr-xml-daily.ru методом /daily_utf8.xml. Не забываем про поле <Nominal> в каждой валюте, означающее, на сколько нужно делить <Value> (ну, или просто берём <VunitRate>). Лимиты у сайта большие, пользуем.

Для криптовалют по типу USDT, USDC, ETH, TON… ответ тоже очевиден — CoinGecko. API имеет лимит в 10 000 запросов в месяц на бесплатном плане, чего хватает для разумного обновления курсов каждые 15–30 минут, в нашем случае — 60 минут (остаётся запас на тестовые стенды).

Как обновлять

Обновление курсов валют и последующее сохранение в currency_rates реализовывается простыми воркерами, гетающими актуальные курсы и кладущими их в базу. Просто и оптимально. Для каждого провайдера — свой cron-воркер со своим периодом обновления.

Реализация представлена в пакете currency, поддиректория workers.

В итоге…

В конечном итоге фин. модуль понимает 16 валют, включая как фиат, так и крипто, и умеет сводить баланс в рубли со всех операций вне зависимости от её валюты.

оппа

оппа

Kroncl — операционная учётная система малого бизнеса. Физическая изоляция, 5 модулей, ролевая модель на 70+ разрешениях. Go + pgx | Next.js + TS.

Github | Apache 2.0

Автор статьи грустно флексит бабками

Автор статьи грустно флексит бабками

Благодарю за чтение, хорошего дня.