github.com/companieshouse/lfp-pay-api@v0.0.0-20230203133422-0ca455cd79f9/service/payable_resource_test.go (about)

     1  package service
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net/http/httptest"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/companieshouse/lfp-pay-api-core/constants"
    11  	"github.com/companieshouse/lfp-pay-api-core/models"
    12  	"github.com/companieshouse/lfp-pay-api-core/validators"
    13  	"github.com/companieshouse/lfp-pay-api/config"
    14  	"github.com/companieshouse/lfp-pay-api/mocks"
    15  	"github.com/golang/mock/gomock"
    16  	"github.com/jarcoal/httpmock"
    17  	. "github.com/smartystreets/goconvey/convey"
    18  )
    19  
    20  func createMockPayableResourceService(mockDAO *mocks.MockService, cfg *config.Config) PayableResourceService {
    21  	return PayableResourceService{
    22  		DAO:    mockDAO,
    23  		Config: cfg,
    24  	}
    25  }
    26  
    27  func TestUnitGetPayableResource(t *testing.T) {
    28  	mockCtrl := gomock.NewController(t)
    29  	cfg, _ := config.Get()
    30  
    31  	Convey("Error getting payable resource from DB", t, func() {
    32  		mock := mocks.NewMockService(mockCtrl)
    33  		mockPayableService := createMockPayableResourceService(mock, cfg)
    34  		mock.EXPECT().GetPayableResource("12345678", gomock.Any()).Return(&models.PayableResourceDao{}, fmt.Errorf("error"))
    35  
    36  		req := httptest.NewRequest("Get", "/test", nil)
    37  
    38  		payableResource, status, err := mockPayableService.GetPayableResource(req, "12345678", "1234")
    39  		So(payableResource, ShouldBeNil)
    40  		So(status, ShouldEqual, Error)
    41  		So(err.Error(), ShouldEqual, "error getting payable resource from db: [error]")
    42  	})
    43  
    44  	Convey("Payable resource not found", t, func() {
    45  		mock := mocks.NewMockService(mockCtrl)
    46  		mockPayableService := createMockPayableResourceService(mock, cfg)
    47  		mock.EXPECT().GetPayableResource("12345678", "invalid").Return(nil, nil)
    48  
    49  		req := httptest.NewRequest("Get", "/test", nil)
    50  
    51  		payableResource, status, err := mockPayableService.GetPayableResource(req, "12345678", "invalid")
    52  		So(payableResource, ShouldBeNil)
    53  		So(status, ShouldEqual, NotFound)
    54  		So(err, ShouldBeNil)
    55  	})
    56  
    57  	Convey("Get Payable resource - success - Single transaction", t, func() {
    58  		mock := mocks.NewMockService(mockCtrl)
    59  		mockPayableService := createMockPayableResourceService(mock, cfg)
    60  
    61  		txs := map[string]models.TransactionDao{
    62  			"abcd": models.TransactionDao{Amount: 5},
    63  		}
    64  		t := time.Now().Truncate(time.Millisecond)
    65  		mock.EXPECT().GetPayableResource("12345678", gomock.Any()).Return(
    66  			&models.PayableResourceDao{
    67  				CompanyNumber: "12345678",
    68  				Reference:     "1234",
    69  				Data: models.PayableResourceDataDao{
    70  					Etag:      "qwertyetag1234",
    71  					CreatedAt: &t,
    72  					CreatedBy: models.CreatedByDao{
    73  						ID:       "identity",
    74  						Email:    "test@user.com",
    75  						Forename: "some",
    76  						Surname:  "body",
    77  					},
    78  					Links: models.PayableResourceLinksDao{
    79  						Self:    "/company/12345678/penalties/late-filing/payable/1234",
    80  						Payment: "/company/12345678/penalties/late-filing/payable/1234/payment",
    81  					},
    82  					Transactions: txs,
    83  					Payment: models.PaymentDao{
    84  						Status: constants.Pending.String(),
    85  						Amount: "5",
    86  					},
    87  				},
    88  			},
    89  			nil,
    90  		)
    91  
    92  		req := httptest.NewRequest("Get", "/test", nil)
    93  
    94  		httpmock.Activate()
    95  		defer httpmock.DeactivateAndReset()
    96  
    97  		payableResource, status, err := mockPayableService.GetPayableResource(req, "12345678", "1234")
    98  
    99  		So(status, ShouldEqual, Success)
   100  		So(err, ShouldBeNil)
   101  		So(payableResource.CompanyNumber, ShouldEqual, "12345678")
   102  		So(payableResource.Reference, ShouldEqual, "1234")
   103  		So(payableResource.Etag, ShouldEqual, "qwertyetag1234")
   104  		So(payableResource.CreatedAt, ShouldEqual, &t)
   105  		So(payableResource.CreatedBy.ID, ShouldEqual, "identity")
   106  		So(payableResource.CreatedBy.Email, ShouldEqual, "test@user.com")
   107  		So(payableResource.CreatedBy.Forename, ShouldEqual, "some")
   108  		So(payableResource.CreatedBy.Surname, ShouldEqual, "body")
   109  		So(payableResource.Links.Self, ShouldEqual, "/company/12345678/penalties/late-filing/payable/1234")
   110  		So(payableResource.Links.Payment, ShouldEqual, "/company/12345678/penalties/late-filing/payable/1234/payment")
   111  		So(payableResource.Payment.Amount, ShouldEqual, "5")
   112  		So(payableResource.Payment.Status, ShouldEqual, "pending")
   113  		So(len(payableResource.Transactions), ShouldEqual, 1)
   114  		So(payableResource.Transactions[0].Amount, ShouldEqual, 5)
   115  	})
   116  
   117  	Convey("Get Payable resource - success - Multiple transactions", t, func() {
   118  		mock := mocks.NewMockService(mockCtrl)
   119  		mockPayableService := createMockPayableResourceService(mock, cfg)
   120  
   121  		txs := map[string]models.TransactionDao{
   122  			"abcd": models.TransactionDao{Amount: 5},
   123  			"wxyz": models.TransactionDao{Amount: 10},
   124  		}
   125  		t := time.Now().Truncate(time.Millisecond)
   126  		mock.EXPECT().GetPayableResource("12345678", gomock.Any()).Return(
   127  			&models.PayableResourceDao{
   128  				CompanyNumber: "12345678",
   129  				Reference:     "1234",
   130  				Data: models.PayableResourceDataDao{
   131  					Etag:      "qwertyetag1234",
   132  					CreatedAt: &t,
   133  					CreatedBy: models.CreatedByDao{
   134  						ID:       "identity",
   135  						Email:    "test@user.com",
   136  						Forename: "some",
   137  						Surname:  "body",
   138  					},
   139  					Links: models.PayableResourceLinksDao{
   140  						Self:    "/company/12345678/penalties/late-filing/payable/1234",
   141  						Payment: "/company/12345678/penalties/late-filing/payable/1234/payment",
   142  					},
   143  					Transactions: txs,
   144  					Payment: models.PaymentDao{
   145  						Status:    constants.Paid.String(),
   146  						Amount:    "15",
   147  						Reference: "payref",
   148  						PaidAt:    &t,
   149  					},
   150  				},
   151  			},
   152  			nil,
   153  		)
   154  
   155  		req := httptest.NewRequest("Get", "/test", nil)
   156  
   157  		httpmock.Activate()
   158  		defer httpmock.DeactivateAndReset()
   159  
   160  		payableResource, status, err := mockPayableService.GetPayableResource(req, "12345678", "1234")
   161  
   162  		So(status, ShouldEqual, Success)
   163  		So(err, ShouldBeNil)
   164  		So(payableResource.CompanyNumber, ShouldEqual, "12345678")
   165  		So(payableResource.Reference, ShouldEqual, "1234")
   166  		So(payableResource.Etag, ShouldEqual, "qwertyetag1234")
   167  		So(payableResource.CreatedAt, ShouldEqual, &t)
   168  		So(payableResource.CreatedBy.ID, ShouldEqual, "identity")
   169  		So(payableResource.CreatedBy.Email, ShouldEqual, "test@user.com")
   170  		So(payableResource.CreatedBy.Forename, ShouldEqual, "some")
   171  		So(payableResource.CreatedBy.Surname, ShouldEqual, "body")
   172  		So(payableResource.Links.Self, ShouldEqual, "/company/12345678/penalties/late-filing/payable/1234")
   173  		So(payableResource.Links.Payment, ShouldEqual, "/company/12345678/penalties/late-filing/payable/1234/payment")
   174  		So(payableResource.Payment.Amount, ShouldEqual, "15")
   175  		So(payableResource.Payment.Status, ShouldEqual, "paid")
   176  		So(payableResource.Payment.Reference, ShouldEqual, "payref")
   177  		So(payableResource.Payment.PaidAt, ShouldEqual, &t)
   178  		So(len(payableResource.Transactions), ShouldEqual, 2)
   179  		So(payableResource.Transactions[0].Amount+payableResource.Transactions[1].Amount, ShouldEqual, 15) // array order can change - sum can't
   180  	})
   181  }
   182  
   183  func TestUnitPayableResourceService_UpdateAsPaid(t *testing.T) {
   184  	Convey("PayableResourceService.UpdateAsPaid", t, func() {
   185  		Convey("Payable resource must exist", func() {
   186  			mockCtrl := gomock.NewController(t)
   187  			defer mockCtrl.Finish()
   188  
   189  			mockDaoService := mocks.NewMockService(mockCtrl)
   190  			mockDaoService.EXPECT().GetPayableResource(gomock.Any(), gomock.Any()).Return(nil, errors.New("not found"))
   191  			svc := PayableResourceService{DAO: mockDaoService}
   192  
   193  			err := svc.UpdateAsPaid(models.PayableResource{}, validators.PaymentInformation{})
   194  
   195  			So(err, ShouldBeError, ErrLFPNotFound)
   196  		})
   197  
   198  		Convey("LFP payable resource must not have already been paid", func() {
   199  			mockCtrl := gomock.NewController(t)
   200  			defer mockCtrl.Finish()
   201  
   202  			dataModel := &models.PayableResourceDao{
   203  				Data: models.PayableResourceDataDao{
   204  					Payment: models.PaymentDao{
   205  						Status: constants.Paid.String(),
   206  					},
   207  				},
   208  			}
   209  			mockDaoService := mocks.NewMockService(mockCtrl)
   210  			mockDaoService.EXPECT().GetPayableResource(gomock.Any(), gomock.Any()).Return(dataModel, nil)
   211  			svc := PayableResourceService{DAO: mockDaoService}
   212  
   213  			err := svc.UpdateAsPaid(models.PayableResource{}, validators.PaymentInformation{Status: constants.Paid.String()})
   214  
   215  			So(err, ShouldBeError, ErrAlreadyPaid)
   216  		})
   217  
   218  		Convey("payment details are saved to db", func() {
   219  			mockCtrl := gomock.NewController(t)
   220  			defer mockCtrl.Finish()
   221  
   222  			dataModel := &models.PayableResourceDao{
   223  				Data: models.PayableResourceDataDao{
   224  					Payment: models.PaymentDao{},
   225  				},
   226  			}
   227  			mockDaoService := mocks.NewMockService(mockCtrl)
   228  			mockDaoService.EXPECT().GetPayableResource(gomock.Any(), gomock.Any()).Return(dataModel, nil)
   229  			mockDaoService.EXPECT().UpdatePaymentDetails(gomock.Any()).Times(1)
   230  			svc := PayableResourceService{DAO: mockDaoService}
   231  
   232  			layout := "2006-01-02T15:04:05.000Z"
   233  			str := "2014-11-12T11:45:26.371Z"
   234  			completedAt, _ := time.Parse(layout, str)
   235  
   236  			paymentResponse := validators.PaymentInformation{
   237  				Reference:   "123",
   238  				Amount:      "150",
   239  				Status:      "paid",
   240  				CompletedAt: completedAt,
   241  				CreatedBy:   "test@example.com",
   242  			}
   243  
   244  			err := svc.UpdateAsPaid(models.PayableResource{}, paymentResponse)
   245  
   246  			So(err, ShouldBeNil)
   247  			So(dataModel.Data.Payment.Status, ShouldEqual, paymentResponse.Status)
   248  			So(dataModel.Data.Payment.PaidAt, ShouldNotBeNil)
   249  			So(dataModel.Data.Payment.Amount, ShouldEqual, paymentResponse.Amount)
   250  			So(dataModel.Data.Payment.Reference, ShouldEqual, paymentResponse.Reference)
   251  		})
   252  	})
   253  }