Немного знания предметной области
Я пишу POS (Point Of Sales) программное обеспечение, которое позволяет оплачивать товары или возвращать их. При оплате или возврате денег необходимо указать, какой денежный перевод означает использовать: наличные, EFT (~ = кредитная карта), карта лояльности, ваучер и т. Д.
Эти средства денежных переводов представляют собой конечный и известный набор значений (своего рода перечисление).
Сложность в том, что мне нужно иметь возможность хранить пользовательский набор этих средств как для платежей, так и для возвратов (эти два набора могут отличаться) на POS-терминале.
Например:
- Доступные способы оплаты: наличные, EFT, карта лояльности, ваучер
- Доступный возврат средств: наличные, ваучер
Текущее состояние реализации
Я решил реализовать концепцию перевода денег следующим образом:
public abstract class MoneyTransferMean : AggregateRoot
{
public static readonly MoneyTransferMean Cash = new CashMoneyTransferMean();
public static readonly MoneyTransferMean EFT = new EFTMoneyTransferMean();
// and so on...
//abstract method
public class CashMoneyTransferMean : MoneyTransferMean
{
//impl of abstract method
}
public class EFTMoneyTransferMean : MoneyTransferMean
{
//impl of abstract method
}
//and so on...
}
Причина, по которой это не просто перечисление, заключается в том, что в этих классах существует некоторое поведение. Мне также пришлось объявить внутренние классы открытыми (а не закрытыми), чтобы ссылаться на них в отображении FluentNHibernate (см. Ниже).
Как это используется
Средства оплаты и возврата всегда хранятся или извлекаются в / из БД в виде набора. На самом деле это два разных набора, хотя некоторые значения внутри обоих наборов могут быть одинаковыми.
Вариант использования 1: определить новый набор средств оплаты / возврата
- Удалить все существующие способы оплаты / возврата
- Вставьте новые
Вариант использования 2: получить все средства оплаты / возврата
- Получить коллекцию всех сохраненных средств оплаты / возврата
проблема
Я застрял с моим текущим дизайном на аспекте постоянства. Я использую NHibernate (с FluentNHibernate для объявления карт классов) и не могу найти способ сопоставить его с какой-либо действительной схемой БД.
Я обнаружил, что можно отобразить класс несколько раз, используя имя объекта, однако я не уверен, что это возможно с подклассами.
Что я не готов сделать, так это изменить публичный API MoneyTransferMean, чтобы иметь возможность его сохранить (например, добавить bool isRefund
различие между ними). Однако добавление некоторого частного поля дискриминатора или все в порядке.
Мое текущее отображение:
public sealed class MoneyTransferMeanMap : ClassMap<MoneyTransferMean>
{
public MoneyTransferMeanMap()
{
Id(Entity.Expressions<MoneyTransferMean>.Id);
DiscriminateSubClassesOnColumn("Type")
.Not.Nullable();
}
}
public sealed class CashMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.CashMoneyTransferMean>
{
public CashMoneyTransferMeanMap()
{
DiscriminatorValue("Cash");
}
}
public sealed class EFTMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.EFTMoneyTransferMean>
{
public EFTMoneyTransferMeanMap()
{
DiscriminatorValue("EFT");
}
}
//and so on...
Это сопоставление компилируется, однако оно генерирует только 1 таблицу, и я не могу отличить платеж / возврат при запросе этой таблицы.
Я попытался объявить два сопоставления, ссылающихся как MoneyTransferMean
на другую таблицу, так и на имя объекта, однако это приводит меня к исключению Duplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean
.
Я также пытался дублировать сопоставления подклассов, но я не могу указать «родительское сопоставление», которое приводит меня к тому же исключению, что и выше.
Вопрос
Существует ли решение для сохранения моих текущих доменных сущностей?
Если нет, то какой наименьший рефакторинг я должен выполнить для своих сущностей, чтобы сделать их устойчивыми с помощью NHibnernate?
What I'm not ready to do is to alter the MoneyTransferMean public API to be able to persist it (for example adding a bool isRefund to differentiate between the two).
: Почему бы нет? Это простое и приятное изменение, которое должно решить вашу проблему. Вы можете сделать с тремя возможными значениями (хотя два и будет делать с дублированием записей илиFlag
типа):Payment
,Refund
,Both
. Если для васbool
подходят два значения, то собственность просто великолепна.Ответы:
Почему бы вам не создать одну единственную сущность MoneyTransferMean со всеми общими свойствами (полями) и просто добавить 2 дополнительных поля (логических), чтобы определить, является ли этот MoneyTransferMean платёжным или возвратным, или и тем и другим ???? Сохранять это или нет.
Также это может быть сделано с дополнительным Entity с Id (PK), добавьте те же дополнительные поля, отношение будет 1: 1 с MoneyTransferMean. Ужасно, я знаю, но это должно работать.
источник
Я бы добавил и добавил к тому, что предложил @ DEVX75, в том смысле, что ваши типы транзакций по сути описывают одну и ту же концепцию, хотя один из них + ve, а другой - -ve. Я, вероятно, добавил бы только одно логическое поле, и имел бы отдельные записи, чтобы различить возмещение от платежей.
Предполагая, что у вас есть UID и вы не используете имя метки средства в качестве идентификатора, вы можете разрешить дублирование имен для средств и включить две записи кассы, например:
Тогда вы можете легко получить следующее:
Таким образом, если в своих транзакциях вы ссылались на MoneyTransferMean.UID = 2, вы знаете, что это денежное возмещение, а не знаете, что это тип транзакции, который может быть либо денежным, либо денежным.
источник
Наконец, я решил решить эту проблему, дублируя мое лицо
MoneyTransferMean
на два объектаPaymentMean
иRefundMean
.Несмотря на схожесть в реализации, различие между двумя объектами имеет смысл в бизнесе и было для меня наименее худшим решением.
источник