diff --git a/api/src/main/java/org/openmrs/module/billing/api/db/hibernate/ImmutableBillInterceptor.java b/api/src/main/java/org/openmrs/module/billing/api/db/hibernate/ImmutableBillInterceptor.java
index 8360cbff..ead9950d 100644
--- a/api/src/main/java/org/openmrs/module/billing/api/db/hibernate/ImmutableBillInterceptor.java
+++ b/api/src/main/java/org/openmrs/module/billing/api/db/hibernate/ImmutableBillInterceptor.java
@@ -29,7 +29,8 @@ public class ImmutableBillInterceptor extends ImmutableEntityInterceptor {
private static final String[] MUTABLE_PROPERTY_NAMES = new String[] { "changedBy", "dateChanged", "voided", "dateVoided",
"voidedBy", "voidReason", "payment", "billAdjusted", "adjustmentReason", "adjustedBy", "receiptPrinted",
- "status", "receiptNumber" };
+ "status", "receiptNumber", "refundReason", "refundRequestedBy", "dateRefundRequested", "refundApprovedBy",
+ "dateRefundApproved" };
@Override
protected Class> getSupportedType() {
diff --git a/api/src/main/java/org/openmrs/module/billing/api/model/Bill.java b/api/src/main/java/org/openmrs/module/billing/api/model/Bill.java
index bf65b11b..81785af2 100644
--- a/api/src/main/java/org/openmrs/module/billing/api/model/Bill.java
+++ b/api/src/main/java/org/openmrs/module/billing/api/model/Bill.java
@@ -16,6 +16,7 @@
import java.math.BigDecimal;
import java.security.AccessControlException;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -25,6 +26,7 @@
import org.openmrs.BaseOpenmrsData;
import org.openmrs.Patient;
import org.openmrs.Provider;
+import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.module.billing.api.util.PrivilegeConstants;
import org.openmrs.module.stockmanagement.api.model.StockItem;
@@ -63,6 +65,16 @@ public class Bill extends BaseOpenmrsData {
private String adjustmentReason;
+ private String refundReason;
+
+ private User refundRequestedBy;
+
+ private Date dateRefundRequested;
+
+ private User refundApprovedBy;
+
+ private Date dateRefundApproved;
+
public BigDecimal getTotal() {
BigDecimal total = BigDecimal.ZERO;
@@ -169,6 +181,9 @@ public void addPayment(Payment payment) {
}
public void synchronizeBillStatus() {
+ if (this.status == BillStatus.REFUND_REQUESTED || this.status == BillStatus.REFUNDED) {
+ return;
+ }
if (!this.getPayments().isEmpty() && getTotalPayments().compareTo(BigDecimal.ZERO) > 0) {
boolean billFullySettled = getTotalPayments().compareTo(getTotal()) >= 0;
if (billFullySettled) {
diff --git a/api/src/main/java/org/openmrs/module/billing/api/model/BillStatus.java b/api/src/main/java/org/openmrs/module/billing/api/model/BillStatus.java
index 29e17d2e..a8215321 100644
--- a/api/src/main/java/org/openmrs/module/billing/api/model/BillStatus.java
+++ b/api/src/main/java/org/openmrs/module/billing/api/model/BillStatus.java
@@ -23,7 +23,9 @@ public enum BillStatus {
PAID(),
CANCELLED(),
ADJUSTED(),
- EXEMPTED();
+ EXEMPTED(),
+ REFUND_REQUESTED(),
+ REFUNDED();
BillStatus() {
}
diff --git a/api/src/main/resources/Bill.hbm.xml b/api/src/main/resources/Bill.hbm.xml
index dd88092c..de03d6a0 100644
--- a/api/src/main/resources/Bill.hbm.xml
+++ b/api/src/main/resources/Bill.hbm.xml
@@ -139,6 +139,12 @@
+
+
+
+
+
diff --git a/api/src/test/java/org/openmrs/module/billing/api/model/BillTest.java b/api/src/test/java/org/openmrs/module/billing/api/model/BillTest.java
index 17a1240a..06e53428 100644
--- a/api/src/test/java/org/openmrs/module/billing/api/model/BillTest.java
+++ b/api/src/test/java/org/openmrs/module/billing/api/model/BillTest.java
@@ -218,6 +218,52 @@ public void synchronizeBillStatus_shouldUpdateAllNonVoidedLineItemsToPaidWhenBil
assertNull(voidedLineItem.getPaymentStatus());
}
+ @Test
+ public void synchronizeBillStatus_shouldNotOverwriteRefundRequestedStatus() {
+ Bill bill = new Bill();
+ bill.setLineItems(new ArrayList<>());
+ bill.setPayments(new HashSet<>());
+ bill.setStatus(BillStatus.REFUND_REQUESTED);
+
+ BillLineItem lineItem = new BillLineItem();
+ lineItem.setPrice(BigDecimal.valueOf(100));
+ lineItem.setQuantity(1);
+ lineItem.setVoided(false);
+ bill.getLineItems().add(lineItem);
+
+ Payment payment = new Payment();
+ payment.setAmountTendered(BigDecimal.valueOf(100));
+ payment.setVoided(false);
+ bill.getPayments().add(payment);
+
+ bill.synchronizeBillStatus();
+
+ assertEquals(BillStatus.REFUND_REQUESTED, bill.getStatus());
+ }
+
+ @Test
+ public void synchronizeBillStatus_shouldNotOverwriteRefundedStatus() {
+ Bill bill = new Bill();
+ bill.setLineItems(new ArrayList<>());
+ bill.setPayments(new HashSet<>());
+ bill.setStatus(BillStatus.REFUNDED);
+
+ BillLineItem lineItem = new BillLineItem();
+ lineItem.setPrice(BigDecimal.valueOf(100));
+ lineItem.setQuantity(1);
+ lineItem.setVoided(false);
+ bill.getLineItems().add(lineItem);
+
+ Payment payment = new Payment();
+ payment.setAmountTendered(BigDecimal.valueOf(100));
+ payment.setVoided(false);
+ bill.getPayments().add(payment);
+
+ bill.synchronizeBillStatus();
+
+ assertEquals(BillStatus.REFUNDED, bill.getStatus());
+ }
+
@Test
public void setLineItems_shouldAllowSettingLineItemsOnNewBill() {
Bill bill = new Bill();
diff --git a/omod/src/main/java/org/openmrs/module/billing/web/rest/resource/BillResource.java b/omod/src/main/java/org/openmrs/module/billing/web/rest/resource/BillResource.java
index df393725..c1e2ff3f 100644
--- a/omod/src/main/java/org/openmrs/module/billing/web/rest/resource/BillResource.java
+++ b/omod/src/main/java/org/openmrs/module/billing/web/rest/resource/BillResource.java
@@ -13,7 +13,9 @@
*/
package org.openmrs.module.billing.web.rest.resource;
+import java.security.AccessControlException;
import java.util.ArrayList;
+import java.util.Date;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -35,6 +37,7 @@
import org.openmrs.module.billing.api.model.BillLineItem;
import org.openmrs.module.billing.api.model.BillStatus;
import org.openmrs.module.billing.api.model.CashPoint;
+import org.openmrs.module.billing.api.util.PrivilegeConstants;
import org.openmrs.module.billing.api.model.Payment;
import org.openmrs.module.billing.api.model.Timesheet;
import org.openmrs.module.billing.api.search.BillSearch;
@@ -77,6 +80,11 @@ public DelegatingResourceDescription getRepresentationDescription(Representation
description.addProperty("receiptNumber");
description.addProperty("status");
description.addProperty("adjustmentReason");
+ description.addProperty("refundReason");
+ description.addProperty("refundRequestedBy", Representation.REF);
+ description.addProperty("dateRefundRequested");
+ description.addProperty("refundApprovedBy", Representation.REF);
+ description.addProperty("dateRefundApproved");
description.addProperty("uuid");
return description;
}
@@ -122,6 +130,22 @@ public void setBillStatus(Bill instance, BillStatus status) {
instance.setStatus(status);
} else if (instance.getStatus() == BillStatus.PENDING && status == BillStatus.POSTED) {
instance.setStatus(status);
+ } else if (instance.getStatus() == BillStatus.PAID && status == BillStatus.REFUND_REQUESTED) {
+ instance.setRefundRequestedBy(Context.getAuthenticatedUser());
+ instance.setDateRefundRequested(new Date());
+ instance.setStatus(status);
+ } else if (instance.getStatus() == BillStatus.REFUND_REQUESTED && status == BillStatus.REFUNDED) {
+ if (!Context.hasPrivilege(PrivilegeConstants.REFUND_MONEY)) {
+ throw new AccessControlException("Access denied to issue refund.");
+ }
+ instance.setRefundApprovedBy(Context.getAuthenticatedUser());
+ instance.setDateRefundApproved(new Date());
+ instance.setStatus(status);
+ } else if (instance.getStatus() == BillStatus.REFUND_REQUESTED && status == BillStatus.PAID) {
+ if (!Context.hasPrivilege(PrivilegeConstants.REFUND_MONEY)) {
+ throw new AccessControlException("Access denied to reject refund request.");
+ }
+ instance.setStatus(status);
}
if (status == BillStatus.POSTED) {
RoundingUtil.handleRoundingLineItem(instance);
diff --git a/omod/src/main/resources/liquibase.xml b/omod/src/main/resources/liquibase.xml
index 118d17c3..582840d0 100644
--- a/omod/src/main/resources/liquibase.xml
+++ b/omod/src/main/resources/liquibase.xml
@@ -1095,4 +1095,34 @@
baseTableName="bill_exemption_rule" baseColumnNames="voided_by"
referencedTableName="users" referencedColumnNames="user_id"/>
+
+
+ Widen status columns for REFUND_REQUESTED and add refund audit fields to cashier_bill
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file