Skip to content

Commit

Permalink
fix: inc seedlot status and draft update (#1497)
Browse files Browse the repository at this point in the history
  • Loading branch information
craigyu authored Aug 14, 2024
1 parent ee83cc1 commit 1799204
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ public final class Constants {

public static final Integer CLASS_A_SEEDLOT_NUM_MIN = 63000;
public static final Integer CLASS_A_SEEDLOT_NUM_MAX = 69999;
public static final String CLASS_A_SEEDLOT_STATUS = "PND";
public static final String INCOMPLETE_SEEDLOT_STATUS = "INC";
public static final String PENDING_SEEDLOT_STATUS = "PND";
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package ca.bc.gov.backendstartapi.service;

import ca.bc.gov.backendstartapi.config.Constants;
import ca.bc.gov.backendstartapi.config.SparLog;
import ca.bc.gov.backendstartapi.dto.RevisionCountDto;
import ca.bc.gov.backendstartapi.dto.SaveSeedlotFormDtoClassA;
import ca.bc.gov.backendstartapi.entity.SaveSeedlotProgressEntityClassA;
import ca.bc.gov.backendstartapi.entity.SeedlotStatusEntity;
import ca.bc.gov.backendstartapi.entity.seedlot.Seedlot;
import ca.bc.gov.backendstartapi.exception.JsonParsingException;
import ca.bc.gov.backendstartapi.exception.RevisionCountMismatchException;
import ca.bc.gov.backendstartapi.exception.SeedlotFormProgressNotFoundException;
import ca.bc.gov.backendstartapi.exception.SeedlotNotFoundException;
import ca.bc.gov.backendstartapi.exception.SeedlotStatusNotFoundException;
import ca.bc.gov.backendstartapi.repository.SaveSeedlotProgressRepositoryClassA;
import ca.bc.gov.backendstartapi.repository.SeedlotRepository;
import ca.bc.gov.backendstartapi.security.LoggedUserService;
Expand All @@ -31,6 +34,7 @@ public class SaveSeedlotFormService {
private final SaveSeedlotProgressRepositoryClassA saveSeedlotProgressRepositoryClassA;
private final SeedlotRepository seedlotRepository;
private final LoggedUserService loggedUserService;
private final SeedlotStatusService seedlotStatusService;

/** Saves the {@link SaveSeedlotFormDtoClassA} to table. */
public RevisionCountDto saveFormClassA(
Expand Down Expand Up @@ -63,19 +67,40 @@ public RevisionCountDto saveFormClassA(
parsedAllStepData,
parsedProgressStatus,
loggedUserService.createAuditCurrentUser());

// Update the seedlot status to pending from incomplete.
if (relatedSeedlot
.getSeedlotStatus()
.getSeedlotStatusCode()
.equals(Constants.INCOMPLETE_SEEDLOT_STATUS)) {
SparLog.info("Updating seedlot {} status from INC to PND", seedlotNumber);

Optional<SeedlotStatusEntity> seedLotStatusEntity =
seedlotStatusService.findById(Constants.PENDING_SEEDLOT_STATUS);

relatedSeedlot.setSeedlotStatus(
seedLotStatusEntity.orElseThrow(SeedlotStatusNotFoundException::new));
}
} else {
// Revision Count verification
Integer prevRevCount = data.revisionCount();
Integer currRevCount = optionalEntityToSave.get().getRevisionCount();

if (prevRevCount != null && !prevRevCount.equals(currRevCount)) {
// Conflict detected
SparLog.info(
"Save progress failed due to revision count mismatch, prev revision count: {}, curr"
+ " revision count: {}",
prevRevCount,
currRevCount);
throw new RevisionCountMismatchException();

// Revision Count verification only for pending seedlots
if (relatedSeedlot
.getSeedlotStatus()
.getSeedlotStatusCode()
.equals(Constants.PENDING_SEEDLOT_STATUS)) {

Integer prevRevCount = data.revisionCount();
Integer currRevCount = optionalEntityToSave.get().getRevisionCount();

if (prevRevCount != null && !prevRevCount.equals(currRevCount)) {
// Conflict detected
SparLog.info(
"Save progress failed due to revision count mismatch, prev revision count: {}, curr"
+ " revision count: {}",
prevRevCount,
currRevCount);
throw new RevisionCountMismatchException();
}
}

SparLog.info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,11 @@ public SeedlotStatusResponseDto createSeedlot(SeedlotCreateDto createDto) {

Seedlot seedlot = new Seedlot(nextSeedlotNumber(createDto.geneticClassCode()));

// Newly created seedlot has a status of INCOMPLETE, will change to PENDING once a row is
// created in the table seedlot_registration_a_class_save
Optional<SeedlotStatusEntity> seedLotStatusEntity =
seedlotStatusService.findById(Constants.CLASS_A_SEEDLOT_STATUS);
seedlot.setSeedlotStatus(seedLotStatusEntity.orElseThrow(InvalidSeedlotRequestException::new));
seedlotStatusService.findById(Constants.INCOMPLETE_SEEDLOT_STATUS);
seedlot.setSeedlotStatus(seedLotStatusEntity.orElseThrow(SeedlotStatusNotFoundException::new));

seedlot.setApplicantClientNumber(createDto.applicantClientNumber());
seedlot.setApplicantLocationCode(createDto.applicantLocationCode());
Expand All @@ -147,11 +149,11 @@ public SeedlotStatusResponseDto createSeedlot(SeedlotCreateDto createDto) {

Optional<GeneticClassEntity> classEntity =
geneticClassRepository.findById(createDto.geneticClassCode().toString());
seedlot.setGeneticClass(classEntity.orElseThrow(InvalidSeedlotRequestException::new));
seedlot.setGeneticClass(classEntity.orElseThrow(GeneticClassNotFoundException::new));

Optional<SeedlotSourceEntity> seedlotSourceEntity =
seedlotSourceRepository.findById(createDto.seedlotSourceCode());
seedlot.setSeedlotSource(seedlotSourceEntity.orElseThrow(InvalidSeedlotRequestException::new));
seedlot.setSeedlotSource(seedlotSourceEntity.orElseThrow(SeedlotSourceNotFoundException::new));

seedlot.setIntendedForCrownLand(createDto.toBeRegistrdInd());
seedlot.setSourceInBc(createDto.bcSourceInd());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import ca.bc.gov.backendstartapi.dto.SaveSeedlotFormDtoClassA;
import ca.bc.gov.backendstartapi.entity.SaveSeedlotProgressEntityClassA;
import ca.bc.gov.backendstartapi.entity.SeedlotStatusEntity;
import ca.bc.gov.backendstartapi.entity.seedlot.Seedlot;
import ca.bc.gov.backendstartapi.repository.SaveSeedlotProgressRepositoryClassA;
import ca.bc.gov.backendstartapi.repository.SeedlotRepository;
Expand All @@ -31,21 +32,29 @@ class SaveSeedlotFormServiceTest {
@Mock SaveSeedlotProgressRepositoryClassA saveSeedlotProgressRepositoryClassA;
@Mock SeedlotRepository seedlotRepository;
@Mock LoggedUserService loggedUserService;
@Mock SeedlotStatusService seedlotStatusService;

private SaveSeedlotFormService saveSeedlotFormService;

private static final String SEEDLOT_NUMBER = "678123";

private Seedlot testSeedlot = new Seedlot(SEEDLOT_NUMBER);

private SeedlotStatusEntity pndStatus = new SeedlotStatusEntity("PND", null, null);

@BeforeEach
void setup() {
saveSeedlotFormService =
new SaveSeedlotFormService(
saveSeedlotProgressRepositoryClassA, seedlotRepository, loggedUserService);
saveSeedlotProgressRepositoryClassA,
seedlotRepository,
loggedUserService,
seedlotStatusService);

when(loggedUserService.getLoggedUserInfo()).thenReturn(Optional.of(UserInfo.createDevUser()));

when(seedlotStatusService.findById(any())).thenReturn(Optional.of(pndStatus));

testSeedlot.setApplicantClientNumber(UserInfo.getDevClientNumber());
}

Expand All @@ -72,6 +81,8 @@ void saveSeedlotProgress_seedlotMissing_shouldFail() throws Exception {
@DisplayName("Save seedlot progress with missing seedlot should succeed.")
void saveSeedlotProgress_shouldSucceed() throws Exception {

testSeedlot.setSeedlotStatus(pndStatus);

when(seedlotRepository.findById(any())).thenReturn(Optional.of(testSeedlot));

when(saveSeedlotProgressRepositoryClassA.save(any()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@
import ca.bc.gov.backendstartapi.entity.seedlot.SeedlotOrchard;
import ca.bc.gov.backendstartapi.entity.seedlot.SeedlotOwnerQuantity;
import ca.bc.gov.backendstartapi.exception.ClientIdForbiddenException;
import ca.bc.gov.backendstartapi.exception.GeneticClassNotFoundException;
import ca.bc.gov.backendstartapi.exception.InvalidSeedlotRequestException;
import ca.bc.gov.backendstartapi.exception.SeedlotConflictDataException;
import ca.bc.gov.backendstartapi.exception.SeedlotNotFoundException;
import ca.bc.gov.backendstartapi.exception.SeedlotSourceNotFoundException;
import ca.bc.gov.backendstartapi.exception.SeedlotStatusNotFoundException;
import ca.bc.gov.backendstartapi.provider.Provider;
import ca.bc.gov.backendstartapi.repository.GeneticClassRepository;
import ca.bc.gov.backendstartapi.repository.SeedlotRepository;
Expand Down Expand Up @@ -178,9 +180,11 @@ void setup() {
@DisplayName("createSeedlotSuccessTest")
void createSeedlotTest_happyPath_shouldSucceed() {
when(seedlotRepository.findNextSeedlotNumber(anyInt(), anyInt())).thenReturn(63000);
String incStatusCode = "INC";

SeedlotStatusEntity statusEntity = new SeedlotStatusEntity("PND", "Pending", DATE_RANGE);
when(seedlotStatusService.findById("PND")).thenReturn(Optional.of(statusEntity));
SeedlotStatusEntity incStatusEntity =
new SeedlotStatusEntity(incStatusCode, "Incomplete", DATE_RANGE);
when(seedlotStatusService.findById(incStatusCode)).thenReturn(Optional.of(incStatusEntity));

SeedlotSourceEntity sourceEntity =
new SeedlotSourceEntity("TPT", "Tested Parent Trees", DATE_RANGE, null);
Expand Down Expand Up @@ -222,57 +226,54 @@ void createSeedlotTest_bClassSeedlot_shouldThrowException() {
void createSeedlotTest_noSeedlotStatus_shouldThrowException() {
when(seedlotRepository.findNextSeedlotNumber(anyInt(), anyInt())).thenReturn(63000);

when(seedlotStatusService.findById("PND")).thenReturn(Optional.empty());
when(seedlotStatusService.findById(any())).thenReturn(Optional.empty());

Exception exc =
Assertions.assertThrows(
InvalidSeedlotRequestException.class,
() -> {
seedlotService.createSeedlot(createSeedlotDto());
});

Assertions.assertEquals(BAD_REQUEST_STR, exc.getMessage());
Assertions.assertThrows(
SeedlotStatusNotFoundException.class,
() -> {
seedlotService.createSeedlot(createSeedlotDto());
});
}

@Test
@DisplayName("createSeedlotAClassWithoutGeneticClassEntity")
void createSeedlotTest_noGeneticClass_shouldThrowException() {
SeedlotStatusEntity statusEntity = new SeedlotStatusEntity("PND", "Pending", DATE_RANGE);
when(seedlotStatusService.findById("PND")).thenReturn(Optional.of(statusEntity));
String incStatusCode = "INC";

when(geneticClassRepository.findById("A")).thenReturn(Optional.empty());
SeedlotStatusEntity incStatusEntity =
new SeedlotStatusEntity(incStatusCode, "Incomplete", DATE_RANGE);
when(seedlotStatusService.findById(incStatusCode)).thenReturn(Optional.of(incStatusEntity));

Exception exc =
Assertions.assertThrows(
InvalidSeedlotRequestException.class,
() -> {
seedlotService.createSeedlot(createSeedlotDto());
});
when(geneticClassRepository.findById("A")).thenReturn(Optional.empty());

Assertions.assertEquals(BAD_REQUEST_STR, exc.getMessage());
Assertions.assertThrows(
GeneticClassNotFoundException.class,
() -> {
seedlotService.createSeedlot(createSeedlotDto());
});
}

@Test
@DisplayName("createSeedlotAClassWithoutSeedlotSourceEntity")
void createSeedlotTest_noSeedlotSource_shouldThrowException() {
when(seedlotRepository.findNextSeedlotNumber(anyInt(), anyInt())).thenReturn(63000);

SeedlotStatusEntity statusEntity = new SeedlotStatusEntity("PND", "Pending", DATE_RANGE);
when(seedlotStatusService.findById("PND")).thenReturn(Optional.of(statusEntity));
String incStatusCode = "INC";

SeedlotStatusEntity incStatusEntity =
new SeedlotStatusEntity(incStatusCode, "Incomplete", DATE_RANGE);
when(seedlotStatusService.findById(incStatusCode)).thenReturn(Optional.of(incStatusEntity));

GeneticClassEntity classEntity = new GeneticClassEntity("A", "A class seedlot", DATE_RANGE);
when(geneticClassRepository.findById("A")).thenReturn(Optional.of(classEntity));

when(seedlotSourceRepository.findById("TPT")).thenReturn(Optional.empty());

Exception exc =
Assertions.assertThrows(
InvalidSeedlotRequestException.class,
() -> {
seedlotService.createSeedlot(createSeedlotDto());
});

Assertions.assertEquals(BAD_REQUEST_STR, exc.getMessage());
Assertions.assertThrows(
SeedlotSourceNotFoundException.class,
() -> {
seedlotService.createSeedlot(createSeedlotDto());
});
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ describe('A Class Seedlot Registration form, Ownership', () => {
cy.saveSeedlotRegFormProgress();
});

it.only('Funding source and method of payment default values and change the values', () => {
it('Funding source and method of payment default values and change the values', () => {
// Expand the funding source combo box
cy.get('#ownership-funding-source-0')
.should('have.value', '')
Expand Down
2 changes: 1 addition & 1 deletion frontend/cypress/e2e/smoke-test/seedlot-dashboard.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('Seedlot Dashboard test', () => {
const seedlotNumber = sNumber as string;

cy.get(`#seedlot-table-cell-${seedlotNumber}-seedlotSpecies`).should('have.text', species);
cy.get(`#seedlot-table-cell-${seedlotNumber}-seedlotStatus`).should('have.text', 'Pending');
cy.get(`#seedlot-table-cell-${seedlotNumber}-seedlotStatus`).should('have.text', 'Incomplete');
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion frontend/cypress/e2e/smoke-test/seedlot-detail.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('Seedlot detail page', () => {
cy.contains('p.seedlot-summary-info-label', 'Status')
.next()
.children('span')
.should('have.text', 'Pending');
.should('have.text', 'Incomplete');

cy.contains('p.seedlot-summary-info-label', 'Approved at')
.siblings('p.seedlot-summary-info-value')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Column, Row, FlexGrid } from '@carbon/react';

import ReadOnlyInput from '../../ReadOnlyInput';
import ClassAContext from '../../../views/Seedlot/ContextContainerClassA/context';
import { utcToIsoSlashStyle } from '../../../utils/DateUtils';

const AuditInfo = () => {
const {
Expand All @@ -29,7 +30,7 @@ const AuditInfo = () => {
<ReadOnlyInput
id="created-at"
label="Created at:"
value={seedlotData?.auditInformation.entryTimestamp}
value={utcToIsoSlashStyle(seedlotData?.auditInformation.entryTimestamp)}
showSkeleton={isFetchingData}
/>
</Column>
Expand All @@ -47,7 +48,7 @@ const AuditInfo = () => {
<ReadOnlyInput
id="last-updated-at"
label="Last updated at:"
value={seedlotData?.auditInformation.updateTimestamp}
value={utcToIsoSlashStyle(seedlotData?.auditInformation.updateTimestamp)}
showSkeleton={isFetchingData}
/>
</Column>
Expand All @@ -65,7 +66,7 @@ const AuditInfo = () => {
<ReadOnlyInput
id="submitted-at"
label="Submitted at:"
value={seedlotData?.declarationOfTrueInformationTimestamp}
value={utcToIsoSlashStyle(seedlotData?.declarationOfTrueInformationTimestamp)}
showSkeleton={isFetchingData}
/>
</Column>
Expand All @@ -83,7 +84,7 @@ const AuditInfo = () => {
<ReadOnlyInput
id="approved-at"
label="Approved at:"
value={seedlotData?.approvedTimestamp ?? undefined}
value={utcToIsoSlashStyle(seedlotData?.approvedTimestamp)}
showSkeleton={isFetchingData}
/>
</Column>
Expand Down
1 change: 0 additions & 1 deletion frontend/src/utils/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export const utcToApStyle = (utcDate: string | null | undefined): string => {
* Convert UTC timestamp to ISO 8601 style with slashes (e.g. 2023/10/26)
*/
export const utcToIsoSlashStyle = (utcDate: string | null | undefined): string => {
console.log(utcDate);
if (!utcDate) {
return '';
}
Expand Down
25 changes: 16 additions & 9 deletions frontend/src/views/Seedlot/SeedlotRegFormClassA/RegPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
InlineLoading,
InlineNotification,
ActionableNotification,
Loading
Loading,
ProgressIndicatorSkeleton
} from '@carbon/react';
import { ArrowRight } from '@carbon/icons-react';
import { useNavigate } from 'react-router-dom';
Expand Down Expand Up @@ -89,17 +90,23 @@ const RegPage = () => {
</Row>
<Row>
<Column className="seedlot-registration-progress">
<SeedlotRegistrationProgress
progressStatus={
seedlotData?.seedlotStatus.seedlotStatusCode === 'PND' || seedlotData?.seedlotStatus.seedlotStatusCode === 'INC'
{
seedlotData
? (
<SeedlotRegistrationProgress
progressStatus={
seedlotData.seedlotStatus.seedlotStatusCode === 'PND' || seedlotData.seedlotStatus.seedlotStatusCode === 'INC'
? progressStatus
: completeProgressConfig
}
interactFunction={(e: number) => {
updateProgressStatus(e, formStep);
setStep((e - formStep));
}}
/>
interactFunction={(e: number) => {
updateProgressStatus(e, formStep);
setStep((e - formStep));
}}
/>
)
: <ProgressIndicatorSkeleton />
}
</Column>
</Row>
{
Expand Down
Loading

0 comments on commit 1799204

Please sign in to comment.