Archive product

Archive Product

The main purpose of this article is to share the requirement that our team is doing to the community. If you have the same needs or have any questions, please contact us。

Business design

Due to the requirement of Siglus, we developed a new feature called “Archive”, which allows users to archive products that are not in use in recent work. For the web portal, this feature involves multiple existing features and pages, it also needs to build several new pages.

For the process of archiving a product, users need to follow this process:

So the first step is to go to the SOH page and select a product which SOH=0, then go to the product stock card page (not the “lot”) by-product, which means view the product general information, not the lot information, as the picture shows below.

In the stock card page, the user can see a red button called “Archive”. When the user clicks this button, he will see a confirmation pop-up to confirm his action (see picture below).

After archiving a product, the product will not be shown on stock management and it will not influence the new R&R report. Meanwhile, after a product is archived, it will be put into an independent place (archived product page), as the picture shows below:

There are some constraints about this feature:

  • User can only archive a product, rather than a LOT;
  • User can only archive a product with SOH=0;
  • User can NOT archive a product in kit;
  • Archive movement will NOT be saved as a movement history in stock card;
  • Archive action will affect the inventory of the product in my facility;
  • Archive action will NOT affect submitted R&Rs;
  • Archive action will NOT affect historical R&Rs;
  • Once a product is archived, all movement records of the product should also be archived. Once the user chooses to activate an archived product, the original lot information and the historical movements should be available when the product is activated.

Technical design

Frontend:

In order to archive the product, we added an archived button on the stock card page. The product can only be archived when:

  • this product is available and
  • the user is stock card page of this product and
  • the SOH of this product is 0 and
  • the product does not belong to any kit.

We add a method named archive in the StockCardController, which is called when the user clicked the archive button and this method will show a confirmation pop-up. When the user clicks “cancel” button, he will stay in the stock card page; and when the user clicks “archive” button, the system will call the archive product api (/api/siglusapi/archivedproducts/{orderableId}/archive) to archive this product. If the status of the response is 200, it will jump to the first page of the archived product list page with the product’s program and get a notification of archive product success. Otherwise, it will stay in the original page and get a notification of archive product failure.


In the state of the openlmis.stockmanagement.stockCardSummaries, we set a query param excludeArchived of the stock card summaries api (/api/siglusintegration/stockCardSummaries) as true to get the stock cards which are not archived.

We added a new route state openlmis.stockmanagement.archivedProductSummaries to show the archived product list. The label of this state is ‘Archived Products’, and it will show as a sub-menu in the stockmanagement menu. We added a flag isArchivedProducts in this state’s params, which is used in the StockCardSummaryListController. This route reuses the stock card summary list page rather than writing a new one.

In the state of the openlmis.stockmanagement.archivedProductSummaries, we set a query param archivedOnly of the stock card summaries api (/api/siglusintegration/stockCardSummaries) as true to get the archived stock cards.

In the StockCardSummaryListController, it will load different stock card resources according to the flag isArchivedProducts. The viewSingleCard method and the viewProductStockCard method in this controller also will go through different route states according to this flag.

Backend:

We add a new field “archived” to table “stock_card_extension” in our new service “siglus-api” to mark whether it has been archived or not.

ALTER TABLE siglusintegration.stock_card_extension ADD COLUMN archived boolean NOT NULL DEFAULT FALSE;

Add a new api to archive product, modify the field “archived” in database to true, delete archived item in physical inventory draft, stock management draft and “INITIATED” requisition.

SiglusArchiveProductController.java

SiglusArchiveProductService.java

Modify the “stockCards” detail api to tell front-end whether the product belongs to kit or not, because products belong to kit cannot be archived.

SiglusStockCardService.java

And modify the “stockCardSummaries” api to support exclude archived products, so users cannot see archived products in the “Stock on Hand” page.

SiglusStockCardSummariesService.java

Modify the “requisition initiate” api to support exclude archived products, so users cannot see archived products when creating a new requisition.

RequisitionService.java

Activate Product

Business design

When a user needs to use the archived products again, he can choose to activate the products manually from the archived products list. The process and related pages are shown below:

By activating the product, user needs to go to “Archived Product” first and click view to the stock card detail page.

In the stock card detail page, the user can see the “activate” button. By clicking this button, the user needs to confirm his action in the confirmation pop-up. After the “activate” process is successful, the system will jump to the SOH page.

There are other situations where the system can activate products automatically.

  • Receive archived products;
  • Make an adjustment of archived products;
  • Do a physical inventory that includes archived products
  • Add archived products in the R & R page and submit.

When a user adds archived products in these scenarios, he will see a pop-up reminder (see picture below); and when the user finishes these actions, archived products will be automatically activated and added back to SOH.

Technical design

Frontend:

We added a new route state “openlmis.stockmanagement.archivedProductSummaries.singleCard” to show the archived product detail page. The definition of this state is almost the same with the state of the stock card detail page, and it reuses the stock card detail page.

On the archived product detail page, we add an activate button to activate the archived products, it only can be shown in the stock card page of archived products.

In the “StockCardController”, we added a method named “activate” which is called when the user clicks “activate” button. It will display a confirmation pop-up, which is similar with the “archive” mentioned above. If the user clicked the activate button, it will call the activate product api (/api/siglusapi/archivedproducts/{orderableId}/ activate) to activate this product. If the product activation is successful, it will jump to the first page of SOH with the product’s program and get a notification about the activate product success. Otherwise, it will stay in the original page and get a notification of activate product failure.

In physical inventory, issue, adjustment and requisition page, when the user adds the archived product, the system will automatically activate the archived product when the user submit the requisition or the movement.

In requisition page, front-end will request the archived products api (/api/siglusapi/archivedproducts) by the id of the current user’s facility to the ids of the archived products by the “getArchivedOrderables” method in the “archivedProductService”. After that it will set the archived field of orderable as true if the archived product ids contain the current orderable’s id, otherwise set as false.

In the “SelectProductsModalController”, it will sort the orderables by the archived field of orderable, so the archived orderable will be displayed at the bottom of the selection drop-up. And in the html of the select product model, it will add the prefix ‘[archived]’ if the orderable is archived.

In the stock management page, front-end adds a filter “archivedProductName” to add the ‘[archived]’ prefix if the orderable is archived. It will also sort the orderables by archived field.

Front-end adds some logic about archived products in the add product of the stock management. If the added product is archived, it will call the info method in the “archivedProductService” and get an alert about this product that it will be activated automatically.

Backend:

Add a new api to activate product, modify the field “archived” in the database to false.

SiglusArchiveProductController.java

SiglusArchiveProductService.java

Modify the “stockCardSummaries” api to support only return archived products, so user can see archived products in our new page “Archived Products”.

SiglusStockCardSummariesService.java

Modify the “stockEvents”, “requisition submit”, “requisition authorize” apis to support automatically activate added archived products.

SiglusStockEventsService.java

SiglusRequisitionController.java

Hi @jingzhao, thank you for sharing this, I’d imagine this capability could be useful to others. A quick question though, are you wanting to making a functional contribution to OpenLMIS? Open to feedback? Wanting to participate in a code-review?

Curious if you have the time and inclination to work through it with the team.

Best,
Josh

Hey @jingzhao, thanks for bringing this to the attention of the community. Some questions:

  • Can you explain if this new logic is in a new microservice, or if some of the logic is actually modifying some of the Core microservices? It seems like a new microservice, but I see code for RequisitionService, which makes me think that the requisition microservice will be modified.
  • I am a bit confused, is this “archive product” actually archiving a stock card (a product at a certain facility), or a product (a product at all facilities in the system)? It is not quite clear to me.
  • Can you explain the purpose for archiving a product? Is it to exclude it from the list of stock cards in stock management, and also new R&Rs? How is this different from how FTAPs (facility type approved products) are used in the system?
  • Can you show us the API design for the archived products feature? From what I can tell here, it does not seem very REST-ful.

This is quite in-depth, but it may be a bit much to digest. Perhaps if we want to review the actual code, we can open a code review?

Shalom,
Chongsun

Hi @joshzamor, thanks for your reply, Our purpose is to contribute our code to the community. However, due to project progress issues, we only can provide our code and answer the question about the feature of the community. The community can also directly view our code.

Hey @Chongsun_Ahn, thanks for your reply

  • Regarding new microservices, we will start another article describing the overall design of our new service.
  • Regarding the archive problem, our team will introduce it in more detail later.
  • If you want to review the code of our new service, you can directly review https://github.com/SIGLUS/siglus-api

Thanks @jingzhao, that’s good to know. OpenLMIS’ Contribution Guide doesn’t have a section for a contribution of code that’s not in the OpenLMIS GitHub, however the community certainly appreciates your work. We’d love to hear more, and if things change and you and your team are able to resource a contribution of code that would be very much appreciated.

Best,
Josh

Hey, @Chongsun_Ahn Thanks for your feedback. Here are the answers to your questions:

  1. please refer to this document Extensions OpenLMIS in our project

  2. The “archive” feature actually only affects the current facility, not all the facilities in the system, which means the archived products only affect users in their home facility, other facilities will not be affected. For example, user A and user B are in the same facility-1, user C is in facility-2. So when user A archives a product-A1, all users of facility-1 will be affected when they want to do some actions to this product-A1. But user C has nothing to do with it because they are in different facilities.

  3. The purpose of this feature is to let users better manage products that are temporarily or permanently useless to users of this facility. For example, a product has not been in demand for a long time; I have better alternatives for a product; the high level told me that this product will not be issued to me anymore, etc… And the archived products will be removed from SOH along with the stock cards. This will affect the related drafts in requisition & Stock Management that contain archived products, so these drafts will be updated (delete archived products from drafts). But the “archive” action will not be recorded as a movement history in the product stock card.

Also, you will not find the archived products in the new R&R. For example, if product A will not be used for some time in the future, there is no need to let product A still in the SOH, it can be archived for better managing stock information. And if you have product A in a requisition draft, then after archiving, product A will disappear from the draft and you will not see it the next time you go into the draft. Also, the “archive” has nothing to do with FTAPs, the user can archive any product in his home facility when the product’s SOH is 0.

  1. API list:
    description: archive product