Skip to content

Commit

Permalink
Adding smaller features (#470)
Browse files Browse the repository at this point in the history
* added basic delete

* added delete button

* removed todo

* added delete test

* resorted buttons

* added quick-prolong button

* added e2e test

* fixed menu filtering

* removed todo

* removed todo

* added invalidate button

* fixed searchtest

* fixed test

* fixed test

* splitted testdata

* removed todo
  • Loading branch information
stephanprantl committed Mar 18, 2023
1 parent 57ddfbe commit e78c227
Show file tree
Hide file tree
Showing 19 changed files with 352 additions and 141 deletions.
11 changes: 3 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
# TODO

* Add buttons on detailpage
* "Disable Customer (dropdown select?) --> today, yesterday"
* Prolong customer (dropdown?) --> 1 month, 2 months?
* Delete customer
* General
* Unify errormsg handling (panel on top) ?
* Toast messages?
* customer creation
* add employer field also for additional persons
* Fix autofocus: https://davidmcintosh.medium.com/auto-focusing-an-angular-input-the-easy-way-part-1-dcb1799e025f
* Improve rendering / wait for data
* customer-detail, dashboard (distribution state)
* Add global app-state per WS (e.g. LCM) and push state change through application
* Add routing resolver to pre-fetch data before rendering (https://medium.com/@redin.gaetan/angular-for-every-one-resolver-c900c8f7672a)

### Open things (to be discussed)

Expand Down
8 changes: 4 additions & 4 deletions _http-calls/customers.http
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,21 @@ Content-Type: application/json
}

### Get customer 100

GET {{baseApiPath}}/customers/100
Content-Type: application/json

### Get masterdata pdf
### Delete customer 100
DELETE {{baseApiPath}}/customers/100
Content-Type: application/json

### Get masterdata pdf
GET {{baseApiPath}}/customers/100/generate-pdf?type=MASTERDATA
Content-Type: application/json

### Get idcard pdf

GET {{baseApiPath}}/customers/100/generate-pdf?type=IDCARD
Content-Type: application/json

### Get combined pdf

GET {{baseApiPath}}/customers/100/generate-pdf?type=COMBINED
Content-Type: application/json
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ interface CustomerRepository : JpaRepository<CustomerEntity, Long> {
@Param("lastname") lastname: String
): List<CustomerEntity>

fun deleteByCustomerId(customerId: Long)
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ class CustomerController(
return CustomerListResponse(items = customerItems)
}

@DeleteMapping("/{customerId}")
fun deleteCustomer(@PathVariable("customerId") customerId: Long) {
if (!service.existsByCustomerId(customerId)) {
throw ResponseStatusException(HttpStatus.NOT_FOUND)
}

service.deleteCustomerByCustomerId(customerId)
}

@GetMapping("/{customerId}/generate-pdf", produces = [MediaType.APPLICATION_PDF_VALUE])
fun generatePdf(
@PathVariable("customerId") customerId: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import at.wrk.tafel.admin.backend.modules.customer.income.IncomeValidatorService
import at.wrk.tafel.admin.backend.modules.customer.masterdata.CustomerPdfService
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class CustomerService(
Expand Down Expand Up @@ -215,6 +216,11 @@ class CustomerService(
)
}

@Transactional
fun deleteCustomerByCustomerId(customerId: Long) {
customerRepository.deleteByCustomerId(customerId)
}

}

@ExcludeFromTestCoverage
Expand Down
26 changes: 19 additions & 7 deletions backend/src/main/resources/db-migration-testdata/testdata.sql
Original file line number Diff line number Diff line change
Expand Up @@ -84,31 +84,43 @@ VALUES (5001, NOW(), NOW(), 500, 'SCANNER');
INSERT INTO customers (id, created_at, updated_at, customer_id, user_id, firstname, lastname, birth_date, country_id,
address_street, address_houseNumber, address_stairway, address_door, address_postalCode,
address_city, telephone_number, email, employer, income, income_due, valid_until)
values (0, NOW(), NOW(), 100, 100, 'Max Single', 'Mustermann', '1980-01-01', 1, 'Erdberg', 1, null, null, '1030', 'Wien',
values (100, NOW(), NOW(), 100, 100, 'Max Single', 'Mustermann', '1980-01-01', 1, 'Erdberg', 1, null, null, '1030', 'Wien',
null, null, 'Stadt Wien', 123.00, '2999-12-31', '2999-12-31');
INSERT INTO customers (id, created_at, updated_at, customer_id, user_id, firstname, lastname, birth_date, country_id,
address_street, address_houseNumber, address_stairway, address_door, address_postalCode,
address_city, telephone_number, email, employer, income, income_due, valid_until)
values (1, NOW(), NOW(), 101, 100, 'Eva', 'Musterfrau', '1990-01-01', 2, 'Erdberg', 2, '1', '20', '1010', 'Wien',
values (101, NOW(), NOW(), 101, 100, 'Eva', 'Musterfrau', '1990-01-01', 2, 'Erdberg', 2, '1', '20', '1010', 'Wien',
'00436645678953', 'eva.musterfrau@wrk.at', 'Rotes Kreuz Wien', 456.00, '2999-12-31', '2999-12-31');
INSERT INTO customers_addpersons (id, created_at, updated_at, customer_id, firstname, lastname, birth_date, income,
income_due, country_id)
values (1, NOW(), NOW(), 1, 'Child 1', 'Musterfrau', '2000-01-01', 500, '2999-12-31', 1);
values (1011, NOW(), NOW(), 101, 'Child 1', 'Musterfrau', '2000-01-01', 500, '2999-12-31', 1);
INSERT INTO customers_addpersons (id, created_at, updated_at, customer_id, firstname, lastname, birth_date, income,
income_due, country_id)
values (2, NOW(), NOW(), 1, 'Child 2', 'Musterfrau', CURRENT_DATE - interval '8 year', 0, null, 1);
values (1012, NOW(), NOW(), 101, 'Child 2', 'Musterfrau', CURRENT_DATE - interval '8 year', 0, null, 1);
INSERT INTO customers_addpersons (id, created_at, updated_at, customer_id, firstname, lastname, birth_date, income,
income_due, country_id)
values (3, NOW(), NOW(), 1, 'Child 3', 'Musterfrau', CURRENT_DATE - interval '2 year', null, null, 1);
values (1013, NOW(), NOW(), 101, 'Child 3', 'Musterfrau', CURRENT_DATE - interval '2 year', null, null, 1);

INSERT INTO customers (id, created_at, updated_at, customer_id, user_id, firstname, lastname, birth_date, country_id,
address_street, address_houseNumber, address_stairway, address_door, address_postalCode,
address_city, telephone_number, email, employer, income, income_due, valid_until)
values (102, NOW(), NOW(), 102, 100, 'John', 'Doe', '1980-01-01', 1, 'Erdberg', 1, null, null, '1030', 'Wien',
null, null, 'Stadt Wien', 123.00, '2999-12-31', '2999-12-31');

INSERT INTO customers (id, created_at, updated_at, customer_id, user_id, firstname, lastname, birth_date, country_id,
address_street, address_houseNumber, address_stairway, address_door, address_postalCode,
address_city, telephone_number, email, employer, income, income_due, valid_until)
values (201, NOW(), NOW(), 201, 100, '1', 'e2e-search', '1980-01-01', 1, 'Erdberg', 1, null, '10', '1030', 'Wien', null, null,
'Stadt Wien', 123.00, '2999-12-31', '2999-12-31');
INSERT INTO customers (id, created_at, updated_at, customer_id, user_id, firstname, lastname, birth_date, country_id,
address_street, address_houseNumber, address_stairway, address_door, address_postalCode,
address_city, telephone_number, email, employer, income, income_due, valid_until)
values (4, NOW(), NOW(), 201, 100, '1', 'e2esearch', '1980-01-01', 1, 'Erdberg', 1, null, '10', '1030', 'Wien', null, null,
values (202, NOW(), NOW(), 202, 100, '2', 'e2e-search', '1980-01-01', 1, 'Erdberg', 1, null, '10', '1030', 'Wien', null, null,
'Stadt Wien', 123.00, '2999-12-31', '2999-12-31');
INSERT INTO customers (id, created_at, updated_at, customer_id, user_id, firstname, lastname, birth_date, country_id,
address_street, address_houseNumber, address_stairway, address_door, address_postalCode,
address_city, telephone_number, email, employer, income, income_due, valid_until)
values (5, NOW(), NOW(), 202, 100, '2', 'e2esearch', '1980-01-01', 1, 'Erdberg', 1, null, '10', '1030', 'Wien', null, null,
values (300, NOW(), NOW(), 300, 100, 'e2e-delete', 'e2e-delete', '1980-01-01', 1, 'Erdberg', 1, null, '10', '1030', 'Wien', null, null,
'Stadt Wien', 123.00, '2999-12-31', '2999-12-31');

-- static values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,26 @@ class CustomerControllerTest {
assertThat(customer).isEqualTo(testCustomer)
}

@Test
fun `delete customer - doesnt exist`() {
every { service.existsByCustomerId(testCustomer.id!!) } returns false

val exception =
assertThrows<ResponseStatusException> { controller.deleteCustomer(testCustomer.id!!) }

assertThat(exception.statusCode).isEqualTo(HttpStatus.NOT_FOUND)
verify { service.existsByCustomerId(testCustomer.id!!) }
}

@Test
fun `delete customer - exists`() {
every { service.existsByCustomerId(testCustomer.id!!) } returns true

controller.deleteCustomer(testCustomer.id!!)

verify { service.existsByCustomerId(testCustomer.id!!) }
}

@Test
fun `get customers - mapped correctly`() {
every { service.getCustomers(any(), any()) } returns listOf(testCustomer)
Expand Down
49 changes: 46 additions & 3 deletions frontend/src/main/webapp/cypress/e2e/customer-detail.cy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as path from 'path';
import * as moment from 'moment';

// TODO optimize structure

Expand All @@ -19,7 +20,7 @@ describe('Customer Detail', () => {
cy.byTestId('printMenuButton').click();
cy.byTestId('printMasterdataButton').click();

const downloadsFolder = Cypress.config('downloadsFolder')
const downloadsFolder = Cypress.config('downloadsFolder');
const downloadedFilename = path.join(downloadsFolder, 'stammdaten-101-musterfrau-eva.pdf');

cy.readFile(downloadedFilename, 'binary', {timeout: 15000})
Expand All @@ -42,10 +43,52 @@ describe('Customer Detail', () => {
it('edit customer', () => {
cy.visit('/#/kunden/detail/101');

cy.intercept('/*/customers/101').as('getCustomer');
cy.wait('@getCustomer').byTestId('editCustomerButton').click();
cy.byTestId('editCustomerButton').click();

cy.url({timeout: 10000}).should('include', '/kunden/bearbeiten/101');
});

it('delete customer', () => {
cy.visit('/#/kunden/detail/300');

cy.byTestId('deleteCustomerButton').click();

cy.byTestId('deletecustomer-modal').should('be.visible');
cy.byTestId('deletecustomer-modal').within(() => {
cy.byTestId('cancelButton').click();
});

cy.byTestId('deletecustomer-modal').should('not.be.visible');

cy.byTestId('deleteCustomerButton').click();
cy.byTestId('deletecustomer-modal').within(() => {
cy.byTestId('okButton').click();
});

cy.url({timeout: 10000}).should('include', '/kunden/suchen');
});

it('prolong customer', () => {
cy.visit('/#/kunden/detail/100');

let validDateString;
cy.byTestId('validUntilText').then(($value) => {
validDateString = $value.text();
const expectedValidDate = moment(validDateString, 'DD.MM.YYYY').add(3, 'months').endOf('day').format('DD.MM.YYYY');

cy.byTestId('prolongButton').click();
cy.byTestId('prolongThreeMonthsButton').click();

cy.byTestId('validUntilText').should('have.text', expectedValidDate);
});
});

it('invalidate customer', () => {
cy.visit('/#/kunden/detail/101');

cy.byTestId('invalidateCustomerButton').click();

cy.byTestId('validUntilText').should('have.text', moment().subtract(1, 'day').endOf('day').format('DD.MM.YYYY'));
});

});
8 changes: 4 additions & 4 deletions frontend/src/main/webapp/cypress/e2e/customer-edit.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ describe('Customer Edit', () => {
});

it('customerId correct', () => {
cy.visit('/#/kunden/bearbeiten/101');
cy.byTestId('customerIdInput').should('have.value', '101');
cy.visit('/#/kunden/bearbeiten/102');
cy.byTestId('customerIdInput').should('have.value', '102');
});

it('customer updated', () => {
cy.visit('/#/kunden/bearbeiten/101');
cy.visit('/#/kunden/bearbeiten/102');
cy.byTestId('save-button').click();

cy.url().should('contain', '/kunden/detail/101');
cy.url().should('contain', '/kunden/detail/102');

// TODO change actual data (but for that create a new dedicated customer beforehand)
});
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/main/webapp/cypress/e2e/customer-search.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ describe('Customer Search', () => {
cy.byTestId('search-button').should('be.disabled');
});

it('search with customerId', () => {
it('search by customerId', () => {
cy.byTestId('customerIdText').type('100');
cy.byTestId('showcustomer-button').click();

cy.url().should('include', '/kunden/detail/100');
});

it('search with lastname and firstname', () => {
cy.byTestId('lastnameText').type('e2esearch');
it('search by lastname and firstname', () => {
cy.byTestId('lastnameText').type('e2e-search');
cy.byTestId('firstnameText').type('1');
cy.byTestId('search-button').click();

Expand All @@ -31,8 +31,8 @@ describe('Customer Search', () => {
cy.url().should('include', '/kunden/detail/201');
});

it('search with lastname only', () => {
cy.byTestId('lastnameText').type('e2esearch');
it('search by lastname only', () => {
cy.byTestId('lastnameText').type('e2e-search');
cy.byTestId('search-button').click();

cy.byTestId('searchresult-table').should('be.visible');
Expand All @@ -44,7 +44,7 @@ describe('Customer Search', () => {
cy.url().should('include', '/kunden/detail/201');
});

it('search with firstname only', () => {
it('search by firstname only', () => {
cy.byTestId('firstnameText').type('2');
cy.byTestId('search-button').click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,12 @@ describe('CustomerApiService', () => {
httpMock.verify();
});

it('delete customer', () => {
apiService.deleteCustomer(1).subscribe();

const req = httpMock.expectOne({method: 'DELETE', url: '/customers/1'});
req.flush(null);
httpMock.verify();
});

});
6 changes: 5 additions & 1 deletion frontend/src/main/webapp/src/app/api/customer-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ export class CustomerApiService {
return this.http.post<CustomerData>('/customers', data);
}

updateCustomer(data: CustomerData): Observable<any> {
updateCustomer(data: CustomerData): Observable<CustomerData> {
return this.http.post<CustomerData>(`/customers/${data.id}`, data);
}

deleteCustomer(customerId: number): Observable<void> {
return this.http.delete<void>(`/customers/${customerId}`);
}

getCustomer(id: number): Observable<CustomerData> {
return this.http.get<CustomerData>('/customers/' + id);
}
Expand Down
Loading

0 comments on commit e78c227

Please sign in to comment.