Skip to content

OBPIH-6298 Error while placing a PO without a product source#4575

Merged
awalkowiak merged 6 commits intorelease/0.9.1from
OBPIH-6298
Apr 5, 2024
Merged

OBPIH-6298 Error while placing a PO without a product source#4575
awalkowiak merged 6 commits intorelease/0.9.1from
OBPIH-6298

Conversation

@kchelstowski
Copy link
Collaborator

No description provided.

…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
@kchelstowski kchelstowski self-assigned this Apr 4, 2024
@kchelstowski kchelstowski changed the title Obpih 6298 OBPIH-6298 Error while placing a PO without a product source Apr 4, 2024
productSupplier: obj.productSupplier
)
return !productPackage || productPackage?.id == obj?.id
})
Copy link
Collaborator Author

@kchelstowski kchelstowski Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to refactor this part, because otherwise packages:

  1. productSupplier: null, uom: "XYZ", quantity: X
  2. 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 ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the name productPackage1, but nothing better comes to my mind, maybe other developers will have some ideas 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's been like this before, hence I assumed this would fit OK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep this in mind. The more we can move to the domain, the easier it'll be to do unit testing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it was mostly a pattern to keep an eye out for in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell we don't need orderItem there. Could you explain the need for that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

image

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)
        }
    }

@awalkowiak awalkowiak merged commit 9d687d7 into release/0.9.1 Apr 5, 2024
@awalkowiak awalkowiak deleted the OBPIH-6298 branch April 5, 2024 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants