Skip to content

[OBPIH-6612] add inverse prepayment invoice items for existing data#4796

Merged
awalkowiak merged 10 commits intofeature/OBPIH-6398-partial-invoices-for-prepaid-pofrom
ft/OBPIH-6612-migrate-old-prepay-invoices
Sep 6, 2024
Merged

[OBPIH-6612] add inverse prepayment invoice items for existing data#4796
awalkowiak merged 10 commits intofeature/OBPIH-6398-partial-invoices-for-prepaid-pofrom
ft/OBPIH-6612-migrate-old-prepay-invoices

Conversation

@ewaterman
Copy link
Member

@ewaterman ewaterman commented Aug 20, 2024

✨ Description of Change

A concise summary of what is being changed. Please provide enough context for reviewers to be able to understand the change and why it is necessary. If the issue/ticket already provides enough information, you can put "See ticket" as the description.

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

We require that all code changes come paired with a method of testing them. Please select which of the following testing approaches you've included with this change:

  • Frontend automation tests (unit)
  • Backend automation tests (unit, API, smoke)
  • End-to-end tests (Playwright)
  • Manual tests (please describe below)
  • Not Applicable

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

Please confirm and check each of the following to ensure that your change conforms to the coding standards of the project:

  • The pull request title is prefixed with the issue/ticket number (Ex: [OBS-123] for Jira, [#0000] for GitHub, or [OBS-123, OBPIH-123] if there are multiple), or with [N/A] if not applicable
  • The pull request description has enough information for someone without context to be able to understand the change and why it is needed
  • The change has tests that prove the issue is fixed / the feature works as intended

@ewaterman ewaterman requested a review from awalkowiak August 20, 2024 22:23
@ewaterman ewaterman self-assigned this Aug 20, 2024
@github-actions github-actions bot added type: feature A new piece of functionality for the app domain: backend Changes or discussions relating to the backend server flag: schema change Hilights a pull request that contains a change to the database schema labels Aug 20, 2024
@ewaterman ewaterman added status: work in progress For issues or pull requests that are in progress but not yet completed warn: do not merge Marks a pull request that is not yet ready to be merged labels Aug 20, 2024
@ewaterman
Copy link
Member Author

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

@awalkowiak
Copy link
Collaborator

@ewaterman

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.

amount(nullable: true)
unitPrice(nullable: true)
inverse(nullable: true)
inverse(nullable: false)
Copy link
Member Author

Choose a reason for hiding this comment

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

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

@awalkowiak
Copy link
Collaborator

Did you try to run it locally? How was the performance?

@ewaterman ewaterman removed the status: work in progress For issues or pull requests that are in progress but not yet completed label Aug 26, 2024
@ewaterman
Copy link
Member Author

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

Copy link
Collaborator

@alannadolny alannadolny left a comment

Choose a reason for hiding this comment

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

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.

Copy link
Collaborator

@awalkowiak awalkowiak left a comment

Choose a reason for hiding this comment

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

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 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

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 ;/

Copy link
Member Author

Choose a reason for hiding this comment

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

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.

@ewaterman
Copy link
Member Author

@awalkowiak @alannadolny

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:

Prepayment Invoice migration completed in 12755 milliseconds!
761 prepayment invoices/orders were found.
694 orders were migrated.
6 were skipped due to no migration being needed
0 were skipped due to a bad order.

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

@ewaterman
Copy link
Member Author

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

image

@ewaterman
Copy link
Member Author

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

    preconditions(onFail:'MARK_RAN') {
            sqlCheck(expectedResult: '0') {
                <count all invoice items where amount is null joined in invoice where invoice type is prepayment>
            }
    }

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.

@ewaterman
Copy link
Member Author

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

@ewaterman ewaterman removed the warn: do not merge Marks a pull request that is not yet ready to be merged label Aug 30, 2024
@awalkowiak awalkowiak requested a review from jmiranda September 3, 2024 14:56
Copy link
Member

@jmiranda jmiranda left a comment

Choose a reason for hiding this comment

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

I'm going to try to address all of the points made in the PR and anything else I could think of.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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?
  6. 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.

@ewaterman
Copy link
Member Author

ewaterman commented Sep 5, 2024

@jmiranda

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.

@ewaterman
Copy link
Member Author

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.

@awalkowiak awalkowiak merged commit 59153ff into feature/OBPIH-6398-partial-invoices-for-prepaid-po Sep 6, 2024
@awalkowiak awalkowiak deleted the ft/OBPIH-6612-migrate-old-prepay-invoices branch September 6, 2024 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: backend Changes or discussions relating to the backend server flag: schema change Hilights a pull request that contains a change to the database schema type: feature A new piece of functionality for the app

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants