powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Реализация "кошельков" для разных сущностей
38 сообщений из 38, показаны все 2 страниц
Реализация "кошельков" для разных сущностей
    #39856930
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день Уважаемые!

Скажите пожалуйста, как лучше оформить личные счета например для "Пользователей" и для "Групп Пользователей".
Пример исключительно теоретический, просто для иллюстрации. Различных (принципиально) сущностей может быть больше 2-х.

Я пока остановился на таком варианте:
В коде приложения прописаны константы с типами сущностей. Навроде:
Код: sql
1.
2.
define("TYPE_USER"     , 1);
define("TYPE_GROUP"    , 2)



и счета для сущностей описать так:
Код: sql
1.
2.
3.
4.
5.
6.
TABLE Accounts (
    id           SERIAL,
    entityType   TINYINT UNSIGNED NOT NULL,
    entityID     BIGINT UNSIGNED NOT NULL,
    accData      .....
)


И в дальнейшем движения средств уже описывать двойной записью с указанием данных счетов.

Скажите пожалуйста, стоит так формировать или для каждой сущности свою таблицу со счетами надо делать?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39856943
ldfanate
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
учитывая, что финвопросы бывает вызывают ожесточённые споры (претензионно-исковую работу, включая суды), наверное имеет смысл добавлять везде избыточность. Чтобы не получилось потом, что из за кривого 1 бита деньги Иванова легли в кошелёк Петрова.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39856951
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин... Аппаратные проблемы это вроде чуть другое. Их ECC'ом надо решать.
Тут всё-же вопрос в корректности решения.
Да и от сменившегося бита это никак не спасёт.
Если в начале транзакции распределения средств будет тот самый некорректный бит в идентификаторе приёмника или источника - результат в любом случае будет неверным.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39856994
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Разовью тему дальше. Ещё в системе соответственно есть
- платежи от пользователей (через разные системы: карты, WM, ЯД и т.п.)
- платежи "счетами" внутри системы, т.е. от такого-то пользователя такому-то, от такого пользователя на баланс такой-то группы и т.п.

И если вопрос по внутренним счетам (пользователей, групп и др.) уже сформулирован выше с просьбой оценить выбранный способ, то взносы извне хочу тожу спросить совета как оформлять.
Пришёл на ум такой вид:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
//Описание внешних счетов
Account_Ext (
    id        SERIAL,
    accType   TINYINT UNSIGNED NOT NULL, /*константа тип: ЯД, WM, SMS и т.д.*/
    accKey    CHAR(64) UNIQUE, /* идентификатор счёта, т.е. номер кошелька в ЯД или номер телефона в SMS */
    accData1 ...
    accData2 ...
    .....
)

/* Таблица транзакций */
Pay_Transactions (
    id       SERIAL,
    .........
)

/* Собственно учёт внешних движений средств */
Ext_Pays (
     id         SERIAL,
     PT_ID      BIGINT UNSIGNED, /* Транзакция */
     extAcc_ID  BIGINT UNSIGNED NOT NULL, /* Внешний счёт */
     intAcc_ID  BIGINT UNSIGNED NOT NULL, /* Внутренний счёт */
     extAmount  DECIMAL(...), /* Объём транзакции на внешнем счёте. + или - */
     intAmount  DECIMAL(...), /* ....... на внутреннем */ 
)

/* Учёт внутренних передвижений средств */
Ext_Pays (
     id         SERIAL,
     PT_ID      BIGINT UNSIGNED, /* Транзакция */
     intAcc1_ID BIGINT UNSIGNED NOT NULL, /* 1 счёт */
     intAcc2_ID BIGINT UNSIGNED NOT NULL, /* 2 счёт */
     acc1Amount DECIMAL(...), /* Объём транзакции на1 счёте. + или - */
     acc2Amount DECIMAL(...), /* ....... на 2-м */ 
)



Скажите, стоит ли так делать?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857002
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зачем физически делить внешние и внутренние ? Разве они принципиально отличаются ?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857066
mad_nazgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormot,

ИМХО не надо "усложнять" без необходимости.
У вас есть сущность счет с четко заданными операциями - "приход/расход/прсмотр".
А сверху можно "накручивать" доступ к операциям над счетом для пользователя или группы пользователей.
Кто имеет право смотреть/начислять/снимать деньги (производить соответствующие операции)
Т.е. мухи (счета) отдельно, котлеты (права пользователей) отдельно.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857144
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L_argoЗачем физически делить внешние и внутренние ? Разве они принципиально отличаются ?
Ну как... условно потому что внешние они общий баланс системы меняют, а внутренние нет - только перераспределяют внутри. Вроде принципиально разные как я вижу типы счетов. А как иначе? Т.е. прямо стоит все счета в одной таблице хранить и просто типом их подразделять?


mad_nazgulИМХО не надо "усложнять" без необходимости.
У вас есть сущность счет с четко заданными операциями - "приход/расход/прсмотр".
А сверху можно "накручивать" доступ к операциям над счетом для пользователя или группы пользователей.
Кто имеет право смотреть/начислять/снимать деньги (производить соответствующие операции)
Т.е. мухи (счета) отдельно, котлеты (права пользователей) отдельно.
Не очень понял. Тут права не имеют особого значения, эти счета чисто для учёта баланса, нет такого что один пользователь может/не может смотреть чей-то счёт. Он может пополнить свой счёт и оплатить что-то, счета только для таких операций нужны.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857171
mad_nazgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotНе очень понял. Тут права не имеют особого значения, эти счета чисто для учёта баланса, нет такого что один пользователь может/не может смотреть чей-то счёт. Он может пополнить свой счёт и оплатить что-то, счета только для таких операций нужны.

Как раз имеют.
На счет могут деньги придти, с него могут деньги списаться, и можно посмотреть текущее состояние счета. Все.

Вам же нужно разграничить доступ к счету.
Т.е. кто имеет право на ту или иную операцию.
Один клиент или группа клиентов.

Например личные счета, это те счета, на просмотр и снятие с которых имеет право только один клиент.
Групповые счета, это те счета, на просмотр и снятие которых имеет право группа клиентов.

Можно еще упростить. На операции со счетами имеет право всегда группа клиентов.
Но для личных счетов группа будет состоять из одного клиента. :-)
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857172
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Т.е. прямо стоит все счета в одной таблице хранить и просто типом их подразделять?Именно так.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857186
Serguei
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotНу как... условно потому что внешние они общий баланс системы меняют, а внутренние нет - только перераспределяют внутри. Вроде принципиально разные как я вижу типы счетов. А как иначе? Т.е. прямо стоит все счета в одной таблице хранить и просто типом их подразделять?

Думаю надо похожей задачей и решил не делить на разные таблицы- это сильно усложняет.
Все в одной таблице тип счета прописан в самом счете должен быть прописан, так что и без типа понятно что это.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857224
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Товарищи, оцените пожалуйста итоговую схему:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
		case 'tab.pay_account.create':		//Таблица со счетами в системе
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_account` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	accType		TINYINT UNSIGNED NOT NULL, '.
					'	accObjID	BIGINT UNSIGNED NOT NULL, '.
					'	UNIQUE KEY	accKey (accType, accObjID) '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Счета в системе"';
			break;

		case 'tab.pay_accountState.create':	//Состояние счетов
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_accountState` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	payAccID	BIGINT UNSIGNED NOT NULL, '.
					'	currID		SMALLINT UNSIGNED NOT NULL, '.
					'	accAmount	DECIMAL(30,20), '.
					'	UNIQUE KEY	accCurr (payAccID, currID), '.
					' FOREIGN KEY	payAccID REFERENCES pay_account(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	currID REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Состояние счетов в системе в разных валютах"';
			break;

		case 'tab.pay_actions.create':		//Таблица с записью движений средств между счетами
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_accountActions` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	actType		TINYINT UNSIGNED NOT NULL, '.
					'	payAcc1_ID	BIGINT UNSIGNED NOT NULL, '.
					'	curr1_ID	SMALLINT UNSIGNED NOT NULL, '.
					'	pay1_Amount	DECIMAL(30,20) NOT NULL, '.
					'	payAcc2_ID	BIGINT UNSIGNED NOT NULL, '.
					'	curr2_ID	SMALLINT UNSIGNED NOT NULL, '.
					'	pay2_Amount	DECIMAL(30,20) NOT NULL, '.
					' FOREIGN KEY	payAcc1_ID REFERENCES pay_account(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	curr1_ID REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	payAcc2_ID REFERENCES pay_account(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	curr2_ID REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Движения на счетах в разных валютах"';
			break;
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857242
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Транзакции забыл, ну без них оцените пожалуйста, как будто они есть :)
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857307
Serguei
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotТоварищи, оцените пожалуйста итоговую схему:


Разве у счета не должна быть строго одна валюта?
Помоему в банках для каждой валюты отдельный счет открывают.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857488
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SergueiРазве у счета не должна быть строго одна валюта?
Помоему в банках для каждой валюты отдельный счет открывают.
Так у меня не счёт в банковском понимании, а кошелёк скорее. Могут приходить разные валюты и в этих валютах должна быть своя сумма.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857489
Serguei
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotТак у меня не счёт в банковском понимании, а кошелёк скорее. Могут приходить разные валюты и в этих валютах должна быть своя сумма.
Какая разница? Есть одна учетная запись в кошельке, а есть счет для каждой валюты отдельно. Ведь учет каждой валюты идет отдельно.
Не уверен на 100%, но думаю что в этом есть логика. .
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857496
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SergueiКакая разница? Есть одна учетная запись в кошельке, а есть счет для каждой валюты отдельно. Ведь учет каждой валюты идет отдельно.
Не уверен на 100%, но думаю что в этом есть логика. .
Ну вот вроде если прикинуть, то в оформлении всяческих запросов для работы со всем этим хозяйством, просто будет на одну таблицу связующую больше, без каких-либо дополнительных выгод.

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

Но в предложенной выше схеме (один кошелёк мультивалютный) всё вполне реализуется записью в таблице pay_actions с указанием одинакового №счёта 1 и 2 и разных валют. Только вот двойная запись плохо будет некорректной, ведь там дебет и кредит должны сходиться, а мы условно доллары с рублями сравниваем.
Но это можно тогда реализовать в две операции, через кошелёк системы. Т.е.
1. операция снимаем валюту1 со счёта объекта на счёт-обменник системы.
2. операция вносим валюту2 со счёта-обменника системы на счёт объекта.

Но в целом, зерно сомнения закралось насчёт отдельных счетов. Но всё-же в случае отдельных счетов для каждой валюты, ведь операция "конвертации" будет реализована ровно также.
1. Со счёта валюты №1 перенести на какой-то системный счёт в такой-же валюте
2. С какого-то системного счёта в валюте 2 перенести средства на счёт объекта.

Короче не вижу выгод и принципиальной разницы.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857517
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемые, привёл к такому виду пока, скажите пожалуйста свои соображения.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
		case 'tab.pay_transaction.create':	//Транзакции в системе
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_transaction` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	tDescr		CHAR(255) '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Транзакции в системе"';
			break;

		case 'tab.pay_account.create':		//Таблица со счетами в системе
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_account` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	accType		TINYINT UNSIGNED NOT NULL, '.
					'	accObjID	BIGINT UNSIGNED NOT NULL, '.
					'	UNIQUE KEY	accKey (accType, accObjID) '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Счета в системе"';
			break;

		case 'tab.pay_accountState.create':	//Состояние счетов
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_accountState` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	payAccID	BIGINT UNSIGNED NOT NULL, '.
					'	currID		SMALLINT UNSIGNED NOT NULL, '.
					'	accAmount	DECIMAL(30,20), '.
					'	UNIQUE KEY	accCurr (payAccID, currID), '.
					' FOREIGN KEY	payAccID REFERENCES pay_account(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	currID REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Состояние счетов в системе в разных валютах"';
			break;

		case 'tab.pay_actions.create':		//Таблица с записью движений средств между счетами
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_accountActions` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	PT_ID		BIGINT UNSIGNED NOT NULL, '.
					'	actType		TINYINT UNSIGNED NOT NULL, '.
					'	currID		SMALLINT UNSIGNED NOT NULL, '.
					'	debetAccID	BIGINT UNSIGNED NOT NULL, '.
					'	debetAmount	DECIMAL(30,20) NOT NULL, '.
					'	creditAccID	BIGINT UNSIGNED NOT NULL, '.
					'	creditAmount DECIMAL(30,20) NOT NULL, '.
					' FOREIGN KEY	PT_ID REFERENCES pay_transaction(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	currID REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	debetAccID REFERENCES pay_account(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	creditAccID REFERENCES pay_account(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Движения на счетах."';
			break;
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857573
Serguei
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotУважаемые, привёл к такому виду пока, скажите пожалуйста свои соображения.

pay_transaction - по-моему это не транзакции у вас(кстати что вы имели ввиду? :) ), а просто комментарий к операции в pay_actions. С таким же успехом можно tDescr в pay_actions перенести.

pay_accountState на мой взгляд смысла нет. Читаешь последнюю запись в pay_accountActions - вот и состояние счета.
Я бы сделал поля в pay_accountActions:
сумма дебета
сумма кредита
сумма транзакции
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857728
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SergueikormotТак у меня не счёт в банковском понимании, а кошелёк скорее. Могут приходить разные валюты и в этих валютах должна быть своя сумма.
Какая разница? Есть одна учетная запись в кошельке, а есть счет для каждой валюты отдельно. Ведь учет каждой валюты идет отдельно.
Не уверен на 100%, но думаю что в этом есть логика. .
Ну естественно разница есть. Кошелёк и банковский счёт вещи совершенно разные. Не стоит упоминать их в одном предложении. Учёт в кошельке ведётся по наименованию валюты, а не по какому-то счёту.
Достаньте из кармана свой кошелёк, откройте его, и поймите какая причина физически мешает положить туда и долларовые бумажки и рубли. И что мешает Вам сказать, что в кошельке у Вас например, "20 рублей, 30 долларов и 50 евро"?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857768
ViPRos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.FontaineSergueiпропущено...

Какая разница? Есть одна учетная запись в кошельке, а есть счет для каждой валюты отдельно. Ведь учет каждой валюты идет отдельно.
Не уверен на 100%, но думаю что в этом есть логика. .
Ну естественно разница есть. Кошелёк и банковский счёт вещи совершенно разные. Не стоит упоминать их в одном предложении. Учёт в кошельке ведётся по наименованию валюты, а не по какому-то счёту.
Достаньте из кармана свой кошелёк, откройте его, и поймите какая причина физически мешает положить туда и долларовые бумажки и рубли. И что мешает Вам сказать, что в кошельке у Вас например, "20 рублей, 30 долларов и 50 евро"?
Никто.
4000$,
15000р,
1000ман
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857771
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergueipay_transaction - по-моему это не транзакции у вас(кстати что вы имели ввиду? :) ), а просто комментарий к операции в pay_actions. С таким же успехом можно tDescr в pay_actions перенести.
Тут транзакции это не те который COMMIT ROLLBACK :)
Это объединение нескольких действий в одной транзакции. Т.е. например пользователь хочет со своей карты внести денег за товар.
Это в моих транзакциях, в рамках одного PT_ID будут несколько действий:
1. Внесение денег с карты на счёт такого то пользователя
2. Оплата со счёта такого-то пользователя за то-то и то-то.


Mr.FontaineНу естественно разница есть. Кошелёк и банковский счёт вещи совершенно разные. Не стоит упоминать их в одном предложении. Учёт в кошельке ведётся по наименованию валюты, а не по какому-то счёту.
Достаньте из кармана свой кошелёк, откройте его, и поймите какая причина физически мешает положить туда и долларовые бумажки и рубли. И что мешает Вам сказать, что в кошельке у Вас например, "20 рублей, 30 долларов и 50 евро"?
ViPRosНикто.
4000$,
15000р,
1000ман
Товарищи, я только не понял, в итоге как правильно делать? Внешние счета (с которых непосредственно средства извне приходят) - отдельно, а внутрисистемные счета пользователей и других объектов - отдельно?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857789
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergueipay_accountState на мой взгляд смысла нет. Читаешь последнюю запись в pay_accountActions - вот и состояние счета.
Я бы сделал поля в pay_accountActions:
сумма дебета
сумма кредита
сумма транзакции
Ну нет, в pay_accountActions там же лог действий, из которых состояние счёта в любой момент можно получить, но это же надо SUM по всей истории херачить. А так триггерами или ещё как при каждой записи в Actions пересчёт соответствующего счёта.

А по поводу полей в Actions, я так в итоге и сделал (debetAmount, creditAmount), сумма действия же всегда равна нулю в двойной записи? Т.е. дебит с кредитом по величине одинаковы, но разные знаки.

Сумма транзакции, ну да, наверное можно в pay_transaction его добавить. Только имеет ли это поле смысл, кроме как информационное? Ведь если в "транзакции" несколько действий, т.е. например взнос один, а распределяется он например по несколким путям (в группу, процент ещё куда-то и т.п.)
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857799
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormot, так-то я у Сергея спрашивал про кошелёк
Ну, а по табличкам, то более-менее нормально. Не все поля таблиц понятны из их названий, ну да ладно, главное: есть кошельки и движение средств в одной табличке.
Кстати, неплохо было бы переименовать табличку кошельков. "Состояние счёта" как-то не в то русло направляет мысли. Ты сам писал, что это у тебя кошельки, а не счета. Вот и назови её pay_moneyBags.
Тогда проще будет воспринимать, что запрос на состояние счёта может выдать несколько строк (по каждой валюте отдельно), а то из термина "Состояние счёта" совсем не вытекает возможность наличия нескольких строк в выборке.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857811
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontaine,
Ок, приму к сведению и термины сменю.
А всё же надо разделять на уровне таблиц внешние счета и внутренние "кошельки"?

Внешние счета, это например пользователь пополняет свой кошелёк через SMS,
и соответственно агрегатор отправляет мне подтверждение операции. И значит идентификатор этого "внешнего счёта" - это тип (TYPE_SMS_AGGREGATOR1) и уникальный ключ этого "внешнего счёта" - номер телефона.

Тогда будут таблицы "pay_account" => "Кошелёк" и добавится "ext_account" (extTypeID - тип внешнего сервиса, extKey - уникальный ключ счёта в этом внешнем сервисе)
и действия будут разделены на две таблицы ext_actions (id, currID, extAccID, intBagID, extPayAmount, intPayAmount) и текущая "pay_actions" => "bag_actions"

?
А то выше вроде посоветовали в одной таблице хранить и внутренние кошельки и внешние счета, разделяя их типами. В принципе это реализуемо, но вроде смешение довольно разных по смыслу элементов в одной таблице?

А наличие отдельно внешних сервисов как раз принципиально не усложнит все внутрисистемные связанные с движением средств запросы, т.к. требуются лишь в моменты работы с внешними счетами (ввод-вывод средств из системы)
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857833
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormot, чисто теоритически (мне кажется в этом ключе у нас идёт разговор?) конечно надо. Это разные сущности.
Но честно сказать я сомневаюсь, что тебе нужны внешние счета. Мне кажется достаточно знать откуда пришли деньги - по СМС или из Яндекса. У тебя есть сумма денег, есть внутренний аккаунт, куда надо перечислить их. Что даёт тебе номер телефона или последние четыре цифры карты?

Есть сайты, где это дело учитывают, но там движение денег идёт в ручном режиме: пользователь перечислил деньги на счёт Яндекс.Деньги, а уже потом по данным с какого номера деньги пришли, администратор сайта пополняет внутренний кошелёк указанного в примечаниях к платежу аккаунта.

Честно говоря, я не специалист в электронной коммерции и могу запросто ошибаться, да и то что у тебя указано в таблице Account_Ext мне вообще малопонятно....
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857842
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontaine,

Ну разговор не совсем теоретический. Я в данный момент формирую как будет эта вся коммерция и работа с учётом средств в БД сделана. И вот чтобы сразу сделать так, как оно должно быть или максимально близко к этому я тут все вопросы и спрашиваю.

Если без внешних счетов, то где в БД хранить информацию о поступлении средств в такой-то кошелёк?
Сейчас то, что я выше выкладывал, учёт средств идёт в таблице pay_actions (id, currID, debetBagID, creditBagID, debetSum, creditSumm) - т.е. кошелёк кредит, кошелёк дебит, валюта в которой действие происходит и двойная запись величины действия величина дебита и величина кредита.

А как с такой таблицей учёта движений средств указать поступление средств извне? Отдельная получается должна быть таблица pay_extActions (id, currID, bagID, extPayType, extPayData, paySum) - т.е. валюта внешней транзакции, с каким кошельком эта транзакция и собственно описание внешнего плавтежа. Я с введением внешних счетов просто получается дополнительно нормализовал эту таблицу, но если объективно это не требуется, то конечно обойдусь таким вариантом.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857865
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormot,
авторА как с такой таблицей учёта движений средств указать поступление средств извне?
да собственно так же как и в первой таблице, ибо хранить движения денег лучше в одной таблице.
только два поля кредита оставляй пустыми, ибо "извне".
Если есть необходимость хранить данные источника денег, то вот для этого и можно использовать вторую табличку убрав из твоего варианта лишние поля
pay_extActions (id, extPayType, extPayData)
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857868
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontaine,

А если хранить детали внешнего платежа, то его же в любом случае надо линковать с движением средств. Т.е. в таблице pay_extPays надо ещё добавить payActID -> FK pay_actions(id)

А то что в двойной записи должен быть всегда в ноль баланс а мы тут половину отрежем - не будет принципиальной проблемой?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857883
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotMr.Fontaine,

А если хранить детали внешнего платежа, то его же в любом случае надо линковать с движением средств. Т.е. в таблице pay_extPays надо ещё добавить payActID -> FK pay_actions(id)
Ну всё правильно.
Для этого я предполагал использовать существующее поле id. Ну конечно правильнее его назвать payActID. Но куда записывать идентификатор действия в общем-то не принципиально, ибо при структуре таблицы
pay_extActions (id, payActID, extPayType, extPayData)
вряд ли Вы будете использовать поле id вне контекста pay_actions

kormotА то что в двойной записи должен быть всегда в ноль баланс а мы тут половину отрежем - не будет принципиальной проблемой?Будет это приниципиальной проблемой или не будет зависит от ответов на вопросы: Нужно ли тебе знать, что где-то "вовне" деньги уменьшились? Зачем тебе нужен "ноль" в балансе?
Да и ты хорошо бы ответить на мой вопрос
Mr.Fontaine Что даёт тебе номер телефона или последние четыре цифры карты?
Может после этого тебе станет более понятно какие таблицы тебе нужны.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857907
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontaine pay_extActions (id, payActID, extPayType, extPayData)
вряд ли Вы будете использовать поле id вне контекста pay_actions
Точно... у меня просто ID головного мозга :) Во всех таблицах должен быть ID, а тут же точно можно такой-же как в таблице действий первичный ключ использовать. Всё, понял.

Mr.FontaineБудет это приниципиальной проблемой или не будет зависит от ответов на вопросы: Нужно ли тебе знать, что где-то "вовне" деньги уменьшились? Зачем тебе нужен "ноль" в балансе?
Да и ты хорошо бы ответить на мой вопрос
Нет, уменьшение денег вовне мне неинтересно. Но например может теолретически быть полезной информация сколько и откуда денег поступило. Но это уже другой вопрос, к балансу не относящийся.
Ноль в балансе - это меня когда отправили понимать что такое "двойная запись" которая является стандартом для учёта средств, я и взял от туда поступат, что должно быть так и всё. Сумма должна быть равна нулю.

А для чего мне информация о источнике (т.е. номер телефона и идентификатор в платёжной системе и т.п.) - ну так для возможной привязки "внешнего счёта" к тому или иному "субъекту" в системе. Из карт не 4 последние цифры, а там какой-то есть же уникальный идентификатор данной карты в банке и при платеже там вроде передаётся эта информация.
Зачем нужно мне это в итоге, ну всё же это информация о средствах, причём информация о внешних платежах - именно о средствах реальных а не внутрисистемных, и у меня стойкое ощущение что каждый уникальных источник средств для системы должен быть оформлен сущностью.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857914
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotнапример может теолретически быть полезной информация сколько и откуда денег поступило. Как раз для этого мы и создаём табличку pay_extActions (id, payActID, extPayType, extPayData) . Думаю, что при необходимости из extPayData можно получить откуда, а из payActions джойном можно получить сколько.
kormotА для чего мне информация о источнике (т.е. номер телефона и идентификатор в платёжной системе и т.п.) - ну так для возможной привязки "внешнего счёта" к тому или иному "субъекту" в системе. Из карт не 4 последние цифры, а там какой-то есть же уникальный идентификатор данной карты в банке и при платеже там вроде передаётся эта информация.
Зачем нужно мне это в итоге, ну всё же это информация о средствах, причём информация о внешних платежах - именно о средствах реальных а не внутрисистемных, и у меня стойкое ощущение что каждый уникальных источник средств для системы должен быть оформлен сущностью.
А вот это веский аргумент для того, чтобы создать табличку с внешними счетами. и тогда в pay_extActions не будет пустых полей и будет красивый ноль в балансе.
Только может быть в pay_actions ещё поле ввести с типом кредита (внешний или внутренний)?
Да и для дебета тогда можно поле типа ввести. А то мало ли что потребуется....
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857923
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.FontaineА вот это веский аргумент для того, чтобы создать табличку с внешними счетами. и тогда в pay_extActions не будет пустых полей и будет красивый ноль в балансе.
Только может быть в pay_actions ещё поле ввести с типом кредита (внешний или внутренний)?
Да и для дебета тогда можно поле типа ввести. А то мало ли что потребуется....
Т.е. поток движений средств имеет смысл разделять на внутренние и внешние?
А про поле с типом внешний и внутренний у pay_Actions я не понял. Ведь если есть pay_extActions - в которой (currID, extAccID, bagID, extPayAmount, bagPayAmount) зачем указание на внешний или внутренний в pay_actions?

Да и к тому же если типы "внешний счёт" или "кошелёк" будут определяться значением поля в таблице - то это же сразу будет проблемой при выборке. Надо джойнить с обеими таблицами ext_accounts и pay_bags и IF'ом выбирать или в самом приложении брать то или иное поле. Нужно ли тут это EAV?
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857933
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormot,
Я говорю про такую структуру (выдеру таблицы из твоих сообщений, потому формат разный)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
 table pay_actions (id, currID, debetBagID, creditBagID, debetSum, creditSumm) 

TABLE Accounts (
    id           SERIAL,
    entityType   TINYINT UNSIGNED NOT NULL,
    entityID     BIGINT UNSIGNED NOT NULL,
    accData      .....
)

//Описание внешних счетов
Account_Ext (
    id        SERIAL,
    accType   TINYINT UNSIGNED NOT NULL, /*константа тип: ЯД, WM, SMS и т.д.*/
    accKey    CHAR(64) UNIQUE, /* идентификатор счёта, т.е. номер кошелька в ЯД или номер телефона в SMS */
    accData1 ...
    accData2 ...
    .....
)


вот тут-то и можно в таблицу pay_actions добавить тип аккаунта
pay_actions (id, currID, debetBagID, debetBagType, creditBagID, creditBagType, debetSum, creditSumm)
а таблица pay_extActions (id, currID, bagID, extPayType, extPayData, paySum) в этом случае вообще не нужна.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857935
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя таблицу Accounts лучше показать по последнему варианту:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
'CREATE TABLE IF NOT EXISTS `pay_account` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	accType		TINYINT UNSIGNED NOT NULL, '.
					'	accObjID	BIGINT UNSIGNED NOT NULL, '.
					'	UNIQUE KEY	accKey (accType, accObjID) '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Счета в системе"
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857942
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontaine,

Ну да, я так и понял, но ведь тут ссылка на родителя (счёт) получается в зависимости от accType - это стоит того? Как тогда например выбирать информацию о всех поступлениях в данный кошелёк, с информацией о счетах участвующих в операции?
Код: sql
1.
2.
3.
4.
select aa..... , bb.... , cc....
FROM pay_actions    aa 
LEFT JOIN Accounts bb ON ... /* Как мы должны понять, что aa.debetBagID - это именно bagID а не extID?*/
LEFT JOIN Account_Ext cc ON .../* Как мы должны понять, что aa.creditBagID - это именно bagID а не extID?*/


Как-то очень недетерминировано выглядит это.

А в случае наличия двух таблиц ext_actions и bag_actions , там UNION ALL'ом всё однозначно получается.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857950
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormot, ну согласен. недетерминированно.
Твой вариант с разными таблицами внутренних и внешних перемещений лучше.
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857959
kormot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontaine спасибо за помощь!
В итоге сформировалась благодаря этому обсуждению такая схема:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
		case 'tab.pay_transaction.create':	//Транзакции в системе
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_transaction` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	tDescr		CHAR(255) '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Транзакции в системе"';
			break;

		case 'tab.pay_bags.create':		//Таблица с кошельками в системе
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_bags` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	bagType		TINYINT UNSIGNED NOT NULL, '.
					'	ObjID		BIGINT UNSIGNED NOT NULL, '.
					'	UNIQUE KEY	bagKey (bagType, ObjID) '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Кошельки разных объектов в системе"';
			break;

		case 'tab.pay_moneyBags.create':	//Состояние кошельков
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_moneyBags` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	bagID		BIGINT UNSIGNED NOT NULL, '.
					'	currID		SMALLINT UNSIGNED NOT NULL, '.
					'	currMoney	DECIMAL(30,20), '.
					'	UNIQUE KEY	bagCurr (bagID, currID), '.
					' FOREIGN KEY	(bagID) REFERENCES pay_bags(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(currID) REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Состояние кошельков в системе в разных валютах"';
			break;

		case 'tab.pay_bagActions.create':		//Таблица с записью движений средств между кошельками
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_bagActions` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	PT_ID		BIGINT UNSIGNED NOT NULL, '.
					'	actType		TINYINT UNSIGNED NOT NULL, '.
					'	currID		SMALLINT UNSIGNED NOT NULL, '.
					'	debBagID	BIGINT UNSIGNED, '.
					'	debAmount	DECIMAL(30,20) NOT NULL, '.
					'	credBagID	BIGINT UNSIGNED, '.
					'	credAmount DECIMAL(30,20) NOT NULL, '.
					' FOREIGN KEY	(PT_ID) REFERENCES pay_transaction(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(currID) REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(debetBagID) REFERENCES pay_bags(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(creditBagID) REFERENCES pay_bags(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Движения на счетах."';
			break;

		case 'tab.pay_extAccounts.create':		//Таблица с внешними счетами
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_extAccounts` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	extType		SMALLINT UNSIGNED NOT NULL, '.	/* Тип внешнего счёта. Определённая константа указывающая на внешний сервис */
					'	extKey		CHAR(64) NOT NULL, '.			/* Уникальный ключ счёта во внешнем сервисе */
					' UNIQUE KEY	extAcc (extType, extKey) '.	/* Уникальность счёта в сервисе */
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Счета участвовавшие во внешних денежных транзакциях системы"';
			break;

		case 'tab.pay_extActions.create':		//Таблица с движениями средств в\из системы
			$sql	= 'CREATE TABLE IF NOT EXISTS `pay_extActions` ('.
					'	id		BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, '.
					'	cDate		DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(), '.
					'	sessID		BIGINT UNSIGNED NOT NULL, '.
					'	PT_ID		BIGINT UNSIGNED NOT NULL, '.
					'	currID		SMALLINT UNSIGNED NOT NULL, '.	/* TODO: Хотя наверное у счёта внешнего сервиса одна валюта. В будущем будет понятно */
					'	extAccID	BIGINT UNSIGNED NOT NULL, '.	/* Ссылка на внешний счёт */
					'	extAmount	DECIMAL(30,20) NOT NULL, '.		/* Величина движения средств на внешнем счёте */
					'	bagID		BIGINT UNSIGNED NOT NULL, '.	/* Ссылка на кошелёк */
					'	bagAmount	DECIMAL(30,20) NOT NULL, '.		/* Величина движения средств на кошельке */
					' FOREIGN KEY	(PT_ID) REFERENCES pay_transaction(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(currID) REFERENCES sys_currInfo(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(extAccID) REFERENCES pay_extAccounts(id) ON DELETE RESTRICT ON UPDATE RESTRICT, '.
					' FOREIGN KEY	(bagID) REFERENCES pay_bags(id) ON DELETE RESTRICT ON UPDATE RESTRICT '.
					') ENGINE=InnoDB CHARSET="utf8" COMMENT="Движения средств В/ИЗ системы"';
			break;



Если есть предложения и замечания, буду благодарен!
...
Рейтинг: 0 / 0
Реализация "кошельков" для разных сущностей
    #39857994
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kormotСкажите пожалуйста, как лучше оформить личные счета ...
Пример исключительно теоретический
Как угодно, рабочий вариант будет только в том случае когда есть конкретная постановка задачи, нет постановки задачи, придумайте сами процессы для которых создаете информационное сопровождение, из них и выделяйте необходимые сущности и атрибуты, универсального решения на все случаи жизни не существует.
...
Рейтинг: 0 / 0
38 сообщений из 38, показаны все 2 страниц
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Реализация "кошельков" для разных сущностей
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]