github.com/companieshouse/insolvency-api@v0.0.0-20231024103413-440c973d9e9b/service/insolvency_service_test.go (about) 1 package service 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 "github.com/companieshouse/insolvency-api/constants" 11 "github.com/companieshouse/insolvency-api/mocks" 12 "github.com/companieshouse/insolvency-api/models" 13 "github.com/golang/mock/gomock" 14 "github.com/jarcoal/httpmock" 15 . "github.com/smartystreets/goconvey/convey" 16 "go.mongodb.org/mongo-driver/bson/primitive" 17 ) 18 19 var transactionID = "12345678" 20 var companyNumber = "01234567" 21 var companyName = "companyName" 22 var req = httptest.NewRequest(http.MethodPut, "/test", nil) 23 24 func createInsolvencyResource() models.InsolvencyResourceDao { 25 return models.InsolvencyResourceDao{ 26 ID: primitive.ObjectID{}, 27 TransactionID: transactionID, 28 Etag: "etag1234", 29 Kind: "insolvency", 30 Data: models.InsolvencyResourceDaoData{ 31 CompanyNumber: companyNumber, 32 CompanyName: companyName, 33 CaseType: "insolvency", 34 Practitioners: []models.PractitionerResourceDao{ 35 { 36 ID: "1234", 37 IPCode: "1234", 38 FirstName: "Name", 39 LastName: "LastName", 40 TelephoneNumber: "1234", 41 Email: "name@email.com", 42 Address: models.AddressResourceDao{}, 43 Role: "final-liquidator", 44 Links: models.PractitionerResourceLinksDao{}, 45 Appointment: &models.AppointmentResourceDao{ 46 AppointedOn: "2021-07-07", 47 MadeBy: "creditors", 48 }, 49 }, 50 { 51 ID: "5678", 52 IPCode: "5678", 53 FirstName: "FirstName", 54 LastName: "LastName", 55 TelephoneNumber: "5678", 56 Email: "firstname@email.com", 57 Address: models.AddressResourceDao{}, 58 Role: "final-liquidator", 59 Links: models.PractitionerResourceLinksDao{}, 60 Appointment: &models.AppointmentResourceDao{ 61 AppointedOn: "2021-07-07", 62 MadeBy: "creditors", 63 }, 64 }, 65 }, 66 Attachments: []models.AttachmentResourceDao{ 67 { 68 ID: "id", 69 Type: "resolution", 70 Status: "status", 71 Links: models.AttachmentResourceLinksDao{ 72 Self: "self", 73 Download: "download", 74 }, 75 }, 76 { 77 ID: "id", 78 Type: "statement-of-affairs-director", 79 Status: "status", 80 Links: models.AttachmentResourceLinksDao{ 81 Self: "self", 82 Download: "download", 83 }, 84 }, 85 { 86 ID: "id", 87 Type: "progress-report", 88 Status: "status", 89 Links: models.AttachmentResourceLinksDao{ 90 Self: "self", 91 Download: "download", 92 }, 93 }, 94 }, 95 Resolution: &models.ResolutionResourceDao{ 96 DateOfResolution: "2021-06-06", 97 Attachments: []string{ 98 "id", 99 }, 100 }, 101 StatementOfAffairs: &models.StatementOfAffairsResourceDao{ 102 StatementDate: "2021-06-06", 103 Attachments: []string{ 104 "id", 105 }, 106 }, 107 ProgressReport: &models.ProgressReportResourceDao{ 108 FromDate: "2021-04-14", 109 ToDate: "2022-04-13", 110 Attachments: []string{ 111 "id", 112 }, 113 }, 114 }, 115 Links: models.InsolvencyResourceLinksDao{ 116 Self: "/transactions/123456789/insolvency", 117 ValidationStatus: "/transactions/123456789/insolvency/validation-status", 118 }, 119 } 120 } 121 122 func TestUnitValidateInsolvencyDetails(t *testing.T) { 123 httpmock.Activate() 124 defer httpmock.DeactivateAndReset() 125 126 Convey("error - one practitioner is appointed but not all practitioners have been appointed", t, func() { 127 insolvencyCase := createInsolvencyResource() 128 129 // Remove appointment for one practitioner 130 insolvencyCase.Data.Practitioners[1].Appointment = &models.AppointmentResourceDao{} 131 132 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 133 134 So(validationErrors, ShouldHaveLength, 3) 135 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - all practitioners for insolvency case with transaction id [%s] must be appointed", insolvencyCase.TransactionID)) 136 So((*validationErrors)[0].Location, ShouldContainSubstring, "appointment") 137 }) 138 139 Convey("error - one practitioner is appointed but not all practitioners have been appointed - missing date", t, func() { 140 insolvencyCase := createInsolvencyResource() 141 142 // Remove appointment for one practitioner 143 insolvencyCase.Data.Practitioners[1].Appointment.AppointedOn = "" 144 145 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 146 147 So(validationErrors, ShouldHaveLength, 3) 148 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - all practitioners for insolvency case with transaction id [%s] must be appointed", insolvencyCase.TransactionID)) 149 So((*validationErrors)[0].Location, ShouldContainSubstring, "appointment") 150 }) 151 152 Convey("successful validation of practitioner appointments - all practitioners appointed", t, func() { 153 validationErrors := ValidateInsolvencyDetails(createInsolvencyResource()) 154 So(validationErrors, ShouldHaveLength, 0) 155 }) 156 157 Convey("successful validation of practitioner appointments - no practitioners are appointed", t, func() { 158 insolvencyCase := createInsolvencyResource() 159 160 // Remove appointment details for all practitioners 161 insolvencyCase.Data.Practitioners[0].Appointment = nil 162 insolvencyCase.Data.Practitioners[1].Appointment = nil 163 164 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 165 So(validationErrors, ShouldHaveLength, 0) 166 }) 167 168 Convey("error - attachment type is not resolution and practitioners key is absent", t, func() { 169 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 170 insolvencyCase := models.InsolvencyResourceDao{ 171 Data: models.InsolvencyResourceDaoData{ 172 Attachments: []models.AttachmentResourceDao{ 173 { 174 Type: "type", 175 }, 176 }, 177 }, 178 } 179 180 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 181 182 So(validationErrors, ShouldHaveLength, 2) 183 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - attachment type requires that at least one practitioner must be present for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 184 So((*validationErrors)[0].Location, ShouldContainSubstring, "resolution attachment type") 185 }) 186 187 Convey("error - attachment type is not resolution and practitioners object is empty", t, func() { 188 insolvencyCase := models.InsolvencyResourceDao{ 189 Data: models.InsolvencyResourceDaoData{ 190 Practitioners: []models.PractitionerResourceDao{}, 191 Attachments: []models.AttachmentResourceDao{ 192 { 193 Type: "type", 194 }, 195 }, 196 }, 197 } 198 199 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 200 201 So(validationErrors, ShouldHaveLength, 2) 202 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - attachment type requires that at least one practitioner must be present for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 203 So((*validationErrors)[0].Location, ShouldContainSubstring, "resolution attachment type") 204 }) 205 206 Convey("successful validation of attachment type - attachment type is not resolution and practitioner present", t, func() { 207 insolvencyCase := createInsolvencyResource() 208 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 209 So(validationErrors, ShouldHaveLength, 0) 210 }) 211 212 Convey("successful validation of resolution attachment - attachment type is resolution and practitioner present", t, func() { 213 insolvencyCase := createInsolvencyResource() 214 // Set attachment type to "resolution" 215 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 216 Type: "resolution", 217 ID: "1234", 218 } 219 220 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 221 DateOfResolution: "2021-06-06", 222 Attachments: []string{ 223 "1234", 224 }, 225 } 226 227 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 228 So(validationErrors, ShouldHaveLength, 0) 229 }) 230 231 Convey("successful validation of resolution attachment - attachment type is resolution and practitioners key is absent", t, func() { 232 insolvencyCase := models.InsolvencyResourceDao{ 233 Data: models.InsolvencyResourceDaoData{ 234 Attachments: []models.AttachmentResourceDao{ 235 { 236 Type: "resolution", 237 ID: "1234", 238 }, 239 }, 240 Resolution: &models.ResolutionResourceDao{ 241 DateOfResolution: "2021-06-06", 242 Attachments: []string{ 243 "1234", 244 }, 245 }, 246 }, 247 } 248 249 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 250 So(validationErrors, ShouldHaveLength, 0) 251 }) 252 253 Convey("successful validation of resolution attachment - attachment type is resolution and practitioners object empty", t, func() { 254 insolvencyCase := models.InsolvencyResourceDao{ 255 Data: models.InsolvencyResourceDaoData{ 256 Attachments: []models.AttachmentResourceDao{ 257 { 258 Type: "resolution", 259 ID: "1234", 260 }, 261 }, 262 Resolution: &models.ResolutionResourceDao{ 263 DateOfResolution: "2021-06-06", 264 Attachments: []string{ 265 "1234", 266 }, 267 }, 268 }, 269 } 270 271 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 272 So(validationErrors, ShouldHaveLength, 0) 273 }) 274 275 Convey("successful validation of statement-of-concurrence attachment - attachment type is statement-of-concurrence and statement-of-affairs-director are present", t, func() { 276 insolvencyCase := createInsolvencyResource() 277 insolvencyCase.Data.Resolution = nil 278 279 // Set attachment type to "statement-of-concurrence" 280 insolvencyCase.Data.Attachments[0].Type = "statement-of-concurrence" 281 insolvencyCase.Data.Attachments[1].Type = "statement-of-affairs-director" 282 283 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 284 So(validationErrors, ShouldHaveLength, 0) 285 }) 286 287 Convey("error - attachment type is statement-of-affairs-liquidator and a practitioner is appointed", t, func() { 288 insolvencyCase := createInsolvencyResource() 289 290 // Set attachment type to "statement-of-concurrence" 291 insolvencyCase.Data.Attachments[0].Type = "statement-of-affairs-liquidator" 292 293 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 294 295 So(validationErrors, ShouldHaveLength, 2) 296 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - no appointed practitioners can be assigned to the case when attachment type statement-of-affairs-liquidator is included with transaction id [%s]", insolvencyCase.TransactionID)) 297 So((*validationErrors)[0].Location, ShouldContainSubstring, "statement of affairs liquidator attachment type") 298 }) 299 300 Convey("successful validation of statement-of-affairs-liquidator - attachment type is statement-of-affairs-liquidator and at least one practitioner is present but not appointed", t, func() { 301 insolvencyCase := createInsolvencyResource() 302 303 // Set attachment type to "statement-of-affairs-liquidator" 304 insolvencyCase.Data.Attachments[0].Type = "statement-of-affairs-liquidator" 305 306 // Remove resolution from insolvency case 307 insolvencyCase.Data.Resolution = nil 308 309 // Remove appointment details for all practitioners 310 insolvencyCase.Data.Practitioners[0].Appointment = nil 311 insolvencyCase.Data.Practitioners[1].Appointment = nil 312 313 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 314 So(validationErrors, ShouldHaveLength, 0) 315 }) 316 317 Convey("error - no attachments present and no appointed practitioners on insolvency case", t, func() { 318 insolvencyCase := models.InsolvencyResourceDao{ 319 Data: models.InsolvencyResourceDaoData{ 320 Practitioners: []models.PractitionerResourceDao{ 321 { 322 FirstName: "Bob", 323 }, 324 }, 325 }, 326 } 327 328 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 329 330 So(validationErrors, ShouldHaveLength, 1) 331 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - at least one practitioner must be appointed as there are no attachments for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 332 So((*validationErrors)[0].Location, ShouldContainSubstring, "no attachments") 333 }) 334 335 Convey("error - no resolution and no submitted practitioners on insolvency case", t, func() { 336 insolvencyCase := models.InsolvencyResourceDao{ 337 Data: models.InsolvencyResourceDaoData{}, 338 } 339 340 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 341 342 So(validationErrors, ShouldHaveLength, 1) 343 So((*validationErrors)[0].Error, ShouldContainSubstring, "error - if no practitioners are present then an attachment of the type resolution must be present") 344 So((*validationErrors)[0].Location, ShouldContainSubstring, "no practitioners and no resolution") 345 }) 346 347 Convey("successful validation - no attachments present but at least one appointed practitioner is present on insolvency case", t, func() { 348 insolvencyCase := models.InsolvencyResourceDao{ 349 Data: models.InsolvencyResourceDaoData{ 350 Practitioners: []models.PractitionerResourceDao{ 351 { 352 Appointment: &models.AppointmentResourceDao{ 353 AppointedOn: "2020-01-01", 354 MadeBy: "creditors", 355 }, 356 }, 357 }, 358 }, 359 } 360 361 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 362 So(validationErrors, ShouldHaveLength, 0) 363 }) 364 365 Convey("error - resolution attachment present and no date of resolution filed for insolvency case", t, func() { 366 insolvencyCase := createInsolvencyResource() 367 insolvencyCase.Data.Attachments[0].Type = "resolution" 368 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 369 DateOfResolution: "", 370 Attachments: []string{"123"}, 371 } 372 373 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 374 375 So(validationErrors, ShouldHaveLength, 6) 376 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - a date of resolution must be present as there is an attachment with type resolution for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 377 So((*validationErrors)[0].Location, ShouldContainSubstring, "no date of resolution") 378 }) 379 380 Convey("error - resolution attachment present and no resolution details filed for insolvency case", t, func() { 381 insolvencyCase := createInsolvencyResource() 382 insolvencyCase.Data.Attachments[0].Type = "resolution" 383 insolvencyCase.Data.Practitioners = nil 384 insolvencyCase.Data.Resolution = nil 385 386 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 387 388 So(validationErrors, ShouldHaveLength, 1) 389 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - a date of resolution must be present as there is an attachment with type resolution for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 390 So((*validationErrors)[0].Location, ShouldContainSubstring, "no date of resolution") 391 }) 392 393 Convey("error - date_of_resolution present and no resolution filed for insolvency case", t, func() { 394 insolvencyCase := createInsolvencyResource() 395 insolvencyCase.Data.Attachments[0].Type = "test" 396 397 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 398 DateOfResolution: "2021-06-06", 399 } 400 401 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 402 403 So(validationErrors, ShouldHaveLength, 1) 404 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - a resolution attachment must be present as there is a date_of_resolution filed for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 405 406 So((*validationErrors)[0].Location, ShouldContainSubstring, "no resolution") 407 }) 408 409 Convey("error - id for uploaded resolution attachment does not match id supplied with resolution filed for insolvency case", t, func() { 410 insolvencyCase := createInsolvencyResource() 411 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 412 Type: "resolution", 413 ID: "1234", 414 } 415 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 416 DateOfResolution: "2021-06-06", 417 Attachments: []string{ 418 "0234", 419 }, 420 } 421 422 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 423 424 So(validationErrors, ShouldHaveLength, 1) 425 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - id for uploaded resolution attachment must match the attachment id supplied when filing a resolution for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 426 427 So((*validationErrors)[0].Location, ShouldContainSubstring, "attachment ids do not match") 428 }) 429 430 Convey("successful validation - resolution attachment present and date of resolution filed for insolvency case", t, func() { 431 insolvencyCase := createInsolvencyResource() 432 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 433 Type: "resolution", 434 ID: "1234", 435 } 436 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 437 DateOfResolution: "2021-06-06", 438 Attachments: []string{ 439 "1234", 440 }, 441 } 442 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 443 So(validationErrors, ShouldHaveLength, 0) 444 }) 445 446 // Loop through SOA attachment types to repeat test to convey the following: 447 // error - <attachment type> filed but no statement date/resource exists in DB 448 attachmentTypes := []string{constants.StatementOfAffairsDirector.String(), constants.StatementOfAffairsLiquidator.String(), constants.StatementOfConcurrence.String()} 449 contextList := []string{"date", "resource"} 450 for _, attachment := range attachmentTypes { 451 for _, contextItem := range contextList { 452 conveyTitle := "error - " + attachment + " filed but no statement " + contextItem + " exists in DB" 453 // Convey.. e.g. error - statement-of-affairs-director filed but no statement date exists in DB 454 Convey(conveyTitle, t, func() { 455 // Create insolvency case 456 insolvencyCase := createInsolvencyResource() 457 switch contextItem { 458 case "date": 459 // Remove the date value 460 insolvencyCase.Data.StatementOfAffairs = &models.StatementOfAffairsResourceDao{ 461 StatementDate: "", 462 } 463 case "resource": 464 // Remove the SOA resource 465 insolvencyCase.Data.StatementOfAffairs = nil 466 } 467 468 // Change attachment type 469 insolvencyCase.Data.Attachments[1].Type = attachment 470 471 // Remove practitioner for SOA-L to prevent triggering another error 472 if attachment == constants.StatementOfAffairsLiquidator.String() { 473 insolvencyCase.Data.Practitioners = make([]models.PractitionerResourceDao, 0) 474 } 475 476 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 477 So(validationErrors, ShouldHaveLength, 1) 478 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - a date of statement of affairs must be present as there is an attachment with a type of [%s], [%s], or a [%s] for insolvency case with transaction id [%s]", constants.StatementOfAffairsDirector.String(), constants.StatementOfConcurrence.String(), constants.StatementOfAffairsLiquidator.String(), insolvencyCase.TransactionID)) 479 So((*validationErrors)[0].Location, ShouldContainSubstring, "statement-of-affairs") 480 }) 481 } 482 } 483 484 Convey("error - statement resource exists in DB but no statement-of-affairs attachment filed", t, func() { 485 486 // Create insolvency case 487 insolvencyCase := createInsolvencyResource() 488 insolvencyCase.Data.Attachments[1].Type = "random" 489 490 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 491 492 So(validationErrors, ShouldHaveLength, 1) 493 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - an attachment of type [%s], [%s], or a [%s] must be present as there is a date of statement of affairs present for insolvency case with transaction id [%s]", constants.StatementOfAffairsDirector.String(), constants.StatementOfConcurrence.String(), constants.StatementOfAffairsLiquidator.String(), insolvencyCase.TransactionID)) 494 So((*validationErrors)[0].Location, ShouldContainSubstring, "statement-of-affairs") 495 }) 496 497 Convey("error - attachment type is statement-of-concurrence and practitioner object empty", t, func() { 498 insolvencyCase := createInsolvencyResource() 499 // Remove the Practitioners 500 insolvencyCase.Data.Practitioners = nil 501 502 // Replace statement-of-affairs-director attachment type to statement-of-concurrence for the 2nd attachment 503 insolvencyCase.Data.Attachments[0].Type = "type" 504 insolvencyCase.Data.Attachments[1].Type = "statement-of-concurrence" 505 insolvencyCase.Data.Attachments[2].Type = "type2" 506 507 // Remove the resolution and progress report details 508 insolvencyCase.Data.Resolution = nil 509 insolvencyCase.Data.ProgressReport = nil 510 511 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 512 So(validationErrors, ShouldHaveLength, 2) 513 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - attachment type requires that at least one practitioner must be present for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 514 So((*validationErrors)[1].Error, ShouldContainSubstring, "error - if no practitioners are present then an attachment of the type resolution must be present") 515 }) 516 517 Convey("successful validation of statement-of-concurrence - attachment type is statement-of-concurrence and at least one practitioner present", t, func() { 518 insolvencyCase := createInsolvencyResource() 519 520 // Replace statement-of-affairs-director attachment type to statement-of-concurrence for the 2nd attachment 521 insolvencyCase.Data.Attachments[0].Type = "type" 522 insolvencyCase.Data.Attachments[1].Type = "statement-of-concurrence" 523 insolvencyCase.Data.Attachments[2].Type = "type2" 524 525 // Remove the resolution and progress report details 526 insolvencyCase.Data.Resolution = nil 527 insolvencyCase.Data.ProgressReport = nil 528 529 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 530 So(validationErrors, ShouldHaveLength, 0) 531 }) 532 533 Convey("error - practitioner appointment is before date of resolution", t, func() { 534 // Add resolution to insolvency case 535 insolvencyCase := createInsolvencyResource() 536 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 537 Type: "resolution", 538 ID: "1234", 539 } 540 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 541 DateOfResolution: "2021-06-06", 542 Attachments: []string{ 543 "1234", 544 }, 545 } 546 547 // Appoint practitioner before resolution 548 insolvencyCase.Data.Practitioners[0].Appointment.AppointedOn = "2021-05-05" 549 550 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 551 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - practitioner [%s] appointed on [%s] is before the resolution date [%s]", insolvencyCase.Data.Practitioners[0].ID, insolvencyCase.Data.Practitioners[0].Appointment.AppointedOn, insolvencyCase.Data.Resolution.DateOfResolution)) 552 So((*validationErrors)[0].Location, ShouldContainSubstring, "practitioner") 553 }) 554 555 Convey("error parsing appointment date", t, func() { 556 // Add resolution to insolvency case 557 insolvencyCase := createInsolvencyResource() 558 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 559 Type: "resolution", 560 ID: "1234", 561 } 562 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 563 DateOfResolution: "2021-06-06", 564 Attachments: []string{ 565 "1234", 566 }, 567 } 568 569 // Appoint practitioner before resolution 570 insolvencyCase.Data.Practitioners[0].Appointment.AppointedOn = "date" 571 572 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 573 So((*validationErrors)[0].Error, ShouldContainSubstring, "cannot parse") 574 So((*validationErrors)[0].Location, ShouldContainSubstring, "practitioner") 575 }) 576 577 Convey("error parsing resolution date", t, func() { 578 // Add resolution to insolvency case 579 insolvencyCase := createInsolvencyResource() 580 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 581 Type: "resolution", 582 ID: "1234", 583 } 584 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 585 DateOfResolution: "date", 586 Attachments: []string{ 587 "1234", 588 }, 589 } 590 // Appoint practitioner before resolution 591 insolvencyCase.Data.Practitioners[0].Appointment.AppointedOn = "2021-05-05" 592 593 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 594 So((*validationErrors)[0].Error, ShouldContainSubstring, "cannot parse") 595 So((*validationErrors)[0].Location, ShouldContainSubstring, "practitioner") 596 }) 597 598 Convey("Validate statement date and resolution date", t, func() { 599 Convey("Invalid statement date", func() { 600 insolvencyCase := createInsolvencyResource() 601 insolvencyCase.Data.StatementOfAffairs.StatementDate = "invalid" 602 603 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 604 So((*validationErrors)[0].Error, ShouldContainSubstring, "invalid statementOfAffairs date") 605 }) 606 607 Convey("Invalid resolution date", func() { 608 insolvencyCase := createInsolvencyResource() 609 insolvencyCase.Data.Resolution.DateOfResolution = "invalid" 610 insolvencyCase.Data.Practitioners = nil // prevent alternative validation execution 611 612 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 613 So((*validationErrors)[0].Error, ShouldContainSubstring, "invalid resolution date") 614 }) 615 616 Convey("Statement date is after the resolution date", func() { 617 insolvencyCase := createInsolvencyResource() 618 insolvencyCase.Data.StatementOfAffairs.StatementDate = "2021-07-26" 619 insolvencyCase.Data.Resolution.DateOfResolution = "2021-07-25" 620 insolvencyCase.Data.Practitioners = nil // prevent alternative validation execution 621 622 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 623 So((*validationErrors)[0].Error, ShouldContainSubstring, "error - statement of affairs date [" + insolvencyCase.Data.StatementOfAffairs.StatementDate + "] must not be after the resolution date" + " [" + insolvencyCase.Data.Resolution.DateOfResolution + "]") 624 }) 625 626 Convey("Statement date more than 14 days prior to the resolution date", func() { 627 insolvencyCase := createInsolvencyResource() 628 insolvencyCase.Data.StatementOfAffairs.StatementDate = "2021-07-10" 629 insolvencyCase.Data.Resolution.DateOfResolution = "2021-07-25" 630 insolvencyCase.Data.Practitioners = nil // prevent alternative validation execution 631 632 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 633 So((*validationErrors)[0].Error, ShouldContainSubstring, "error - statement of affairs date [" + insolvencyCase.Data.StatementOfAffairs.StatementDate + "] must not be more than 14 days prior to the resolution date" + " [" + insolvencyCase.Data.Resolution.DateOfResolution + "]") 634 }) 635 636 Convey("Statement date is 14 days prior to the resolution date", func() { 637 insolvencyCase := createInsolvencyResource() 638 insolvencyCase.Data.StatementOfAffairs.StatementDate = "2021-07-11" 639 insolvencyCase.Data.Resolution.DateOfResolution = "2021-07-25" 640 insolvencyCase.Data.Practitioners = nil // prevent alternative validation execution 641 642 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 643 So(validationErrors, ShouldHaveLength, 0) 644 }) 645 646 }) 647 648 Convey("valid insolvency case - appointment date is after resolution date", t, func() { 649 // Add resolution to insolvency case 650 insolvencyCase := createInsolvencyResource() 651 insolvencyCase.Data.Attachments[0] = models.AttachmentResourceDao{ 652 Type: "resolution", 653 ID: "1234", 654 } 655 insolvencyCase.Data.Resolution = &models.ResolutionResourceDao{ 656 DateOfResolution: "2021-06-06", 657 Attachments: []string{ 658 "1234", 659 }, 660 } 661 662 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 663 So(validationErrors, ShouldHaveLength, 0) 664 }) 665 666 Convey("Validate progress report from and to dates", t, func() { 667 httpmock.Activate() 668 defer httpmock.DeactivateAndReset() 669 670 Convey("valid submission of progress-report", func() { 671 insolvencyCase := createInsolvencyResource() 672 insolvencyCase.Data.ProgressReport = &models.ProgressReportResourceDao{ 673 FromDate: "2021-04-14", 674 ToDate: "2022-04-13", 675 Attachments: []string{ 676 "id", 677 }, 678 } 679 680 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 681 So(validationErrors, ShouldHaveLength, 0) 682 }) 683 684 Convey("progress-report attachment present and from date blank", func() { 685 insolvencyCase := createInsolvencyResource() 686 insolvencyCase.Data.ProgressReport = &models.ProgressReportResourceDao{ 687 FromDate: "", 688 ToDate: "2022-04-13", 689 Attachments: []string{ 690 "id", 691 }, 692 } 693 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 694 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - progress report dates must be present as there is an attachment with type progress-report for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 695 So((*validationErrors)[0].Location, ShouldContainSubstring, "no dates for progress report") 696 }) 697 698 Convey("progress-report attachment present and to date blank", func() { 699 insolvencyCase := createInsolvencyResource() 700 insolvencyCase.Data.ProgressReport = &models.ProgressReportResourceDao{ 701 FromDate: "2021-04-14", 702 ToDate: "", 703 Attachments: []string{ 704 "id", 705 }, 706 } 707 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 708 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - progress report dates must be present as there is an attachment with type progress-report for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 709 So((*validationErrors)[0].Location, ShouldContainSubstring, "no dates for progress report") 710 }) 711 712 Convey("progress-report attachment present and all dates blank", func() { 713 insolvencyCase := createInsolvencyResource() 714 insolvencyCase.Data.ProgressReport = &models.ProgressReportResourceDao{ 715 FromDate: "", 716 ToDate: "", 717 Attachments: []string{ 718 "id", 719 }, 720 } 721 validationErrors := ValidateInsolvencyDetails(insolvencyCase) 722 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - progress report dates must be present as there is an attachment with type progress-report for insolvency case with transaction id [%s]", insolvencyCase.TransactionID)) 723 So((*validationErrors)[0].Location, ShouldContainSubstring, "no dates for progress report") 724 }) 725 }) 726 727 } 728 729 func TestUnitValidateAntivirus(t *testing.T) { 730 731 httpmock.Activate() 732 defer httpmock.DeactivateAndReset() 733 734 Convey("error - antivirus check has not been completed", t, func() { 735 mockCtrl := gomock.NewController(t) 736 defer mockCtrl.Finish() 737 mockService := mocks.NewMockService(mockCtrl) 738 739 insolvencyCase := createInsolvencyResource() 740 741 attachment := `{ 742 "name": "file", 743 "size": 1000, 744 "content_type": "test", 745 "av_status": "not-scanned" 746 }` 747 748 // Expect GetAttachmentDetails to be called once and return the attachment 749 httpmock.RegisterResponder(http.MethodGet, `=~.*`, httpmock.NewStringResponder(http.StatusOK, attachment)) 750 751 mockService.EXPECT().UpdateAttachmentStatus(transactionID, insolvencyCase.Data.Attachments[0].ID, "integrity_failed").Return(http.StatusNoContent, nil).Times(3) 752 753 validationErrors := ValidateAntivirus(mockService, insolvencyCase, req) 754 755 So(validationErrors, ShouldHaveLength, 1) 756 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - antivirus check has failed on insolvency case with transaction id [%s], attachments have not been scanned", insolvencyCase.TransactionID)) 757 So((*validationErrors)[0].Location, ShouldContainSubstring, "antivirus incomplete") 758 }) 759 760 Convey("error - antivirus check has failed, attachment is infected", t, func() { 761 mockCtrl := gomock.NewController(t) 762 defer mockCtrl.Finish() 763 mockService := mocks.NewMockService(mockCtrl) 764 765 insolvencyCase := createInsolvencyResource() 766 767 attachment := `{ 768 "name": "file", 769 "size": 1000, 770 "content_type": "test", 771 "av_status": "infected" 772 }` 773 774 // Expect GetAttachmentDetails to be called once and return the attachment 775 httpmock.RegisterResponder(http.MethodGet, `=~.*`, httpmock.NewStringResponder(http.StatusOK, attachment)) 776 777 mockService.EXPECT().UpdateAttachmentStatus(transactionID, insolvencyCase.Data.Attachments[0].ID, "integrity_failed").Return(http.StatusNoContent, nil).Times(3) 778 779 validationErrors := ValidateAntivirus(mockService, insolvencyCase, req) 780 781 So(validationErrors, ShouldHaveLength, 1) 782 So((*validationErrors)[0].Error, ShouldContainSubstring, fmt.Sprintf("error - antivirus check has failed on insolvency case with transaction id [%s], virus detected", insolvencyCase.TransactionID)) 783 So((*validationErrors)[0].Location, ShouldContainSubstring, "antivirus failure") 784 }) 785 786 Convey("successful validation - antivirus check has passed, attachment is clean", t, func() { 787 mockCtrl := gomock.NewController(t) 788 defer mockCtrl.Finish() 789 mockService := mocks.NewMockService(mockCtrl) 790 791 insolvencyCase := createInsolvencyResource() 792 793 attachment := `{ 794 "name": "file", 795 "size": 1000, 796 "content_type": "test", 797 "av_status": "clean" 798 }` 799 800 // Expect GetAttachmentDetails to be called once and return the attachment 801 httpmock.RegisterResponder(http.MethodGet, `=~.*`, httpmock.NewStringResponder(http.StatusOK, attachment)) 802 803 mockService.EXPECT().UpdateAttachmentStatus(transactionID, insolvencyCase.Data.Attachments[0].ID, "processed").Return(http.StatusNoContent, nil).Times(3) 804 805 validationErrors := ValidateAntivirus(mockService, insolvencyCase, req) 806 So(validationErrors, ShouldHaveLength, 0) 807 }) 808 } 809 810 var transactionProfileResponseClosed = ` 811 { 812 "status": "closed" 813 } 814 ` 815 816 func TestUnitGenerateFilings(t *testing.T) { 817 httpmock.Activate() 818 defer httpmock.DeactivateAndReset() 819 820 Convey("error getting insolvency resource from database", t, func() { 821 mockCtrl := gomock.NewController(t) 822 defer mockCtrl.Finish() 823 mockService := mocks.NewMockService(mockCtrl) 824 825 // Expect GetInsolvencyResource to be called once and return an error for the insolvency case 826 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(createInsolvencyResource(), errors.New("insolvency case does not exist")).Times(1) 827 828 filings, err := GenerateFilings(mockService, transactionID) 829 830 So(filings, ShouldBeNil) 831 So(err.Error(), ShouldContainSubstring, "insolvency case does not exist") 832 }) 833 834 Convey("Generate filing for 600 case with two practitioners", t, func() { 835 mockCtrl := gomock.NewController(t) 836 defer mockCtrl.Finish() 837 mockService := mocks.NewMockService(mockCtrl) 838 839 // Expect the transaction api to be called and return a closed transaction 840 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 841 842 insolvencyResource := createInsolvencyResource() 843 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{} 844 845 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 846 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 847 848 filings, err := GenerateFilings(mockService, transactionID) 849 850 So(len(filings), ShouldEqual, 1) 851 852 So(filings[0].Kind, ShouldEqual, "insolvency#600") 853 So(filings[0].DescriptionIdentifier, ShouldEqual, "600") 854 So(filings[0].Data, ShouldContainKey, "practitioners") 855 So(filings[0].Data, ShouldNotContainKey, "attachments") 856 857 So(err, ShouldBeNil) 858 }) 859 860 Convey("Generate filing for LRESEX case with resolution attachment and no practitioners", t, func() { 861 mockCtrl := gomock.NewController(t) 862 defer mockCtrl.Finish() 863 mockService := mocks.NewMockService(mockCtrl) 864 865 // Expect the transaction api to be called and return a closed transaction 866 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 867 868 insolvencyResource := createInsolvencyResource() 869 insolvencyResource.Data.Practitioners = []models.PractitionerResourceDao{} 870 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 871 { 872 ID: "id", 873 Type: "resolution", 874 Status: "status", 875 Links: models.AttachmentResourceLinksDao{ 876 Self: "self", 877 Download: "download", 878 }, 879 }, 880 } 881 882 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 883 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 884 885 filings, err := GenerateFilings(mockService, transactionID) 886 887 So(len(filings), ShouldEqual, 1) 888 889 So(filings[0].Kind, ShouldEqual, "insolvency#LRESEX") 890 So(filings[0].DescriptionIdentifier, ShouldEqual, "LRESEX") 891 So(filings[0].Data, ShouldNotContainKey, "practitioners") 892 So(len(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 893 So(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "resolution") 894 895 So(err, ShouldBeNil) 896 }) 897 898 Convey("Generate filing for LIQ02 case with statement-of-affairs-director attachment and two practitioners", t, func() { 899 mockCtrl := gomock.NewController(t) 900 defer mockCtrl.Finish() 901 mockService := mocks.NewMockService(mockCtrl) 902 903 // Expect the transaction api to be called and return a closed transaction 904 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 905 906 insolvencyResource := createInsolvencyResource() 907 insolvencyResource.Data.Practitioners[0].Appointment = nil 908 insolvencyResource.Data.Practitioners[1].Appointment = nil 909 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 910 { 911 ID: "id", 912 Type: "statement-of-affairs-director", 913 Status: "status", 914 Links: models.AttachmentResourceLinksDao{ 915 Self: "self", 916 Download: "download", 917 }, 918 }, 919 } 920 921 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 922 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 923 924 filings, err := GenerateFilings(mockService, transactionID) 925 926 So(len(filings), ShouldEqual, 1) 927 928 So(filings[0].Kind, ShouldEqual, "insolvency#LIQ02") 929 So(filings[0].DescriptionIdentifier, ShouldEqual, "LIQ02") 930 So(filings[0].Data, ShouldContainKey, "practitioners") 931 So(len(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 932 So(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "statement-of-affairs-director") 933 934 So(err, ShouldBeNil) 935 }) 936 937 Convey("Generate filing for LIQ02 case with statement-of-affairs-liquidator attachment and two practitioners", t, func() { 938 mockCtrl := gomock.NewController(t) 939 defer mockCtrl.Finish() 940 mockService := mocks.NewMockService(mockCtrl) 941 942 // Expect the transaction api to be called and return a closed transaction 943 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 944 945 insolvencyResource := createInsolvencyResource() 946 insolvencyResource.Data.Practitioners[0].Appointment = nil 947 insolvencyResource.Data.Practitioners[1].Appointment = nil 948 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 949 { 950 ID: "id", 951 Type: "statement-of-affairs-liquidator", 952 Status: "status", 953 Links: models.AttachmentResourceLinksDao{ 954 Self: "self", 955 Download: "download", 956 }, 957 }, 958 } 959 960 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 961 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 962 963 filings, err := GenerateFilings(mockService, transactionID) 964 965 So(len(filings), ShouldEqual, 1) 966 967 So(filings[0].Kind, ShouldEqual, "insolvency#LIQ02") 968 So(filings[0].DescriptionIdentifier, ShouldEqual, "LIQ02") 969 So(filings[0].Data, ShouldContainKey, "practitioners") 970 So(len(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 971 So(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "statement-of-affairs-liquidator") 972 973 So(err, ShouldBeNil) 974 }) 975 976 Convey("Generate filing for LIQ02 case with statement-of-affairs-director and statement-of-concurrence attachments and two practitioners", t, func() { 977 mockCtrl := gomock.NewController(t) 978 defer mockCtrl.Finish() 979 mockService := mocks.NewMockService(mockCtrl) 980 981 // Expect the transaction api to be called and return a closed transaction 982 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 983 984 insolvencyResource := createInsolvencyResource() 985 insolvencyResource.Data.Practitioners[0].Appointment = nil 986 insolvencyResource.Data.Practitioners[1].Appointment = nil 987 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 988 { 989 ID: "id", 990 Type: "statement-of-affairs-director", 991 Status: "status", 992 Links: models.AttachmentResourceLinksDao{ 993 Self: "self", 994 Download: "download", 995 }, 996 }, 997 { 998 ID: "id", 999 Type: "statement-of-concurrence", 1000 Status: "status", 1001 Links: models.AttachmentResourceLinksDao{ 1002 Self: "self", 1003 Download: "download", 1004 }, 1005 }, 1006 } 1007 1008 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 1009 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 1010 1011 filings, err := GenerateFilings(mockService, transactionID) 1012 1013 So(len(filings), ShouldEqual, 1) 1014 1015 So(filings[0].Kind, ShouldEqual, "insolvency#LIQ02") 1016 So(filings[0].DescriptionIdentifier, ShouldEqual, "LIQ02") 1017 So(filings[0].Data, ShouldContainKey, "practitioners") 1018 So(len(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 2) 1019 So(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "statement-of-affairs-director") 1020 So(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)[1].Type, ShouldEqual, "statement-of-concurrence") 1021 1022 So(err, ShouldBeNil) 1023 }) 1024 1025 Convey("Generate filing for 600 and LIQ02 case with statement-of-affairs-director attachment and two practitioners", t, func() { 1026 mockCtrl := gomock.NewController(t) 1027 defer mockCtrl.Finish() 1028 mockService := mocks.NewMockService(mockCtrl) 1029 1030 // Expect the transaction api to be called and return a closed transaction 1031 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 1032 1033 insolvencyResource := createInsolvencyResource() 1034 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 1035 { 1036 ID: "id", 1037 Type: "statement-of-affairs-director", 1038 Status: "status", 1039 Links: models.AttachmentResourceLinksDao{ 1040 Self: "self", 1041 Download: "download", 1042 }, 1043 }, 1044 } 1045 1046 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 1047 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 1048 1049 filings, err := GenerateFilings(mockService, transactionID) 1050 1051 So(len(filings), ShouldEqual, 2) 1052 1053 So(filings[0].Kind, ShouldEqual, "insolvency#600") 1054 So(filings[0].DescriptionIdentifier, ShouldEqual, "600") 1055 So(filings[0].Data, ShouldContainKey, "practitioners") 1056 So(filings[0].Data, ShouldNotContainKey, "attachments") 1057 1058 So(filings[1].Kind, ShouldEqual, "insolvency#LIQ02") 1059 So(filings[1].DescriptionIdentifier, ShouldEqual, "LIQ02") 1060 So(filings[1].Data, ShouldContainKey, "practitioners") 1061 So(len(filings[1].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 1062 So(filings[1].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "statement-of-affairs-director") 1063 1064 So(err, ShouldBeNil) 1065 }) 1066 1067 Convey("Generate filing for 600, LRESEX, and LIQ02 case with statement-of-affairs-director and statement-of-concurrence attachments and two practitioners", t, func() { 1068 mockCtrl := gomock.NewController(t) 1069 defer mockCtrl.Finish() 1070 mockService := mocks.NewMockService(mockCtrl) 1071 1072 // Expect the transaction api to be called and return a closed transaction 1073 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 1074 1075 insolvencyResource := createInsolvencyResource() 1076 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 1077 { 1078 ID: "id", 1079 Type: "resolution", 1080 Status: "status", 1081 Links: models.AttachmentResourceLinksDao{ 1082 Self: "self", 1083 Download: "download", 1084 }, 1085 }, 1086 { 1087 ID: "id", 1088 Type: "statement-of-affairs-director", 1089 Status: "status", 1090 Links: models.AttachmentResourceLinksDao{ 1091 Self: "self", 1092 Download: "download", 1093 }, 1094 }, 1095 { 1096 ID: "id", 1097 Type: "statement-of-concurrence", 1098 Status: "status", 1099 Links: models.AttachmentResourceLinksDao{ 1100 Self: "self", 1101 Download: "download", 1102 }, 1103 }, 1104 } 1105 1106 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 1107 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 1108 1109 filings, err := GenerateFilings(mockService, transactionID) 1110 1111 So(len(filings), ShouldEqual, 3) 1112 1113 So(filings[0].Kind, ShouldEqual, "insolvency#600") 1114 So(filings[0].DescriptionIdentifier, ShouldEqual, "600") 1115 So(filings[0].Data, ShouldContainKey, "practitioners") 1116 So(filings[0].Data, ShouldNotContainKey, "attachments") 1117 1118 So(filings[1].Kind, ShouldEqual, "insolvency#LRESEX") 1119 So(filings[1].DescriptionIdentifier, ShouldEqual, "LRESEX") 1120 So(filings[1].Data, ShouldNotContainKey, "practitioners") 1121 So(len(filings[1].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 1122 So(filings[1].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "resolution") 1123 1124 So(filings[2].Kind, ShouldEqual, "insolvency#LIQ02") 1125 So(filings[2].DescriptionIdentifier, ShouldEqual, "LIQ02") 1126 So(filings[2].Data, ShouldContainKey, "practitioners") 1127 So(len(filings[2].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 2) 1128 So(filings[2].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "statement-of-affairs-director") 1129 So(filings[2].Data["attachments"].([]*models.AttachmentResourceDao)[1].Type, ShouldEqual, "statement-of-concurrence") 1130 1131 So(err, ShouldBeNil) 1132 }) 1133 1134 Convey("Generate filing for LIQ03 case with progress-report attachment and one practitioner", t, func() { 1135 mockCtrl := gomock.NewController(t) 1136 defer mockCtrl.Finish() 1137 mockService := mocks.NewMockService(mockCtrl) 1138 1139 // Expect the transaction api to be called and return a closed transaction 1140 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 1141 1142 insolvencyResource := createInsolvencyResource() 1143 insolvencyResource.Data.Practitioners = []models.PractitionerResourceDao{ 1144 { 1145 ID: "1234", 1146 IPCode: "1234", 1147 FirstName: "Name", 1148 LastName: "LastName", 1149 TelephoneNumber: "1234", 1150 Email: "name@email.com", 1151 Address: models.AddressResourceDao{}, 1152 Role: "final-liquidator", 1153 Links: models.PractitionerResourceLinksDao{}, 1154 }, 1155 } 1156 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 1157 { 1158 ID: "id", 1159 Type: "progress-report", 1160 Status: "status", 1161 Links: models.AttachmentResourceLinksDao{ 1162 Self: "self", 1163 Download: "download", 1164 }, 1165 }, 1166 } 1167 1168 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 1169 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 1170 1171 filings, err := GenerateFilings(mockService, transactionID) 1172 1173 So(len(filings), ShouldEqual, 1) 1174 1175 So(filings[0].Kind, ShouldEqual, "insolvency#LIQ03") 1176 So(filings[0].DescriptionIdentifier, ShouldEqual, "LIQ03") 1177 So(filings[0].Data, ShouldContainKey, "practitioners") 1178 So(len(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 1179 So(filings[0].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "progress-report") 1180 1181 So(err, ShouldBeNil) 1182 }) 1183 1184 Convey("Generate filing for 600 and LIQ03 case with progress-report attachment and one practitioner", t, func() { 1185 mockCtrl := gomock.NewController(t) 1186 defer mockCtrl.Finish() 1187 mockService := mocks.NewMockService(mockCtrl) 1188 1189 // Expect the transaction api to be called and return a closed transaction 1190 httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed)) 1191 1192 insolvencyResource := createInsolvencyResource() 1193 insolvencyResource.Data.Practitioners = []models.PractitionerResourceDao{ 1194 { 1195 ID: "1234", 1196 IPCode: "1234", 1197 FirstName: "Name", 1198 LastName: "LastName", 1199 TelephoneNumber: "1234", 1200 Email: "name@email.com", 1201 Address: models.AddressResourceDao{}, 1202 Role: "final-liquidator", 1203 Links: models.PractitionerResourceLinksDao{}, 1204 Appointment: &models.AppointmentResourceDao{ 1205 AppointedOn: "2021-07-07", 1206 MadeBy: "creditors", 1207 }, 1208 }, 1209 } 1210 insolvencyResource.Data.Attachments = []models.AttachmentResourceDao{ 1211 { 1212 ID: "id", 1213 Type: "progress-report", 1214 Status: "status", 1215 Links: models.AttachmentResourceLinksDao{ 1216 Self: "self", 1217 Download: "download", 1218 }, 1219 }, 1220 } 1221 1222 // Expect GetInsolvencyResource to be called once and return a valid insolvency case 1223 mockService.EXPECT().GetInsolvencyResource(transactionID).Return(insolvencyResource, nil).Times(1) 1224 1225 filings, err := GenerateFilings(mockService, transactionID) 1226 1227 So(len(filings), ShouldEqual, 2) 1228 1229 So(filings[0].Kind, ShouldEqual, "insolvency#600") 1230 So(filings[0].DescriptionIdentifier, ShouldEqual, "600") 1231 So(filings[0].Data, ShouldContainKey, "practitioners") 1232 So(filings[0].Data, ShouldNotContainKey, "attachments") 1233 1234 So(filings[1].Kind, ShouldEqual, "insolvency#LIQ03") 1235 So(filings[1].DescriptionIdentifier, ShouldEqual, "LIQ03") 1236 So(filings[1].Data, ShouldContainKey, "practitioners") 1237 So(len(filings[1].Data["attachments"].([]*models.AttachmentResourceDao)), ShouldEqual, 1) 1238 So(filings[1].Data["attachments"].([]*models.AttachmentResourceDao)[0].Type, ShouldEqual, "progress-report") 1239 1240 So(err, ShouldBeNil) 1241 }) 1242 1243 }