nepster-web
@nepster-web

Как правильно организовать историю денежного оборота?

Есть некая интересная задачка, которую я уже на протяжении очень долгого времени не могу красиво порешать.
Это реализация структуры финансового учета в проекте.

Давайте представим, что нужно сделать раздел "История денежного оборота", где будет выводиться список движения финансов с более-менее подробной информацией, например вот так:

Пользователь Вася перевел $10 пользователю Пете 
Пользователь Вася вывел $100 через систему "Приват Банк"
Пользователь Петя перевел Вам $15
Активация в тарифный план "Старт" за $25
Оплата $15 за услугу "Смена логина"
Оплата $100 за услугу "Поднять объявление в топ". 
Квартира на сутки №1, Квартира на сутки №2, Квартира на сутки №3, Квартира на сутки №4


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

Теперь более детальный пример

К примеру есть следующие типы услуг:
- Поднять объявления в топ
- Сменить логин
- Купить подписку на "тарифный план"
- Оплатить заказ товара

Задача: зафиксировать идентификаторы сущностей, которые фигурируют в заказе и отобразить из.

Рассмотрим на примере "Поднять объявления в топ" и "Купить подписку на 'тарифный план'".
Наша задача записать где-то список id из таблицы объявлений и id из таблицы тарифных планов, чтобы получить необходимые данные для рендера.

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

Тоесть если у нас задача отобразить 100 записей, то на каждую запись будет по 1 запросу и это выходит более 100 запросов в бд для рендера страницы. Как-то не хорошо.

Собственно поделитесь пожалуйста советом по реализации...
  • Вопрос задан
  • 314 просмотров
Пригласить эксперта
Ответы на вопрос 3
taliban
@taliban
php программист
Mysql поддерживает if
Вы можете разделить всю историю на логические блоки:
кто сделал, что сделал, кому сделал, зачем сделал, сумма
и совать в разнобой айдишники пользователей или операций + добавить поле которое однозначно идентифицирует операцию
в итоге вы будете всегда выбирать 4 поля
перевод: от айди, 'перевел', к айди, '', 10 баксов
поднятие в топ: кто, "поднял в топ", '', '', 10 баксов
покупка подписки: кто, "купил подписку", "", "", 10 баксов
итд, заранее продумайте какие данные возможны в истории, сделайте поля на все случаи жизни (айдишники можно совмешать, пользователя и операции, потом по ифу выводить нужное

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

Можно обойтись без джойнов, выбрать все данные, отдельно взять из них айдишники нужные, и выбрать отдельно :) иногда это быстрей.
Ответ написан
@jus0807
Может я не правильно проблему понял, но разве нельзя просто сделать так:
Есть таблицы: Пользователи Таблицы Действия Лог
Таблица Лог: id user_id action_id target_id datetime comment
action_id связано с таблицей таблицы - в таблицах хранятся названия таблиц, которые логируются, в Действиях - названия действий для этих таблиц типа Оплатил заказ, поднял в топ, сменил логин и тп.
В итоге чтобы отрисовать 100 записей, достаточно сделать 1 запрос с 3 join или 4 отдельных запроса.
select * from log l
join users u on u.id = l.user_id
join actions a on a.id = l.action_id
join tables t on t.id = a.table_id

В коммент можно сохранить текстовое описание действия типа "Вася удалил запись" или же diff в качестве json или какие-то варианты на эту тему.
Ответ написан
MetaAbstract
@MetaAbstract
Архитектор информационных систем и баз данных. Ful
Создайте в базе отдельную таблицу для баланса в разрезе эккаунтов и в нее пишите начисления и оплаты и будет у Вас и баланс и история.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы