Skip to content

Commit

Permalink
Merge pull request #237 from companieshouse/feature/bi-12802/refund_r…
Browse files Browse the repository at this point in the history
…etry

Remove refund-reconciliation-failed status
  • Loading branch information
emead authored Apr 25, 2023
2 parents f652868 + 80b799b commit 77b1201
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 43 deletions.
2 changes: 1 addition & 1 deletion dao/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type DAO interface {
GetPaymentsWithRefundPendingStatus() ([]models.PaymentResourceDB, error)
GetPaymentRefunds(string) ([]models.RefundResourceDB, error)
PatchRefundSuccessStatus(id string, isPaid bool, paymentUpdate *models.PaymentResourceDB) (models.PaymentResourceDB, error)
PatchRefundReconciliationFailedStatus(id string, paymentUpdate *models.PaymentResourceDB) (models.PaymentResourceDB, error)
PatchRefundStatus(id string, isRefunded bool, isFailed bool, refundStatus string, paymentUpdate *models.PaymentResourceDB) (models.PaymentResourceDB, error)
IncrementRefundAttempts(paymentID string, paymentUpdate *models.PaymentResourceDB) error
}

// NewDAO will create a new instance of the DAO interface.
Expand Down
29 changes: 14 additions & 15 deletions dao/mock_dao.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 25 additions & 5 deletions dao/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,6 @@ func (m *MongoService) PatchRefundSuccessStatus(id string, isRefunded bool, paym
return m.PatchRefundStatus(id, isRefunded, false, "refund-success", paymentUpdate)
}

// PatchRefundReconciliationFailedStatus updates payment refunds status to refund-reconciliation-failed
func (m *MongoService) PatchRefundReconciliationFailedStatus(id string, paymentUpdate *models.PaymentResourceDB) (models.PaymentResourceDB, error) {
return m.PatchRefundStatus(id, false, true, "refund-reconciliation-failed", paymentUpdate)
}

// PatchRefundStatus updates payment refunds status and inserts a new refunded_at
func (m *MongoService) PatchRefundStatus(id string, isRefunded bool, isFailed bool, refundStatus string, paymentUpdate *models.PaymentResourceDB) (models.PaymentResourceDB, error) {
collection := m.db.Collection(m.CollectionName)
Expand Down Expand Up @@ -441,3 +436,28 @@ func (m *MongoService) PatchRefundStatus(id string, isRefunded bool, isFailed bo

return updatedPayment, nil
}

// IncrementRefundAttempts increments the attempt counter for a refund
func (m *MongoService) IncrementRefundAttempts(paymentID string, paymentUpdate *models.PaymentResourceDB) error {
collection := m.db.Collection(m.CollectionName)
refunds := paymentUpdate.Refunds[0]
attempts := refunds.Attempts + 1

refundsFilter := options.ArrayFilters{Filters: bson.A{bson.M{"x.refund_id": refunds.RefundId}}}
upsert := true

opts := options.FindOneAndUpdateOptions{
ArrayFilters: &refundsFilter,
Upsert: &upsert,
}

patchUpdate := bson.M{
"$set": bson.M{
"refunds.$[x].attempts": attempts,
},
}

result := collection.FindOneAndUpdate(context.Background(), bson.M{"_id": paymentID}, patchUpdate, &opts)

return result.Err()
}
32 changes: 32 additions & 0 deletions dao/mongo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,35 @@ func TestUnitGetPaymentRefunds(t *testing.T) {
So(err.Error(), ShouldEqual, "the Find operation must have a Deployment set before Execute can be called")
})
}

func TestUnitIncrementRefundAttempts(t *testing.T) {
Convey("Increment refund attempts", t, func() {
cfg, _ := config.Get()
client = &mongo.Client{}
dao := NewDAO(cfg)

refundData := models.RefundResourceDB{
RefundId: "sasaswewq23wsw",
CreatedAt: "2020-11-19T12:57:30.Z06Z",
Amount: 800.0,
Status: "pending",
ExternalRefundUrl: "https://pulicapi.payments.service.gov.uk",
}
refundDatas := []models.RefundResourceDB{refundData}

resource := models.PaymentResourceDB{
Data: models.PaymentResourceDataDB{
PaymentMethod: "credit-card",
Status: "pending",
CompletedAt: time.Now(),
ProviderID: "id123",
},
ExternalPaymentStatusURI: "companieshouse.gov.uk",
ExternalPaymentStatusID: "id123",
ExternalPaymentTransactionID: "id456",
Refunds: refundDatas,
}
err := dao.IncrementRefundAttempts("id123", &resource)
So(err.Error(), ShouldEqual, "the FindAndModify operation must have a Deployment set before Execute can be called")
})
}
36 changes: 16 additions & 20 deletions service/refund.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ import (
)

const (
RefundPending = "pending"
RefundUnavailable = "unavailable"
RefundAvailable = "available"
RefundFull = "full"
RefundsStatusSuccess = "success"
RefundsStatusSubmitted = "submitted"
RefundsStatusError = "error"
PaymentMethodCreditCard = "credit-card"
PaymentMethodPayPal = "PayPal"
RefundPending = "pending"
RefundUnavailable = "unavailable"
RefundAvailable = "available"
RefundFull = "full"
RefundsStatusSuccess = "success"
RefundsStatusSubmitted = "submitted"
RefundsStatusError = "error"
PaymentMethodCreditCard = "credit-card"
PaymentMethodPayPal = "PayPal"
ErrorIncrementingAttempts = "error incrementing attempts in DB: [%w]"
)

// BulkRefundStatus Enum Type
Expand Down Expand Up @@ -521,18 +522,18 @@ func (service *RefundService) checkGovPayAndUpdateRefundStatus(req *http.Request

if err != nil {
log.ErrorR(req, fmt.Errorf("error getting payment resource ID [%s]: [%w]", x.ID, err))
_, err := service.DAO.PatchRefundReconciliationFailedStatus(x.ID, &x)
err := service.DAO.IncrementRefundAttempts(x.ID, &x)
if err != nil {
log.ErrorR(req, fmt.Errorf("error storing status to DB: [%w]", err))
log.ErrorR(req, fmt.Errorf(ErrorIncrementingAttempts, err))
}
continue
}

if response == NotFound {
log.ErrorR(req, fmt.Errorf("not found error from payment service session with payment ID:[%s]", x.ID))
_, err := service.DAO.PatchRefundReconciliationFailedStatus(x.ID, &x)
err := service.DAO.IncrementRefundAttempts(x.ID, &x)
if err != nil {
log.ErrorR(req, fmt.Errorf("error storing status to DB: [%w]", err))
log.ErrorR(req, fmt.Errorf(ErrorIncrementingAttempts, err))
}
continue
}
Expand All @@ -541,9 +542,9 @@ func (service *RefundService) checkGovPayAndUpdateRefundStatus(req *http.Request

if err != nil {
log.ErrorR(req, fmt.Errorf("error getting refund status for ID [%s] [%w]", refund.RefundId, err))
_, err := service.DAO.PatchRefundReconciliationFailedStatus(x.ID, &x)
err := service.DAO.IncrementRefundAttempts(x.ID, &x)
if err != nil {
log.ErrorR(req, fmt.Errorf("error storing status to DB: [%w]", err))
log.ErrorR(req, fmt.Errorf(ErrorIncrementingAttempts, err))
}
continue
}
Expand All @@ -561,11 +562,6 @@ func (service *RefundService) checkGovPayAndUpdateRefundStatus(req *http.Request
}
} else {
log.ErrorR(req, fmt.Errorf("no refund found with payment Id: [%s]", x.ID))
_, err := service.DAO.PatchRefundReconciliationFailedStatus(x.ID, &x)
if err != nil {
log.ErrorR(req, fmt.Errorf("error storing status to DB: [%w]", err))
}
continue
}
}

Expand Down
4 changes: 2 additions & 2 deletions service/refund_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ func TestUnitProcessPendingRefunds(t *testing.T) {

Convey("No payments with paid status found in DB", t, func() {
mockDao.EXPECT().GetPaymentsWithRefundPendingStatus().Return([]models.PaymentResourceDB{}, nil)
mockDao.EXPECT().PatchRefundReconciliationFailedStatus(gomock.Any(), gomock.Any()).Return(models.PaymentResourceDB{}, nil)
mockDao.EXPECT().IncrementRefundAttempts(gomock.Any(), gomock.Any()).Return(nil)

_, Success, errs := service.ProcessPendingRefunds(req)

Expand Down Expand Up @@ -1364,7 +1364,7 @@ func TestUnitCheckGovPayAndUpdateRefundStatus(t *testing.T) {
Convey("Process pending refunds payments status with payments", t, func() {
paymentsPaidDatas = append(paymentsPaidDatas, paymentsPaidData)
mockDao.EXPECT().GetPaymentResource(gomock.Any()).Return(&paymentsPaidData, nil)
mockDao.EXPECT().PatchRefundReconciliationFailedStatus(gomock.Any(), gomock.Any()).Return(models.PaymentResourceDB{}, nil).AnyTimes()
mockDao.EXPECT().IncrementRefundAttempts(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()

updatedPayments := service.checkGovPayAndUpdateRefundStatus(req, paymentsPaidDatas)
So(len(updatedPayments), ShouldBeZeroValue)
Expand Down

0 comments on commit 77b1201

Please sign in to comment.