[OBPIH-6612] add inverse prepayment invoice items for existing data#4796
Conversation
|
@awalkowiak lets chat about this PR either during tech huddle or a JEAM meeting. I'm hoping we can refine this a bit since it's pretty crude in its current state. Maybe we can build a lot of this logic into the PrepaymentInvoiceService (or maybe a new PrepaymentInvoiceMigrationService) and unit test the heck out of it to know that it works. It also doesn't seem to run on app startup so I need to figure out why... |
You have to add this migration file in the 0.9.x/changelog.xml. Looks like (at least in this PR) it is missing there. |
....x/changelog-2024-08-20-0000-migrate-prepayment-invoices-add-amount-and-inverse-items.groovy
Outdated
Show resolved
Hide resolved
| amount(nullable: true) | ||
| unitPrice(nullable: true) | ||
| inverse(nullable: true) | ||
| inverse(nullable: false) |
There was a problem hiding this comment.
@awalkowiak the migration script used to be looping through all existing invoice items and marking them as inverse = false which I realize is the same as doing this and since the code will probably break if this value isn't set, then I think this makes sense to make as non-null.
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
....x/changelog-2024-08-20-0000-migrate-prepayment-invoices-add-amount-and-inverse-items.groovy
Outdated
Show resolved
Hide resolved
....x/changelog-2024-08-20-0000-migrate-prepayment-invoices-add-amount-and-inverse-items.groovy
Outdated
Show resolved
Hide resolved
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
|
Did you try to run it locally? How was the performance? |
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
|
@awalkowiak I haven't been able to performance test this yet since I haven't tried setting my local up with prod data. Maybe we can chat tomorrow about what it takes to get that set up (and I can document the process for the future). |
…o ft/OBPIH-6612-migrate-old-prepay-invoices
alannadolny
left a comment
There was a problem hiding this comment.
Maybe I am missing something, but is there a check to see if this migration was run? I mean it looks like it can take a lot of time to run on a bigger db, so maybe it will be beneficial to check if there is a need to run that before.
....x/changelog-2024-08-20-0000-migrate-prepayment-invoices-add-amount-and-inverse-items.groovy
Outdated
Show resolved
Hide resolved
....x/changelog-2024-08-20-0000-migrate-prepayment-invoices-add-amount-and-inverse-items.groovy
Outdated
Show resolved
Hide resolved
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
grails-app/services/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationService.groovy
Outdated
Show resolved
Hide resolved
src/test/groovy/unit/org/pih/warehouse/invoice/PrepaymentInvoiceMigrationServiceSpec.groovy
Outdated
Show resolved
Hide resolved
awalkowiak
left a comment
There was a problem hiding this comment.
I think we need to have some extensive logging, which PO we are updating right now and how many there are still left. I would also wrap the update logic in some try-catch and log into the console the POs that failed to update (I am basing this idea on the Alan's recent issue with his local db)
| * The logic was only put in a service class so that it could be unit tested. Do not use it in regular flows. | ||
| */ | ||
| @Transactional | ||
| class PrepaymentInvoiceMigrationService { |
There was a problem hiding this comment.
I started wondering if it is a good idea to move this logic to a separate service, because we are removing the liquibase's complaints about checksum if someone modifies something in this service
There was a problem hiding this comment.
Plus I am getting more and more convinced that it should be a manual trigger from data migration page in app instead of a db migration ;/
There was a problem hiding this comment.
that's a fair point, though I'd hope we wouldn't need to ever modify this file and if we did I don't see a world where we'd want to rerun it. The only reason it's in here is so that I could unit test it.
As to making this a manual trigger, yes we discussed it before and that's likely a safer option (that or just auto-migrate any invoices when they're saved if they haven't been migrated yet). We'd need to refactor the partial invoicing code to be able to support old data, but it'd mean we're not running this questionably long migration step on startup.
|
The change runs the full way through with my latest commit. Looks like it had something to do with the way the code was looping over the prepayment invoices. Maybe something to do with iterator vs loops, I'm not totally sure. Here's the output I got on my local with stage data: which is much faster than I thought it would be... I'm slightly suspicious and also wondering where the other 61 prepayment invoices are (I have a log statement for each case so I have no idea...) I still have to check how the invoices are looking in the frontend (my local is behaving all wonky with the stage data). |
|
I poked around in the UI for some invoices that were migrated and all the ones I looked at seem to look correct to me. That said, I'm noticing the migration is not setting the amount field for any old non-prepay, non-inverse invoice items, would this be a problem? I'd appreciate if someone else could run the migration locally to confirm it works for them as well. @awalkowiak @alannadolny Artur, I know you wanted to revisit the topic of whether we should not do this migration, so if you have that conversation Monday please loop me in (I'll be OOO), |
|
@alannadolny to answer an earlier question, I thought about it, but it's quite difficult to construct a reasonable precondition for these migrations. For step 1, we could technically add a check like: but that's doing essentially the same lookup that the migration is doing and so wouldn't really save us much. And step 2 of the migration is even harder to build a precondition for. Anyways, if there's nothing to migrate, the script will likely run fast enough since it's just doing a few selects, but it is a valid concern. |
|
@awalkowiak I'm going to remove the do not merge flag in case any decisions are made on Monday, but I'd like at the very least to have one more person test on their local first. |
jmiranda
left a comment
There was a problem hiding this comment.
I'm going to try to address all of the points made in the PR and anything else I could think of.
- I like the idea of moving the migration code to its own service. Even though it's only going to be executed once it's better to have the logic in one place.
- Whether we go with a liquibase changeset or manual data migration trigger is up to you guys. If we think there's even a remote chance that existing implementations will have prepayment invoices we should probably go with the former.
- The one thing I wanted to see in the PR was whether we had logic to detect whether this migration had already been executed. Not a precondition, but the check mentioned in Line 78-79 where we skip invoices that already have inverse items. One word of caution on this. If you get to a place where you want to allow rerunning the migration (due to an error that might occur in the middle) you might want to change the logic to "does every invoice item have an inverse" so the process can be rerun over the invoice that error'd.
- I wasn't ever really concerned about the performance of this because there's not much happening. I'm just glad that was actually the case.
- Are we sure the service, executed via Bootstrap.groovy (during database migrations phase), is participating in a transaction? Can you run some tests on what happens when an exception occurs while processing an invoice within the loop?
- While not necessary, the one way to rollback the operation would be to remove all inverse invoice items for an invoice. In fact, you could set up the migration to execute ALWAYS and as long as the check logic was "do all invoice items have an invoice", you could safely execute the inverse operation.
|
3 - That's a fair concern. It might be somewhat complex to determine since we'd need to fetch all invoice items of an invoice at once and see if there's a matching inverse for each item, but maybe it's worth it to do that extra work just to be sure we don't ever get in a halfway state. If this is all working in a transaction, it shouldn't be an issue since it should get rolled back. I'll check. 5 - Good question. I'll test. 6 - I'm not sure it's safe to rollback by deleting inverse items. I don't think the system could handle that properly since it now expects the inverse items to be there. Maybe it'd be fine though and we can keep generating inverse items the old way if there aren't already inverses. Maybe @awalkowiak can comment on this. |
|
Okay I tested the code and it does seem to be properly transactional (I threw an error at the end of the migration and all amount fields were set back to null). I believe this solves concerns 3 since if there's ever an error (there shouldn't be), the script will rollback all inverse items it created and so would be impossible to get stuck in a place where some of a prepayment invoice's items have an inverse and some don't. As far as I'm concerned I think this can be merged once we've had a chance to retest against Manon's data on stage. |
59153ff
into
feature/OBPIH-6398-partial-invoices-for-prepaid-po

✨ Description of Change
Link to GitHub issue or Jira ticket: https://pihemr.atlassian.net/browse/OBPIH-6612
Description: Now that we're storing inverse prepayment invoice items on the server, we need to migrate our existing non-prepayment (aka final) invoices to include those inverses as well since historically we've generated the inverses on demand. See ticket for details.
📈 Test Plan
Description of test plan (if applicable): This is going to require thorough testing to make sure that we don't muck up any of our environments by running this script. We'll need to populate a local db with some old data then run the migration to ensure everything looks correct.
✅ Quality Checks
[OBS-123]for Jira,[#0000]for GitHub, or[OBS-123, OBPIH-123]if there are multiple), or with[N/A]if not applicable