Skip to content

OBPIH-6328 Dashboard indicator for items with backdated shipments#4633

Merged
awalkowiak merged 11 commits intodevelopfrom
OBPIH-6328
May 28, 2024
Merged

OBPIH-6328 Dashboard indicator for items with backdated shipments#4633
awalkowiak merged 11 commits intodevelopfrom
OBPIH-6328

Conversation

@alannadolny
Copy link
Collaborator

No description provided.

List<GroovyRowResult> results = dataService.executeQuery(query, [
locationId: location?.id,
inventoryId: location?.inventory?.id,
transactionCode: TransactionCode.PRODUCT_INVENTORY.name(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this also should/could include TransactionCode.INVENTORY. I think it was used in the past for marking the record stock done through import inventory. At least we are still looking into this type while calculating transactions for product availability and the latest inventory dates indicator.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am not sure about that, this subquery for getting the last stock count date is the same as in the product view (I copied this part of the query from there).
So, this method is called in the view:
image
This is the method that contains the query:
image

But, if you are sure about it, I can change that

Copy link
Member

Choose a reason for hiding this comment

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

Sorry just seeing this now. I would prefer NOT to include Inventory. We have removed all of the features that created this type of transaction so if there's data in the database it's very old and somewhat irrelevant. In other words, if a transaction exists that has an "INVENTORY" transaction code I'd be fine for the last stock count feature to return Never.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@jmiranda do we have all these types of decisions documented somewhere? I based my comment (suggestion) on the past behavior, and state of the current code where we are still looking into this transaction type, and there is some dead code in the InventoryService that is using it and it was a bit misleading. Perhaps we could at least add some comments about it in the TransactionCode enum?

Copy link
Member

@jmiranda jmiranda May 29, 2024

Choose a reason for hiding this comment

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

and state of the current code where we are still looking into this transaction type

I think you're misread what I said.

Justin: "We have removed all of the features that created this type of transaction"

If that's not true and there's still code that creates INVENTORY transactions then please flag them and let me know.

do we have all these types of decisions documented somewhere?

Yes, this particular issue was documented before you guys were involved.
#165

The underlying issue is the QoH Calculation issue that is near and dear to my heart. It was recently documented here but there are probably countless discussions on this issue throughout tickets, documents, and community posts.
https://pihemr.atlassian.net/browse/OBPIH-6353

The pull request for #165 is this epic roller coaster.
#710

I was only able to get to a place where we could convert the INVENTORY transactions to ADJUSTMENT transactions on a product by product basis. The idea was to eventually move this to an automated feature that would convert everything, but I wasn't comfortable with that since there were some edge cases that I wasn't absolutely sure about.

So I pushed that code and converted all of the transactions in the PIH and SBHF databases. But I have been holding out hope that I'd someday get become independently wealth so I could fund my own development priorities or have time to work on it as tech debt using PIH's budget. However, it's pretty far down on the tech debt priority list, so I think it'll probably be refactored out completely once we have time to work on the Cycle Count feature and the data model refactorings around that.

Perhaps we could at least add some comments about it in the TransactionCode enum?

Yes, that's probably a good idea.

WHERE DATE_ADD(t.transaction_date, INTERVAL :daysOffset DAY) < t.date_created
AND t.date_created > :timeLimit
AND s.origin_id = :locationId
) AS bt
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please be a bit more descriptive here with bt and sc since it does not match any table name and it's hard to decode

List<TableData> tableData = results.collect { new TableData(
it[0] as String, // Item
it[2] as String, // Shipments
it[3] as String ?: "None" // Last count
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think "Never" would fit here more, unless "None" was requested, then you can disregard this comment

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 was requested

Copy link
Member

Choose a reason for hiding this comment

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

@awalkowiak I guess this is the sort of detail we need to catch during "design".

One additional point (add to #3849)

  1. We should use an enum if there are multiple coded classification values (i.e. Never, Long Ago, Somewhat Recently, Recently)
  2. We should use a Constant if we need to support just a string literal in logic (i.e. Default, Never, None).
  3. We should allow constants and enums to be i18n'd, so there's a way to translate the actual string literal.

Add it right under the default constant and call it never.

static final String DEFAULT = "DEFAULT"
static final String NEVER = "NEVER"

Copy link
Collaborator

Choose a reason for hiding this comment

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

@jmiranda

I guess this is the sort of detail we need to catch during "design".

This particular label did not appear in the ticket at all, and it was just suggested by Manon outside the ticket. So it is hard to speak about design here if it was missed since the beginning. I am also not sure if I would spot it even with a proper dev design because I would be focusing on the SQL query itself, it is hard to tell.

Copy link
Collaborator

Choose a reason for hiding this comment

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

(added a topic around label and messages designing for a tech huddle)

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, in case it wasn't clear ... this was not criticism of what we should have done here but rather what patterns we should be looking for when we start to do proper design in the near future.

Copy link
Member

Choose a reason for hiding this comment

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

I think we want to do something like this to allow for i18n.

default.lastInventoryCount.NEVER.label
default.lastInventoryCount.NONE.label

Then the value could be a constant, enum, or null.

it[3] as String ?: Constants.DEFAULT // or TimeEnum.NEVER or null

And then somewhere else we might try to resolve this value to an i18n string

if (whatever.lastInventoryCount) { 
    formatDate(whatever.lastInventoryCount)
} else {
    return g.message(code: "default.lastInventoryCount.never.label")
}

@awalkowiak awalkowiak merged commit f36c76d into develop May 28, 2024
@awalkowiak awalkowiak deleted the OBPIH-6328 branch May 28, 2024 16:23
]

String query = '''
SELECT ii.product_id, COUNT(ii.product_id) as products, GROUP_CONCAT(backdated_transaction.shipment_number SEPARATOR ' ') as shipments, DATE_FORMAT(stock_count.last_stock_count, "%d-%M-%Y") FROM (
Copy link
Member

Choose a reason for hiding this comment

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

This formatting is premature. We should return the date (or NULL) and then let the caller / client handle the rendering logic (i.e. formatting in a specific locale). And what I didn't realize was that we could just return NULL and allow the renderer to conditionally render the value properly. So probably don't even need the constant, definitely want to return a date and have the renderer handle the date format.

amountOfItemsWithBackdatedShipments[it[1] as String] += 1
}

Table table = new Table("Item", "Shipments", "Last Count", tableData.toList())
Copy link
Member

Choose a reason for hiding this comment

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

These need to be translatable strings. We do not need to handle that here, but we need to provide this as feedback in the ticket to make sure that Manon (at least) knows that these labels are hard-coded (along with the None label) and cannot be translated.

Copy link
Member

Choose a reason for hiding this comment

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

One way to tackle the translatable label problem is to require the ticket creator to specify multiple translations for each string at the beginning to make it clear that there's a i18n requirement.

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.

3 participants