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 }