OBPIH-6298 Error while placing a PO without a product source#4575
OBPIH-6298 Error while placing a PO without a product source#4575awalkowiak merged 6 commits intorelease/0.9.1from
Conversation
…er for the persistence actions to be flushed before rendering a view
… an existing one (found by the product, uom, quantity pair)
…ckage with and without productSupplier, but with the same uom/quantity pair is treated as the same package
…hile finding a product package
| productSupplier: obj.productSupplier | ||
| ) | ||
| return !productPackage || productPackage?.id == obj?.id | ||
| }) |
There was a problem hiding this comment.
I had to refactor this part, because otherwise packages:
- productSupplier: null, uom: "XYZ", quantity: X
- productSupplier: "ZYX", uom: "XYZ", quantity: X
did not pass the unique constraint, because when no productSupplier provided, for the validation query it was not searching for eventual productPackage with productSupplier as null, but skipped it while quering, so for the uniqness check, it was doing:
select from product_package where
uom = ...
and product = ...
and quantity = ...
instead of:
select from product_package where uom = ...
and product = ...
and quantity = ...
and product_supplier IS NULL
|
|
||
| // If not found, then we look for a product package associated with the product | ||
| if (!productPackage && !orderItem?.productSupplier) { | ||
| productPackage = orderItem.product.packages.find { ProductPackage productPackage1 -> |
There was a problem hiding this comment.
I don't like the name productPackage1, but nothing better comes to my mind, maybe other developers will have some ideas 🤔
There was a problem hiding this comment.
it's been like this before, hence I assumed this would fit OK.
There was a problem hiding this comment.
I had the same reaction, but I've probably done this as well. This is a case where the default it would probably make it less confusing, but that's not an official convention so meh.
In general, if there's a way to describe a variable in a more meaningful way, then do it. Here, since we're basically iterating through and trying to find a default product package, I would call it defaultProductPackage.
A better (more DRY, OOO) approach would be to add a convenience method to Product.
if (!productPackage && !orderItem?.productSupplier) {
productPackage = orderItem.product.getDefaultProductPackage(orderItem.quantityPerUom, orderItem.quantityUom)
The actual method might look like this
// Does not handle if multiple product packages match (but this should happen due to unique constraint)
// Does not pass product since we make the call on orderItem.product
ProductPackage getDefaultProductPackage(Integer quantityPerUom, quantityUom) {
return productPackages.find { ProductPackage productPackage ->
return productPackage.uom == orderItem.quantityUom &&
productPackage.quantity == orderItem.quantityPerUom &&
!productPackage.productSupplier
}
}
There was a problem hiding this comment.
Keep this in mind. The more we can move to the domain, the easier it'll be to do unit testing.
There was a problem hiding this comment.
@jmiranda would you like me to move it to a method now, or you just wanted to make a point for the future?
If the answer is, that I should move it, then I think I'd also have to pass the orderItem as well (beside quantityPerUom and uom), because if we want to have it in the Product domain, we would not have the access to the orderItem.
There was a problem hiding this comment.
Yeah it was mostly a pattern to keep an eye out for in the future.
There was a problem hiding this comment.
As far as I can tell we don't need orderItem there. Could you explain the need for that?
There was a problem hiding this comment.
From the Product domain we don’t have an access to orderItem, hence if we wanted to make this method work we would have to pass the orderItem as an argument, which is currently passed to the updateProductPackage method where this if belongs to
There was a problem hiding this comment.
Sorry, I'm missing something here. What do you need from the order item that we're not already passing into the new method?
Oops. Sorry, I just realized I had a typo in my previous version of getDefaultProductPackage. I've now removed the "orderItem" from within the find closure.
The new method on Product.groovy doesn't need the orderItem, it would take the quantity and uom as arguments.
ProductPackage getDefaultProductPackage(Integer quantityPerUom, UnitOfMeasure quantityUom) {
return productPackages.find { ProductPackage productPackage ->
return productPackage.uom == quantityUom &&
productPackage.quantity == quantityPerUom &&
!productPackage.productSupplier }
}
And then the caller in updateProductPackage would just invoke the default product package method using the properties from orderItem.
// If not found, then we look for a product package associated with the product
if (!productPackage && !orderItem?.productSupplier) {
productPackage = orderItem.product.getDefaultProductPackage(orderItem.quantityPerUom, orderItem.quantityUom)
}
}

No description provided.