实体也可以做加减?

业务:一笔订单,有种商品,且该笔订单已发货。如果顾客不满意,可退货。而且业务上允许对一笔订单进行多次退货。假设该订单有十种商品,每种数量为“1”,那么就可以退十次。

数据库设计:销售订单和退货订单存一起,退货订单有一字段指向原订单。

如果顾客要退货,原订单的行项目要跟它已经产生的退货单的行项目进行"减"操作。才能知道此时还有哪些商品可退。


“订单”是个实体,不是“值对象”。但好像有这种要求:
可退货行项目 = 原单行项目 - 所以已退货行项目



[该贴被admin于2009-07-21 16:21修改过]

模型应该是:

可退货订单 = 原单 - 退货单

这三个都是同一个实体

个人认为好像是指对特定的订单项的退货作业。
class Order{
Set<Item> items;
}
class Item{
boolean back;
}
这样应该能够计数并列举出哪些可以退货哪些不能了,如果需求还有要求生成退货单的,也可以由这些item重组生成。
[该贴被freebox于2009-06-11 15:09修改过]

boolean back;

不能解决问题,如果该行项目的数量是10,我只要退2两个,
back就成了尴尬的属性。

我提到过,一笔订单的退货单是有记录的,退货单跟其它订单都在一张,结构一样的。

我没有区分是订货单还是退货单,这些都得到保存,最后发货的时候是按订货单和退货单的统计计算的。
像订货单order1{item1{count:10,back:false}}
退货单order2{item1{count:2,back:true}}
根据这些单就可以统计计算。
或者把退货单的item count规定为负值,放弃back属性,最后也能统计。
对item的操作就像很多金融系统一样,不能直接加减,只能记录每一笔资料,最后统计,也可以在每一笔记录之后生成瞬时状态,下次直接以这个状态为基础进行操作,操作后的新状态变成新的瞬时状态,但在最后发货前仍要重新统计以确保瞬时状态是有效态。
下面用正负值标记的item,简要写个方法。


class Order{
Long id;
String number;
<Set>Item items;
public Order add(Order order){
if(!order.number.equals(this.number)){
throw new OrderException("not same order operation");
}
Order momentOrder=new Order(new HashSet<Item>());
for(Item item:this.items){
for(Item orderItem:order.items){
if(item.product.equals(orderItem.product)){
if(item.count+orderItem.count<0){throw new OrderException(
"count error");}
momentOrder.items.add(new Item(item.product,item.count+orderItem.count));
}
}
}
return momentOrder;
}
}
class Item{
int count;
//equals hashcode
}

可退加减是一个业务计算,没有必须做一个可退货订单,可退货订单是结果,结果不能做为实体,因为你是数据库思维,在数据表里,输入和输出都并行躺在那里,所以,你从数据表反推到对象实体,以为有一个可退货订单是对象实体。

你可以做一个Specification,用来进行可退加减规则计算就可以。

对,退货是一种操作,而不是一种属性,对于商品的属性没有改变,而只是决定了某个承载该对象的容器数量的变化,以及产生相关的后果(生成退货单)。

确实,退货是一个业务操作,专门有个获取可退货的订单明细的方法,该方法逻辑:把所有该笔订单的退货单汇总,然后然后循环原订单的明细跟汇总后的明显进行比较。得出可退货的订单明细。

但我觉得这样做不是很好。而且如果明细里有特殊的东西,处理就复杂了。比如说运费也是一个订单里的明细,该明细的数量永远都是1.

运费也是可以部分退的,虽然代码已经实现,感觉不是很优雅,也不好扩展。

用spec的话就声明一个退回接口,退订单项和退运费和退其它分别实现,需要考查订单项、运费、其它项之间有没有业务上的必然联系,是不是退一个其它的也必须跟着改变等。不了解更详细的业务,先分析这点。

首先你要分析你的订单里面有什么,货物能够等同于运费么??运费是否是根据货物的多少计算出来的?他们是订单项,具备显示的方法,但是对于一个订单,应当包含题头,户名,时间、明细、合计等一些列的订单项,但是这些订单项是不一样的。难道能用一种方法搞定么??