diff --git a/ehr_billing/api-src/org/labkey/api/ehr_billing/pipeline/InvoicedItemsProcessingService.java b/ehr_billing/api-src/org/labkey/api/ehr_billing/pipeline/InvoicedItemsProcessingService.java index 29d3d1648..d13cadd47 100644 --- a/ehr_billing/api-src/org/labkey/api/ehr_billing/pipeline/InvoicedItemsProcessingService.java +++ b/ehr_billing/api-src/org/labkey/api/ehr_billing/pipeline/InvoicedItemsProcessingService.java @@ -22,32 +22,45 @@ import org.labkey.api.data.SimpleFilter; import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; +import org.labkey.api.module.Module; import org.labkey.api.pipeline.PipelineJobException; import org.labkey.api.query.FieldKey; import org.labkey.api.query.QueryService; import org.labkey.api.security.User; -import org.labkey.api.services.ServiceRegistry; import org.labkey.api.util.Pair; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; /** * Service to get a list of queries to be processed during a Billing Run. The listing is a collection of * BillingPipelineJobProcess objects that define what schema.query to execute and the mapping from that query's * columns to the ehr_billing.invoicedItem table's columns. * Additionally, get center specific generated invoice number. - * - * Currently registered server wide but should allow multiple co-existing services and resolve per container's active modules */ public interface InvoicedItemsProcessingService { + record Registration(String moduleName, InvoicedItemsProcessingService impl){} + + List REGISTRATION_LIST = new CopyOnWriteArrayList<>(); + + static void register(Module module, InvoicedItemsProcessingService impl) + { + REGISTRATION_LIST.add(new Registration(module.getName(), impl)); + } + @Nullable - static InvoicedItemsProcessingService get() + static InvoicedItemsProcessingService get(Container c) { - return ServiceRegistry.get().getService(InvoicedItemsProcessingService.class); + // Return the service implementation based on the registering module being active in the provided container + return REGISTRATION_LIST.stream() + .filter(reg -> c.hasActiveModuleByName(reg.moduleName())) + .map(Registration::impl) + .findFirst() + .orElse(null); } /** @return the inputs to the billing process that are capable of generating charges */ diff --git a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java index abacf8776..345c12252 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java +++ b/ehr_billing/src/org/labkey/ehr_billing/EHR_BillingController.java @@ -104,7 +104,7 @@ public ApiResponse execute(BillingPipelineForm form, BindException errors) throw new PipelineJobException("Cannot create a billing run with the same start and end date"); } - InvoicedItemsProcessingService processingService = InvoicedItemsProcessingService.get(); + InvoicedItemsProcessingService processingService = InvoicedItemsProcessingService.get(getContainer()); if (null != processingService) { Pair previousInvoice = processingService.verifyBillingRunPeriod(getUser(), getContainer(), form.getStartDate(), form.getEndDate()); diff --git a/ehr_billing/src/org/labkey/ehr_billing/pipeline/BillingTask.java b/ehr_billing/src/org/labkey/ehr_billing/pipeline/BillingTask.java index 908b09837..4e44bf8d5 100644 --- a/ehr_billing/src/org/labkey/ehr_billing/pipeline/BillingTask.java +++ b/ehr_billing/src/org/labkey/ehr_billing/pipeline/BillingTask.java @@ -78,11 +78,13 @@ public class BillingTask extends PipelineJob.Task { private final static DbSchema EHR_BILLING_SCHEMA = EHR_BillingSchema.getInstance().getSchema(); - private final static InvoicedItemsProcessingService processingService = InvoicedItemsProcessingService.get(); + + private final InvoicedItemsProcessingService _processingService; protected BillingTask(Factory factory, PipelineJob job) { super(factory, job); + _processingService = InvoicedItemsProcessingService.get(EHR_BillingManager.get().getBillingContainer(job.getContainer())); } public static class Factory extends AbstractTaskFactory @@ -148,16 +150,16 @@ public RecordedActionSet run() throws PipelineJobException { getOrCreateInvoiceRunRecord(); loadTransactionNumber(); - processingService.setBillingStartDate(getSupport().getStartDate()); + _processingService.setBillingStartDate(getSupport().getStartDate()); if (null != _previousInvoice) { - processingService.processBillingRerun(_invoiceId, _invoiceRowId, getSupport().getStartDate(), getSupport().getEndDate(), getNextTransactionNumber(), user, billingContainer, getJob().getLogger()); + _processingService.processBillingRerun(_invoiceId, _invoiceRowId, getSupport().getStartDate(), getSupport().getEndDate(), getNextTransactionNumber(), user, billingContainer, getJob().getLogger()); } else { - for (BillingPipelineJobProcess process : processingService.getProcessList()) + for (BillingPipelineJobProcess process : _processingService.getProcessList()) { Container billingRunContainer = process.isUseEHRContainer() ? ehrContainer : billingContainer; runProcessing(process, billingRunContainer); @@ -166,7 +168,7 @@ public RecordedActionSet run() throws PipelineJobException updateInvoiceTable(billingContainer); - processingService.performAdditionalProcessing(_invoiceId, user, container); + _processingService.performAdditionalProcessing(_invoiceId, user, container); transaction.commit(); } @@ -278,7 +280,7 @@ private String getOrCreateInvoiceRunRecord() throws PipelineJobException @Nullable private String getOrCreateInvoiceRecord(Map row, Date endDate) throws PipelineJobException { - String invoiceNumber = processingService.getInvoiceNum(row, endDate); + String invoiceNumber = _processingService.getInvoiceNum(row, endDate); if (null != invoiceNumber) { try @@ -499,25 +501,25 @@ private void runProcessing(BillingPipelineJobProcess process, Container billingR // get cost Double unitCost = ci.getUnitCost(); - procedureRow.put(processingService.getUnitCostColName(), unitCost); + procedureRow.put(_processingService.getUnitCostColName(), unitCost); // total cost Double totalCost = unitCost * (Double) procedureRow.get("quantity"); - procedureRow.put(processingService.getTotalCostColName(), totalCost); + procedureRow.put(_processingService.getTotalCostColName(), totalCost); // calculate total cost with additional/other rate (ex. tier rate for WNPRC) Double otherRate = (Double) procedureRow.get("otherRate"); Double unitCostWithOtherRate; double totalCostWithOtherRate; if (null != otherRate && - null != processingService.getAdditionalUnitCostColName() && - null != processingService.getAdditionalTotalCostColName()) + null != _processingService.getAdditionalUnitCostColName() && + null != _processingService.getAdditionalTotalCostColName()) { unitCostWithOtherRate = unitCost + (unitCost * otherRate); - procedureRow.put(processingService.getAdditionalUnitCostColName(), unitCostWithOtherRate); + procedureRow.put(_processingService.getAdditionalUnitCostColName(), unitCostWithOtherRate); totalCostWithOtherRate = unitCostWithOtherRate * (Double) procedureRow.get("quantity"); - procedureRow.put(processingService.getAdditionalTotalCostColName(), totalCostWithOtherRate); + procedureRow.put(_processingService.getAdditionalTotalCostColName(), totalCostWithOtherRate); } } writeToInvoicedItems(process, procedureRows, getSupport());