Какую архитектуру использовать для профиля пользователя, который нельзя изменить без модерации?
У пользователя есть профиль. Телефон/email/адрес, да, неважно, что
Нужно, чтобы пользователь не мог изменить свой профиль без премодерации. То есть, если пользователь прописывает
новые данные, то они уходят админам на проверку, а активными остаются ранее апрувнутые данные. Если админы отклоняют изменения, то в профиле остаются данные, которые были апрувнуты ранее.
Я виду несколько вариантов реализации "временного" и "апрувнутого" профилей
1. Полностью отдельные модели, как Profile и PendingProfile. Из минусов - нужно следить за консистентностью полей и добавлять/удалять поля в двух таблицах/моделях одновременно.
2. Одна модель с признаком, апрувнутый это профиль, или временный.
3. Модель профиля с JSON полем временных данных. Имхо, колхоз
4. Модель профиля с полем "родительского профиля". Если есть родитель, значит это временный профиль. Это частный случай второго варианта. Как плюс - можно во временном профиле заполнить только те поля, которые пользователь хочет изменить, а неизмененные подтягивать с апрувнутого профиля
Какой подход принято использовать для реализации данной логики?
Еще стоит прояснить следующие вещи:
1. При повторном запросе изменения профиля пользователем - что делать с предыдущим изменением, если администратор не успел его проверить? (как вариант оставлять последний, оставлять все - на выбор администратору);
2. Сам пользователь может запросить отмену отправленных изменений? Он вообще видит, что его профиль будет подвергнут изменению? (флажок какой, надпись в личном кабинете и пр.)
Как вариант можно разделить профиль на что-то типа profile + info, где info будет представлять собой подтверждаемые данные. Тогда будет так: Profiles(Id, InfoId, ...) и Info (Id, ProfileId, email, fio, ..., isActual (1 - у актуальной информации, 0 - у не очень)).
Администратор при входе в админку будет строить запрос по пользователям у которых есть два и более объекта Info и как-то обрабатывать их. При подтверждении одного из Info мы подменяем InfoId у профиля на нужный, ставим признак isActual. Остальные же Info по этому профилю либо удаляем, либо помечаем как отработанные или удаленные.
Пользователь же будет подтягивать информацию по своему InfoId, но и получит возможность знать, что там по его аккаунту творится у администратора (например, кол-во ожидающих изменений можно посмотреть или еще что).
Ещё вопрос: стоит ли заставлять модераторов проверять-аппрувить каждый раз целиком все поля профиля, или только diff изменений? Если нет, то варианты 2, 4 отваливаются, либо писать механизм сравнения, чтобы показать на проверку только изменившиеся поля.
Да, нормальный вариант с JSON - вы можете хранить там (или если получится вообще в отдельной таблице) список изменённых полей со значениями, ожидающих подтверждения, и при подтверждении записывать их в профиль и удалять из хранилища. Это очень гибкий вариант.
V Sh., эти вопросы вообще не вопросы)) Конечно только последний, зачем админу видеть историю правок запроса? Наблюдать, как Пндркй плавно превращался в Андрей, или войну с пальцами за попадание в нужную цифровую клавишу?) Что касается п. 2 - возможность запросить отмену бессмысленна: если изменения внесены, то "по ТЗ" предыдущее состояние никто не помнит, нужно что-то поменять - отправляется новый запрос на изменение. А видит пользователь или нет... По условию сам пользователь запрос и отправляет)
Алексей Березников, С JSON - самый простой, самый гибкий - с двумя моделями, там можно легким движением руки добавлять или выпиливать кучи фич разной степени нужности.
Владимир, ну да, с двумя моделями, если нужно только одно поле поменять - то либо для отображения изменённых полей придётся все поля сравнивать каждый раз, либо все поля делать nullable, либо хранить дополнительный флаг "изменено/нет" - все это костыли разной степени костыльности. Опять же с историей не получится, то что она вам лично не нужна - не значит, что никому не нужно. Самый гибкий вариант это иметь отдельную таблицу для изменений, в таком случае можно сделать что угодно, JSON конечно попроще и деревяннее маленько.
Алексей Березников, Ничего подобного не нужно, эти две модели могут быть абсолютно одинаковы. Если изменения одобряются, то просто нужные данные из PendingProfile обновляют запись целиком в таблице Profile и удаляются в PendingProfile. Если нужна история, то максимум, что будет отличать PendingProfile от Profile - это флаг ожидания модерации. Но можно даже без него обойтись)
Алексей Березников, А тут и спорить не о чем) Поля в случае варианта с двумя моделями сравнивать просто бессмысленно: если что-то в запросе не устраивает модератора, то запрос отклоняется, изменений вообще нет, если устраивает - все кучей обновляется и все - поля везде одинаковы, меняется только содержимое, а выяснять что именно поменялось - тратить время на лишний код для получение бесполезных данных.
Это может быть нужно только для анализа истории изменений, но тогда мы просто берем все записи из PendingProfile + запись Profile и непринужденно получаем искомое. Кстати, случае необходимости ведения истории изменений использовать JSON нельзя, т.к. приведет к лавинообразному нарастанию трудностей на ровном месте, тут подходит только вариант с двумя моделями.
Владимир, Ага, и для каждой модели сравниваем все поля чтобы увидеть что же именно изменилось :) Я же говорю спорить не о чем, это как JPEG vs PNG. JSON не лучший подход и я на нем не настаиваю, отдельная таблица для изменений это самый гибкий вариант.
Алексей Березников, Да не нужно ничего сравнивать))) В том-то и дело) То, что я писал про сравнение - это единственно когда оно может понадобиться) А так: сравнение не нужно! Вообще!) Просто прямой, как полет стрелы, update where и все)
Владимир, Вот у вас есть старый и новый профиль, вы модератор. Вам нужно понять, что именно поменялось, чтобы вынести свой вердикт так сказать. Одно дело если 2-3 поля, это несложно, но бывает и по 20 полей (например юрлица контрагенты) - и там уже глаз может легко замылиться. Т. е. очень логично будет подсветить только те поля, что изменились, а может быть даже и отобразить только их - мол гляди, вот такие ченджи сделал этот юзер, принимаем нет? И вот вам приходится писать 20 if-ов для того, чтобы сравнить старые и новые значения, а с историей изменений эта история начинает играть новыми красками :) Либо делаете все поля nullable (якобы то, что не изменилось - null), до свидания целостность данных на уровне БД. Либо добавляете отдельный флаг, изменено поле или нет - тот же костыль, только в профиль. Вот я и говорю, каждому своё - если вас устраивает такая архитектура, я не вижу смысла в дальнейшем диалоге.
Алексей Березников, Я занимаюсь бэкендами, но я вас понял: вы действительно не понимаете о чем идет речь, т.к. ваша область - морды. Если вам действительно необходимо ставить красивые галочки, крестики и вопросики, то абсолютно все равно, что используется - JSON, две модели, записи с признаками или что-то еще - для морды вы получите то, что хватит вам идеально и с запасом. И, во всех случаях nullable - лишнее, если вы уважаете KISS. А вот от сравнений в том или ином виде вы никуда не денетесь, сравнивать придется обязательно. Хотя, может я чего-то не знаю, вы владеете магией и можете узнать одинаковы поля или нет без сравнения?)))
Владимир, я фронтендом вообще не занимаюсь, но думаю не только о том, как бы таску закрыть, но и о том, что придётся делать дальше. А без сравнения можно обойтись, если записывать только изменённые поля в отдельную таблицу в формате key-value.
Владимир, Я думаю я вам уже и так разжевал более чем достаточно, вы уж извините, но у меня есть дела и поважнее :) Да вам придётся в одном месте один раз сравнить, и то есть методы как даже этого не делать (типа свойств dirty у инпутов), и это совершенно не сравнимо с необходимостью сравнивать каждый раз для просмотра, сохранения данных и т. д. А потом добавится новое поле и кто-то забудет в одном месте один if и 20 и тому подобное.
Т.е. сравнивать все-таки придется))) А насчет свойства dirty я вам открою страшную тайну: там тоже происходит сравнение, только его написали за вас. Более того, когда вы его используете, то вам нужно проверить что в нем, а это - еще одно сравнение, внезапно. К тем, что там в недрах объекта производились) Да и не факт, что все делается в Angular или мелкомягком Access'е, и это (либо аналогичное) свойство вам доступно.