> Почему нельзя было в момент сдачи платежки сразу прописывать текущий курс и передавать дальше (Go)

Уровень: middle · Роль: backend · Категория: Технические вопросы

Компании: Автомакон

Стек: Go

> Пример ответа

Короткий ответ

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

Подробное объяснение

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

  • при списании банк использует свой курс, который может отличаться;
  • при зачислении на счёт получателя курс может быть уже другим;
  • при возврате или частичном исполнении платёжки зафиксированный курс становится нерелевантным.

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

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

Четвёртый аспект - гибкость. Если курс фиксируется в момент сдачи, то нельзя пересчитать платёжку при изменении условий (например, при частичной оплате или изменении даты исполнения). Лучше хранить курс в отдельной таблице курсов с датой и валютой, а в платёжке ссылаться на дату операции.

На практике

В реальных системах (банковские API, платёжные шлюзы, ERP) используется подход:

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

Пример из практики: при интеграции с банком, банк возвращает в ответе на платёжку свой курс и сумму в рублях. Эти данные сохраняются в отдельном поле "фактический курс" уже после исполнения, а не на этапе создания.

Пример кода

GO
type Payment struct {
ID string
Amount decimal.Decimal // сумма в валюте
Currency string
CreatedAt time.Time
ExecutedAt *time.Time
Rate *decimal.Decimal // заполняется после исполнения
}
type RateService struct {
rates map[string]map[time.Time]decimal.Decimal // currency -> date -> rate
}
func (s *RateService) GetRate(currency string, date time.Time) (decimal.Decimal, error) {
// берём курс на дату, а не на момент создания
if rates, ok := s.rates[currency]; ok {
if rate, ok := rates[date.Truncate(24*time.Hour)]; ok {
return rate, nil
}
}
return decimal.Zero, fmt.Errorf("rate not found for %s on %s", currency, date)
}
func (s *RateService) ExecutePayment(p *Payment) error {
rate, err := s.GetRate(p.Currency, time.Now())
if err != nil {
return err
}
p.Rate = &rate
now := time.Now()
p.ExecutedAt = &now
return nil
}

Как отвечать на собеседовании

Начни с того, что курс - это динамическая величина, а платёж - это документ с жизненным циклом. Затем перечисли проблемы: расхождение курсов на разных этапах, проблемы с пересчётом, бухгалтерские требования, риск некорректных данных при изменении статуса платёжки. Подчеркни, что правильный подход - хранить валюту и сумму, а курс вычислять на дату операции или хранить в отдельном справочнике. Если спросят про "блокировку курса" - скажи, что это отдельный механизм, который используется в e-commerce и требует отдельной сущности с сроком действия.

Что проверяет интервьюер

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

Типичные ошибки

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

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью