You mentioned the join entities (blc_product_cross_sale) having additional properties that should be managed within the relationship. We actually manage this with an @AdminPresentationAdornedTargetCollection. The idea with this annotation is that you would like to relate 2 entities together (like Product and Category) but also want to manage fields on the join table in-between them.
This is what the list of cross sale products looks like on CategoryImpl:
Code: Select all
@OneToMany(mappedBy = "category", targetEntity = CrossSaleProductImpl.class, cascade = {CascadeType.ALL})
@Cascade(value={org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blCategories")
@OrderBy(value="sequence")
@AdminPresentationAdornedTargetCollection(friendlyName = "crossSaleProductsTitle", order = 2000,
tab = Presentation.Tab.Name.Marketing, tabOrder = Presentation.Tab.Order.Marketing,
targetObjectProperty = "relatedSaleProduct",
sortProperty = "sequence",
maintainedAdornedTargetFields = { "promotionMessage" },
gridVisibleFields = { "defaultSku.name", "promotionMessage" })
@ClonePolicyAdornedTargetCollection
protected List<RelatedProduct> crossSaleProducts = new ArrayList<RelatedProduct>();
And if you look at the CrossSaleProductImpl entity:
Code: Select all
@Column(name = "CROSS_SALE_PRODUCT_ID")
protected Long id;
@Column(name = "PROMOTION_MESSAGE")
@AdminPresentation(friendlyName = "CrossSaleProductImpl_Cross_Sale_Promotion_Message", largeEntry=true)
protected String promotionMessage;
@Column(name = "SEQUENCE", precision = 10, scale = 6)
@AdminPresentation(visibility = VisibilityEnum.HIDDEN_ALL)
protected BigDecimal sequence;
@ManyToOne(targetEntity = ProductImpl.class)
@JoinColumn(name = "PRODUCT_ID")
@Index(name="CROSSSALE_INDEX", columnNames={"PRODUCT_ID"})
protected Product product;
@ManyToOne(targetEntity = CategoryImpl.class)
@JoinColumn(name = "CATEGORY_ID")
@Index(name="CROSSSALE_CATEGORY_INDEX", columnNames={"CATEGORY_ID"})
protected Category category;
@ManyToOne(targetEntity = ProductImpl.class, optional=false)
@JoinColumn(name = "RELATED_SALE_PRODUCT_ID", referencedColumnName = "PRODUCT_ID")
@Index(name="CROSSSALE_RELATED_INDEX", columnNames={"RELATED_SALE_PRODUCT_ID"})
protected Product relatedSaleProduct = new ProductImpl();
The 'real' relationship is between the 'relatedSaleProduct' and a category. In the @AdminPresentationAdornedTargetCollection there is also a 'maintainedAdornedTargetFields = { "promotionMessage" }' which means that the UI will allow you to manage that field on the relationship.
The UI looks like when you add a cross sale product you first select a Product (step 1 of 2):
http://cl.ly/image/1L221R1D2x0N and then you fill in the promotion message (which is a property on that join entity):
http://cl.ly/image/3I0i013r1G3k.
You are right, we do not have the specific UI portion for multi-select but I think that the requirement is still met through our list grid UIs. Feel free to open a feature request describing this at
https://github.com/BroadleafCommerce/Br ... rce/issues.