| @@ -1870,14 +1870,10 @@ components: | |||
| deprecated: false | |||
| properties: | |||
| zone: | |||
| readOnly: true | |||
| type: string | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| $ref: '#/components/schemas/Zone' | |||
| name: | |||
| type: string | |||
| zoneName: | |||
| readOnly: true | |||
| code: | |||
| type: string | |||
| createdAt: | |||
| readOnly: true | |||
| @@ -1887,6 +1883,7 @@ components: | |||
| format: date-time | |||
| required: | |||
| - name | |||
| - code | |||
| Location.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -1916,12 +1913,10 @@ components: | |||
| readOnly: true | |||
| type: string | |||
| zone: | |||
| readOnly: true | |||
| $ref: '#/components/schemas/Zone.jsonld' | |||
| name: | |||
| type: string | |||
| zoneName: | |||
| readOnly: true | |||
| code: | |||
| type: string | |||
| createdAt: | |||
| readOnly: true | |||
| @@ -1931,6 +1926,7 @@ components: | |||
| format: date-time | |||
| required: | |||
| - name | |||
| - code | |||
| MediaObject.jsonld-media_object.read: | |||
| type: object | |||
| description: '' | |||
| @@ -1973,9 +1969,12 @@ components: | |||
| deprecated: false | |||
| required: | |||
| - name | |||
| - code | |||
| properties: | |||
| name: | |||
| type: string | |||
| code: | |||
| type: string | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -1988,6 +1987,7 @@ components: | |||
| deprecated: false | |||
| required: | |||
| - name | |||
| - code | |||
| properties: | |||
| '@context': | |||
| readOnly: true | |||
| @@ -2014,6 +2014,8 @@ components: | |||
| type: string | |||
| name: | |||
| type: string | |||
| code: | |||
| type: string | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -2604,14 +2606,14 @@ components: | |||
| deprecated: false | |||
| required: | |||
| - name | |||
| - code | |||
| properties: | |||
| name: | |||
| type: string | |||
| company: | |||
| readOnly: true | |||
| code: | |||
| type: string | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| company: | |||
| $ref: '#/components/schemas/ShippingCompany' | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| @@ -2624,6 +2626,7 @@ components: | |||
| deprecated: false | |||
| required: | |||
| - name | |||
| - code | |||
| properties: | |||
| '@context': | |||
| readOnly: true | |||
| @@ -2650,8 +2653,9 @@ components: | |||
| type: string | |||
| name: | |||
| type: string | |||
| code: | |||
| type: string | |||
| company: | |||
| readOnly: true | |||
| $ref: '#/components/schemas/ShippingCompany.jsonld' | |||
| createdAt: | |||
| readOnly: true | |||
| @@ -118,4 +118,33 @@ export class SearchSelectComponent implements OnInit, AfterViewInit { | |||
| } as ListColDefinition, | |||
| ]; | |||
| } | |||
| public static getDefaultColDefShippingCompanies(subResource?: string): ListColDefinition[] { | |||
| return [ | |||
| { | |||
| name: 'name', | |||
| text: 'common.name', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'code', | |||
| text: 'common.code', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'code', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| ]; | |||
| } | |||
| } | |||
| @@ -3,14 +3,14 @@ import { FormGroup, FormControl, Validators } from '@angular/forms'; | |||
| export const locationForm = new FormGroup({ | |||
| zone: new FormControl(null, []), | |||
| name: new FormControl(null, [Validators.required]), | |||
| zoneName: new FormControl(null, []), | |||
| code: new FormControl(null, [Validators.required]), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| export const locationJsonldForm = new FormGroup({ | |||
| zone: new FormControl(null, []), | |||
| name: new FormControl(null, [Validators.required]), | |||
| zoneName: new FormControl(null, []), | |||
| code: new FormControl(null, [Validators.required]), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -20,11 +20,13 @@ export const mediaObjectJsonldMediaObjectReadForm = new FormGroup({ | |||
| export const shippingCompanyForm = new FormGroup({ | |||
| name: new FormControl(null, [Validators.required]), | |||
| code: new FormControl(null, [Validators.required]), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| export const shippingCompanyJsonldForm = new FormGroup({ | |||
| name: new FormControl(null, [Validators.required]), | |||
| code: new FormControl(null, [Validators.required]), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -140,12 +142,14 @@ export const userTripWorkLogJsonldForm = new FormGroup({ | |||
| export const vesselForm = new FormGroup({ | |||
| name: new FormControl(null, [Validators.required]), | |||
| code: new FormControl(null, [Validators.required]), | |||
| company: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| export const vesselJsonldForm = new FormGroup({ | |||
| name: new FormControl(null, [Validators.required]), | |||
| code: new FormControl(null, [Validators.required]), | |||
| company: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -20,7 +20,7 @@ import {LocationNewComponent} from "@app/_views/location/location-new/location-n | |||
| export class LocationListComponent implements OnInit, AfterViewInit { | |||
| @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; | |||
| protected readonly LocationNewComponent = LocationNewComponent; | |||
| protected listColDefinitions!: ListColDefinition[]; | |||
| constructor( | |||
| @@ -38,19 +38,28 @@ export class LocationListComponent implements OnInit, AfterViewInit { | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'code', | |||
| text: 'common.code', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'code', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'zone', | |||
| text: 'model.zone', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| subResource: 'zone', | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'creationDate', | |||
| text: 'common.creation_date', | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'creationDate', | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| @@ -87,6 +96,5 @@ export class LocationListComponent implements OnInit, AfterViewInit { | |||
| this.router.navigate(['/' + ROUTE_LOCATIONS, this.appHelperService.extractId(location.id)]); | |||
| } | |||
| protected readonly ZoneNewComponent = ZoneNewComponent; | |||
| protected readonly LocationNewComponent = LocationNewComponent; | |||
| } | |||
| @@ -5,20 +5,25 @@ | |||
| <label for="name" class="form-label">{{ 'common.name' | translate }}*:</label> | |||
| <input type="text" class="form-control" id="name" formControlName="name" required/> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label for="code" class="form-label">{{ 'common.code' | translate }}*:</label> | |||
| <input type="text" class="form-control" id="code" formControlName="code" required/> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label for="zone" class="form-label">{{ 'model.zone' | translate }}:</label> | |||
| <app-search-select #zoneSearchSelect | |||
| [formId]="'zoneIri'" | |||
| [formLabelLangKey]="'model.zone'" | |||
| [documentForm]="zoneForm" | |||
| [getDataFunction]="getZones" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="SearchSelectComponent.getDefaultColDefZones()" | |||
| <app-search-select #locationSearchSelect | |||
| [formId]="'zone'" | |||
| [formLabelLangKey]="'model.zone'" | |||
| [documentForm]="form" | |||
| [getDataFunction]="getZones" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="zoneColDefinitions" | |||
| > | |||
| </app-search-select> | |||
| <input id="zone" type="hidden" formControlName="zone"/> | |||
| </div> | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid">{{ 'basic.send' | translate }} | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid"> | |||
| {{ 'basic.send' | translate }} | |||
| </button> | |||
| </form> | |||
| </div> | |||
| @@ -1,28 +1,38 @@ | |||
| import {Component, EventEmitter, Input, Output} from '@angular/core'; | |||
| import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | |||
| import {AbstractCreateDataComponent} from "@app/_interfaces/AbstractCreateDataComponent"; | |||
| import {LocationJsonld, LocationService, ZoneService} from "@app/core/api/v1"; | |||
| import {ModalStatus} from "@app/_helpers/modal.states"; | |||
| import {FormGroup} from "@angular/forms"; | |||
| import {locationForm, zoneForm} from "@app/_forms/apiForms"; | |||
| import {locationForm} from "@app/_forms/apiForms"; | |||
| import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; | |||
| import {SearchSelectComponent} from "@app/_components/search-select/search-select.component"; | |||
| import {ListColDefinition} from "@app/_components/list/list-col-definition"; | |||
| @Component({ | |||
| selector: 'app-location-new', | |||
| templateUrl: './location-new.component.html', | |||
| styleUrl: './location-new.component.scss' | |||
| selector: 'app-location-new', | |||
| templateUrl: './location-new.component.html', | |||
| styleUrl: './location-new.component.scss' | |||
| }) | |||
| export class LocationNewComponent extends AbstractCreateDataComponent<LocationJsonld>{ | |||
| export class LocationNewComponent extends AbstractCreateDataComponent<LocationJsonld> implements OnInit { | |||
| @Input() public override data!: LocationJsonld; | |||
| @Output() public override submit: EventEmitter<ModalStatus> = new EventEmitter<ModalStatus>(); | |||
| protected readonly SearchSelectComponent = SearchSelectComponent; | |||
| override form: FormGroup = locationForm; | |||
| protected zoneColDefinitions: ListColDefinition[]; | |||
| constructor( | |||
| private locationService: LocationService, | |||
| private zoneService: ZoneService, | |||
| ) { | |||
| super(); | |||
| this.zoneColDefinitions = SearchSelectComponent.getDefaultColDefZones(); | |||
| } | |||
| override ngOnInit() { | |||
| if (this.data) { | |||
| this.form.patchValue(this.data); | |||
| } | |||
| } | |||
| getInitialData(): LocationJsonld { | |||
| @@ -39,6 +49,8 @@ export class LocationNewComponent extends AbstractCreateDataComponent<LocationJs | |||
| onSubmit() { | |||
| if (this.form.valid) { | |||
| console.log(this.form); | |||
| console.log(this.form.value as LocationJsonld); | |||
| this.locationService.locationsPost( | |||
| this.form.value as LocationJsonld | |||
| ).subscribe( | |||
| @@ -50,6 +62,5 @@ export class LocationNewComponent extends AbstractCreateDataComponent<LocationJs | |||
| } | |||
| } | |||
| protected readonly zoneForm = zoneForm; | |||
| protected readonly SearchSelectComponent = SearchSelectComponent; | |||
| } | |||
| } | |||
| @@ -5,5 +5,6 @@ | |||
| [onNavigateToDetailsFunction]="navigateToZoneDetail" | |||
| [onSortFunction]="onSortChange" | |||
| [listColDefinitions]="listColDefinitions" | |||
| [createDataComponent]="ShippingCompanyNewComponent" | |||
| ></app-list> | |||
| </div> | |||
| @@ -10,7 +10,11 @@ import {AppHelperService} from "@app/_helpers/app-helper.service"; | |||
| import {FilterBarComponent} from "@app/_components/filter-bar/filter-bar.component"; | |||
| import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; | |||
| import {Sort} from "@angular/material/sort"; | |||
| import {ROUTE_SHIPPING_COMPANIES, ROUTE_VESSELS} from "@app/app-routing.module"; | |||
| import {ROUTE_SHIPPING_COMPANIES} from "@app/app-routing.module"; | |||
| import { | |||
| ShippingCompanyNewComponent | |||
| } from "@app/_views/shipping-company/shipping-company-new/shipping-company-new.component"; | |||
| import {ZoneNewComponent} from "@app/_views/zone/zone-new/zone-new.component"; | |||
| @Component({ | |||
| selector: 'app-shipping-company-list', | |||
| @@ -20,6 +24,7 @@ import {ROUTE_SHIPPING_COMPANIES, ROUTE_VESSELS} from "@app/app-routing.module"; | |||
| export class ShippingCompanyListComponent { | |||
| @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; | |||
| protected readonly ShippingCompanyNewComponent = ShippingCompanyNewComponent; | |||
| protected listColDefinitions!: ListColDefinition[]; | |||
| constructor( | |||
| @@ -36,12 +41,21 @@ export class ShippingCompanyListComponent { | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'code', | |||
| text: 'common.code', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'code', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'creationDate', | |||
| text: 'common.creation_date', | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'creationDate', | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| @@ -77,4 +91,5 @@ export class ShippingCompanyListComponent { | |||
| const shippingCompany: ShippingCompanyJsonld = element as ShippingCompanyJsonld; | |||
| this.router.navigate(['/' + ROUTE_SHIPPING_COMPANIES, this.appHelperService.extractId(shippingCompany.id)]); | |||
| } | |||
| protected readonly ZoneNewComponent = ZoneNewComponent; | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| <h2>{{ 'basic.new' | translate }} {{ 'model.shipping_company' | translate }}</h2> | |||
| <div class="spt-form"> | |||
| <form [formGroup]="form" (ngSubmit)="onSubmit()"> | |||
| <div class="mb-3"> | |||
| <label for="name" class="form-label">{{ 'common.name' | translate }}*:</label> | |||
| <input type="text" class="form-control" id="name" formControlName="name" required/> | |||
| </div> | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid">{{ 'basic.send' | translate }} | |||
| </button> | |||
| </form> | |||
| </div> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { ShippingCompanyNewComponent } from './shipping-company-new.component'; | |||
| describe('ShippingCompanyNewComponent', () => { | |||
| let component: ShippingCompanyNewComponent; | |||
| let fixture: ComponentFixture<ShippingCompanyNewComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ShippingCompanyNewComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(ShippingCompanyNewComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,41 @@ | |||
| import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | |||
| import {AbstractCreateDataComponent} from "@app/_interfaces/AbstractCreateDataComponent"; | |||
| import {LocationJsonld, ShippingCompanyJsonld, ShippingCompanyService} from "@app/core/api/v1"; | |||
| import {ModalStatus} from "@app/_helpers/modal.states"; | |||
| import {FormGroup} from "@angular/forms"; | |||
| import {shippingCompanyForm} from "@app/_forms/apiForms"; | |||
| @Component({ | |||
| selector: 'app-shipping-company-new', | |||
| templateUrl: './shipping-company-new.component.html', | |||
| styleUrl: './shipping-company-new.component.scss' | |||
| }) | |||
| export class ShippingCompanyNewComponent extends AbstractCreateDataComponent<ShippingCompanyJsonld> implements OnInit { | |||
| @Input() public override data!: ShippingCompanyJsonld; | |||
| @Output() public override submit: EventEmitter<ModalStatus> = new EventEmitter<ModalStatus>(); | |||
| override form: FormGroup = shippingCompanyForm; | |||
| constructor( | |||
| private shippingCompanyService: ShippingCompanyService | |||
| ) { | |||
| super(); | |||
| } | |||
| getInitialData(): ShippingCompanyJsonld { | |||
| return {} as ShippingCompanyJsonld; | |||
| } | |||
| onSubmit() { | |||
| if (this.form.valid) { | |||
| this.shippingCompanyService.shippingCompaniesPost( | |||
| this.form.value as ShippingCompanyJsonld | |||
| ).subscribe( | |||
| data => { | |||
| this.form.reset(); | |||
| this.submit.emit(ModalStatus.Submitted); | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| @@ -5,5 +5,6 @@ | |||
| [onNavigateToDetailsFunction]="navigateToVesselDetail" | |||
| [onSortFunction]="onSortChange" | |||
| [listColDefinitions]="listColDefinitions" | |||
| [createDataComponent]="VesselNewComponent" | |||
| ></app-list> | |||
| </div> | |||
| @@ -8,6 +8,7 @@ import {FilterBarComponent} from "@app/_components/filter-bar/filter-bar.compone | |||
| import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; | |||
| import {Sort} from "@angular/material/sort"; | |||
| import {ROUTE_VESSELS} from "@app/app-routing.module"; | |||
| import {VesselNewComponent} from "@app/_views/vessel/vessel-new/vessel-new.component"; | |||
| @Component({ | |||
| selector: 'app-vessel-list', | |||
| @@ -17,6 +18,7 @@ import {ROUTE_VESSELS} from "@app/app-routing.module"; | |||
| export class VesselListComponent { | |||
| @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; | |||
| protected readonly VesselNewComponent = VesselNewComponent; | |||
| protected listColDefinitions!: ListColDefinition[]; | |||
| constructor( | |||
| @@ -35,10 +37,27 @@ export class VesselListComponent { | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'creationDate', | |||
| text: 'common.creation_date', | |||
| name: 'code', | |||
| text: 'common.code', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| field: 'code', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'shippingCompanyName', | |||
| text: 'model.shipping_company', | |||
| type: ListComponent.COLUMN_TYPE_TEXT, | |||
| subResource: 'company', | |||
| field: 'name', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_TEXT, | |||
| } as ListColDefinition, | |||
| { | |||
| name: 'createdAt', | |||
| text: 'common.created_at', | |||
| type: ListComponent.COLUMN_TYPE_DATE, | |||
| field: 'creationDate', | |||
| field: 'createdAt', | |||
| sortable: true, | |||
| filterType: FilterBarComponent.FILTER_TYPE_DATE, | |||
| } as ListColDefinition, | |||
| @@ -0,0 +1,25 @@ | |||
| <h2>{{ 'basic.new' | translate }} {{ 'model.vessel' | translate }}</h2> | |||
| <div class="spt-form"> | |||
| <form [formGroup]="form" (ngSubmit)="onSubmit()"> | |||
| <div class="mb-3"> | |||
| <label for="name" class="form-label">{{ 'common.name' | translate }}*:</label> | |||
| <input type="text" class="form-control" id="name" formControlName="name" required/> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label for="zone" class="form-label">{{ 'model.shipping_company' | translate }}:</label> | |||
| <app-search-select #shippingCompanySearchSelect | |||
| [formId]="'company'" | |||
| [formLabelLangKey]="'model.shipping_company'" | |||
| [documentForm]="form" | |||
| [getDataFunction]="getShippingCompanies" | |||
| [displayedDataField]="'name'" | |||
| [listColDefinitions]="shippingCompanyColDefinitions" | |||
| > | |||
| </app-search-select> | |||
| <input id="company" type="hidden" formControlName="company"/> | |||
| </div> | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid"> | |||
| {{ 'basic.send' | translate }} | |||
| </button> | |||
| </form> | |||
| </div> | |||
| @@ -0,0 +1,23 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { VesselNewComponent } from './vessel-new.component'; | |||
| describe('VesselNewComponent', () => { | |||
| let component: VesselNewComponent; | |||
| let fixture: ComponentFixture<VesselNewComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [VesselNewComponent] | |||
| }) | |||
| .compileComponents(); | |||
| fixture = TestBed.createComponent(VesselNewComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,66 @@ | |||
| import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | |||
| import {AbstractCreateDataComponent} from "@app/_interfaces/AbstractCreateDataComponent"; | |||
| import { | |||
| ShippingCompanyService, | |||
| VesselJsonld, | |||
| VesselService, | |||
| } from "@app/core/api/v1"; | |||
| import {ModalStatus} from "@app/_helpers/modal.states"; | |||
| import {FormGroup} from "@angular/forms"; | |||
| import {vesselForm} from "@app/_forms/apiForms"; | |||
| import {ListColDefinition} from "@app/_components/list/list-col-definition"; | |||
| import {SearchSelectComponent} from "@app/_components/search-select/search-select.component"; | |||
| import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type"; | |||
| @Component({ | |||
| selector: 'app-vessel-new', | |||
| templateUrl: './vessel-new.component.html', | |||
| styleUrl: './vessel-new.component.scss' | |||
| }) | |||
| export class VesselNewComponent extends AbstractCreateDataComponent<VesselJsonld> implements OnInit { | |||
| @Input() public override data!: VesselJsonld; | |||
| @Output() public override submit: EventEmitter<ModalStatus> = new EventEmitter<ModalStatus>(); | |||
| protected readonly SearchSelectComponent = SearchSelectComponent; | |||
| override form: FormGroup = vesselForm; | |||
| protected shippingCompanyColDefinitions: ListColDefinition[]; | |||
| constructor( | |||
| private vesselService: VesselService, | |||
| private shippingCompanyService: ShippingCompanyService, | |||
| ) { | |||
| super(); | |||
| this.shippingCompanyColDefinitions = SearchSelectComponent.getDefaultColDefShippingCompanies(); | |||
| } | |||
| override ngOnInit() { | |||
| if (this.data) { | |||
| this.form.patchValue(this.data); | |||
| } | |||
| } | |||
| getInitialData(): VesselJsonld { | |||
| return {} as VesselJsonld; | |||
| } | |||
| getShippingCompanies: ListGetDataFunctionType = (index: number, pageSize: number, term?: string) => { | |||
| return this.shippingCompanyService.shippingCompaniesGetCollection( | |||
| index, | |||
| pageSize, | |||
| term | |||
| ); | |||
| } | |||
| onSubmit() { | |||
| if (this.form.valid) { | |||
| this.vesselService.vesselsPost( | |||
| this.form.value as VesselJsonld | |||
| ).subscribe( | |||
| data => { | |||
| this.form.reset(); | |||
| this.submit.emit(ModalStatus.Submitted); | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| import { Component } from '@angular/core'; | |||
| import {Component} from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-vessel', | |||
| @@ -19,6 +19,7 @@ import {SearchSelectComponent} from "@app/_components/search-select/search-selec | |||
| export class ZoneListComponent { | |||
| @ViewChild("listComponent", {static: false}) listComponent!: ListComponent; | |||
| protected readonly ZoneNewComponent = ZoneNewComponent; | |||
| protected listColDefinitions!: ListColDefinition[]; | |||
| constructor( | |||
| @@ -58,5 +59,5 @@ export class ZoneListComponent { | |||
| const zone: ZoneJsonld = element as ZoneJsonld; | |||
| this.router.navigate(['/' + ROUTE_ZONES, this.appHelperService.extractId(zone.id)]); | |||
| } | |||
| protected readonly ZoneNewComponent = ZoneNewComponent; | |||
| } | |||
| @@ -55,6 +55,8 @@ import { VesselListComponent } from './_views/vessel/vessel-list/vessel-list.com | |||
| import { ShippingCompanyListComponent } from './_views/shipping-company/shipping-company-list/shipping-company-list.component'; | |||
| import { ZoneNewComponent } from './_views/zone/zone-new/zone-new.component'; | |||
| import { LocationNewComponent } from './_views/location/location-new/location-new.component'; | |||
| import { ShippingCompanyNewComponent } from './_views/shipping-company/shipping-company-new/shipping-company-new.component'; | |||
| import { VesselNewComponent } from './_views/vessel/vessel-new/vessel-new.component'; | |||
| registerLocaleData(localeDe, 'de-DE'); | |||
| @@ -132,6 +134,8 @@ export function HttpLoaderFactory(http: HttpClient) { | |||
| ShippingCompanyListComponent, | |||
| ZoneNewComponent, | |||
| LocationNewComponent, | |||
| ShippingCompanyNewComponent, | |||
| VesselNewComponent, | |||
| ], | |||
| providers: [ | |||
| {provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, | |||
| @@ -1,5 +1,4 @@ | |||
| .gitignore | |||
| .openapi-generator-ignore | |||
| README.md | |||
| api.module.ts | |||
| api/api.ts | |||
| @@ -9,15 +9,16 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { Zone } from './zone'; | |||
| /** | |||
| * | |||
| */ | |||
| export interface Location { | |||
| readonly zone?: string; | |||
| zone?: Zone; | |||
| name: string; | |||
| readonly zoneName?: string; | |||
| code: string; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -20,9 +20,9 @@ export interface LocationJsonld { | |||
| context?: LocationJsonldContext; | |||
| readonly id?: string; | |||
| readonly type?: string; | |||
| readonly zone?: ZoneJsonld; | |||
| zone?: ZoneJsonld; | |||
| name: string; | |||
| readonly zoneName?: string; | |||
| code: string; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -16,6 +16,7 @@ | |||
| */ | |||
| export interface ShippingCompany { | |||
| name: string; | |||
| code: string; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -20,6 +20,7 @@ export interface ShippingCompanyJsonld { | |||
| readonly id?: string; | |||
| readonly type?: string; | |||
| name: string; | |||
| code: string; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -9,6 +9,7 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { ShippingCompany } from './shippingCompany'; | |||
| /** | |||
| @@ -16,7 +17,8 @@ | |||
| */ | |||
| export interface Vessel { | |||
| name: string; | |||
| readonly company?: string; | |||
| code: string; | |||
| company?: ShippingCompany; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -21,7 +21,8 @@ export interface VesselJsonld { | |||
| readonly id?: string; | |||
| readonly type?: string; | |||
| name: string; | |||
| readonly company?: ShippingCompanyJsonld; | |||
| code: string; | |||
| company?: ShippingCompanyJsonld; | |||
| readonly createdAt?: string | null; | |||
| } | |||
| @@ -12,7 +12,8 @@ | |||
| "common": | |||
| { | |||
| "name": "Name", | |||
| "created_at": "Creation date" | |||
| "code": "Code", | |||
| "created_at": "Created at" | |||
| }, | |||
| "base_data": | |||
| { | |||
| @@ -24,7 +25,9 @@ | |||
| }, | |||
| "model": { | |||
| "location": "Location", | |||
| "zone": "Zone" | |||
| "zone": "Zone", | |||
| "vessel": "Vessel", | |||
| "shipping_company": "Shipping Company" | |||
| }, | |||
| "location": | |||
| @@ -1,7 +1,7 @@ | |||
| name: imaq | |||
| type: php | |||
| docroot: public | |||
| php_version: "8.2" | |||
| php_version: "8.3" | |||
| webserver_type: nginx-fpm | |||
| xdebug_enabled: false | |||
| additional_hostnames: [] | |||
| @@ -0,0 +1,31 @@ | |||
| <?php | |||
| declare(strict_types=1); | |||
| namespace DoctrineMigrations; | |||
| use Doctrine\DBAL\Schema\Schema; | |||
| use Doctrine\Migrations\AbstractMigration; | |||
| /** | |||
| * Auto-generated Migration: Please modify to your needs! | |||
| */ | |||
| final class Version20241206100317 extends AbstractMigration | |||
| { | |||
| public function getDescription(): string | |||
| { | |||
| return ''; | |||
| } | |||
| public function up(Schema $schema): void | |||
| { | |||
| // this up() migration is auto-generated, please modify it to your needs | |||
| $this->addSql('ALTER TABLE location ADD code VARCHAR(10) NOT NULL'); | |||
| } | |||
| public function down(Schema $schema): void | |||
| { | |||
| // this down() migration is auto-generated, please modify it to your needs | |||
| $this->addSql('ALTER TABLE location DROP code'); | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| <?php | |||
| declare(strict_types=1); | |||
| namespace DoctrineMigrations; | |||
| use Doctrine\DBAL\Schema\Schema; | |||
| use Doctrine\Migrations\AbstractMigration; | |||
| /** | |||
| * Auto-generated Migration: Please modify to your needs! | |||
| */ | |||
| final class Version20241206103710 extends AbstractMigration | |||
| { | |||
| public function getDescription(): string | |||
| { | |||
| return ''; | |||
| } | |||
| public function up(Schema $schema): void | |||
| { | |||
| // this up() migration is auto-generated, please modify it to your needs | |||
| $this->addSql('ALTER TABLE shipping_company ADD code VARCHAR(20) NOT NULL'); | |||
| $this->addSql('CREATE UNIQUE INDEX UNIQ_A9F70F8B77153098 ON shipping_company (code)'); | |||
| $this->addSql('ALTER TABLE vessel ADD code VARCHAR(20) NOT NULL'); | |||
| $this->addSql('CREATE UNIQUE INDEX UNIQ_4ED8DCA877153098 ON vessel (code)'); | |||
| } | |||
| public function down(Schema $schema): void | |||
| { | |||
| // this down() migration is auto-generated, please modify it to your needs | |||
| $this->addSql('DROP INDEX UNIQ_4ED8DCA877153098 ON vessel'); | |||
| $this->addSql('ALTER TABLE vessel DROP code'); | |||
| $this->addSql('DROP INDEX UNIQ_A9F70F8B77153098 ON shipping_company'); | |||
| $this->addSql('ALTER TABLE shipping_company DROP code'); | |||
| } | |||
| } | |||
| @@ -54,9 +54,9 @@ class LocationApi | |||
| * @var ZoneApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: false, | |||
| writable: true, | |||
| readableLink: true, | |||
| writableLink: false, | |||
| writableLink: true, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| @@ -69,8 +69,8 @@ class LocationApi | |||
| #[Assert\NotBlank] | |||
| public string $name; | |||
| #[ApiProperty(writable: false)] | |||
| public string $zoneName; | |||
| #[Assert\NotBlank] | |||
| public string $code; | |||
| #[ApiProperty(writable: false)] | |||
| public ?\DateTimeImmutable $createdAt = null; | |||
| @@ -52,6 +52,9 @@ class ShippingCompanyApi | |||
| #[Assert\NotBlank] | |||
| public string $name; | |||
| #[Assert\NotBlank] | |||
| public string $code; | |||
| #[ApiProperty(writable: false)] | |||
| public ?\DateTimeImmutable $createdAt = null; | |||
| } | |||
| @@ -53,13 +53,16 @@ class VesselApi | |||
| #[Assert\NotBlank] | |||
| public string $name; | |||
| #[Assert\NotBlank] | |||
| public string $code; | |||
| /** | |||
| * @var ShippingCompanyApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: false, | |||
| writable: true, | |||
| readableLink: true, | |||
| writableLink: false, | |||
| writableLink: true, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| @@ -0,0 +1,111 @@ | |||
| <?php | |||
| declare(strict_types=1); | |||
| namespace App\Command\Import; | |||
| use App\Entity\ShippingCompany; | |||
| use App\Entity\Vessel; | |||
| use Doctrine\ORM\EntityManagerInterface; | |||
| use Symfony\Component\Console\Attribute\AsCommand; | |||
| use Symfony\Component\Console\Command\Command; | |||
| use Symfony\Component\Console\Input\InputInterface; | |||
| use Symfony\Component\Console\Output\OutputInterface; | |||
| use Symfony\Component\Console\Style\SymfonyStyle; | |||
| #[AsCommand( | |||
| name: 'app:create-shipping-test-data', | |||
| description: 'Creates test data for shipping companies and vessels with unique codes' | |||
| )] | |||
| class CreateShippingTestDataCommand extends Command | |||
| { | |||
| private array $companyData = [ | |||
| ['name' => 'Arctic Shipping Lines', 'code' => 'ARCTIC-SL'], | |||
| ['name' => 'Greenland Marine Transport', 'code' => 'GRE-MAR-TRANS'], | |||
| ['name' => 'Nordic Sea Carriers', 'code' => 'NORDIC-SEA'], | |||
| ['name' => 'Polar Route Navigation', 'code' => 'POLAR-ROUTE'], | |||
| ['name' => 'Royal Arctic Line', 'code' => 'RAL'], | |||
| ['name' => 'North Atlantic Shipping', 'code' => 'NORTH-ATL'], | |||
| ['name' => 'Viking Ocean Transport', 'code' => 'VIKING-OT'], | |||
| ['name' => 'Ice Route Maritime', 'code' => 'ICE-ROUTE'], | |||
| ['name' => 'Aurora Vessel Operations', 'code' => 'AURORA-VO'], | |||
| ['name' => 'Baltic Sea Logistics', 'code' => 'BALTIC-LOG'] | |||
| ]; | |||
| private array $vesselNames = [ | |||
| 'Nordic Explorer', | |||
| 'Arctic Princess', | |||
| 'Polar Star', | |||
| 'Northern Light', | |||
| 'Ice Breaker', | |||
| 'Aurora', | |||
| 'Viking Spirit', | |||
| 'Ocean Pioneer', | |||
| 'Greenland Express', | |||
| 'Baltic Voyager' | |||
| ]; | |||
| public function __construct( | |||
| private readonly EntityManagerInterface $entityManager | |||
| ) { | |||
| parent::__construct(); | |||
| } | |||
| protected function execute(InputInterface $input, OutputInterface $output): int | |||
| { | |||
| $io = new SymfonyStyle($input, $output); | |||
| try { | |||
| // Shuffle company data to randomize selection | |||
| shuffle($this->companyData); | |||
| // Select 7-10 companies randomly | |||
| $numberOfCompanies = random_int(7, 10); | |||
| $selectedCompanies = array_slice($this->companyData, 0, $numberOfCompanies); | |||
| foreach ($selectedCompanies as $companyInfo) { | |||
| $company = new ShippingCompany($companyInfo['name'], $companyInfo['code']); | |||
| $this->entityManager->persist($company); | |||
| // Create 1-3 vessels for each company | |||
| $numberOfVessels = random_int(1, 3); | |||
| // Generate unique vessel names and codes | |||
| for ($i = 0; $i < $numberOfVessels; $i++) { | |||
| $vesselName = $this->vesselNames[array_rand($this->vesselNames)]; | |||
| // Create unique vessel code using company code and counter | |||
| $vesselCode = sprintf( | |||
| '%s-V%03d', | |||
| $companyInfo['code'], | |||
| random_int(1, 999) | |||
| ); | |||
| $vessel = new Vessel($company, $vesselName, $vesselCode); | |||
| $this->entityManager->persist($vessel); | |||
| $io->writeln(sprintf( | |||
| 'Created vessel "%s" (%s) for company "%s" (%s)', | |||
| $vesselName, | |||
| $vesselCode, | |||
| $companyInfo['name'], | |||
| $companyInfo['code'] | |||
| )); | |||
| } | |||
| $io->writeln(sprintf( | |||
| 'Created company "%s" (%s) with %d vessels', | |||
| $companyInfo['name'], | |||
| $companyInfo['code'], | |||
| $numberOfVessels | |||
| )); | |||
| } | |||
| $this->entityManager->flush(); | |||
| $io->success(sprintf('Created %d companies with vessels', $numberOfCompanies)); | |||
| return Command::SUCCESS; | |||
| } catch (\Exception $e) { | |||
| $io->error('Error creating test data: ' . $e->getMessage()); | |||
| return Command::FAILURE; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,117 @@ | |||
| <?php | |||
| declare(strict_types=1); | |||
| namespace App\Command\Import; | |||
| use App\Entity\Zone; | |||
| use App\Entity\Location; | |||
| use Doctrine\ORM\EntityManagerInterface; | |||
| use Symfony\Component\Console\Attribute\AsCommand; | |||
| use Symfony\Component\Console\Command\Command; | |||
| use Symfony\Component\Console\Input\InputInterface; | |||
| use Symfony\Component\Console\Output\OutputInterface; | |||
| use Symfony\Component\Console\Style\SymfonyStyle; | |||
| #[AsCommand( | |||
| name: 'app:import-zones-locations', | |||
| description: 'Import zones and locations from matrix' | |||
| )] | |||
| class ImportZonesLocationsCommand extends Command | |||
| { | |||
| public function __construct( | |||
| private readonly EntityManagerInterface $entityManager | |||
| ) { | |||
| parent::__construct(); | |||
| } | |||
| protected function execute(InputInterface $input, OutputInterface $output): int | |||
| { | |||
| $io = new SymfonyStyle($input, $output); | |||
| // Zone data | |||
| $zoneData = [ | |||
| 4 => 'Area 4', | |||
| 5 => 'Area 5', | |||
| 6 => 'Area 6', | |||
| 7 => 'Area 7', | |||
| ]; | |||
| // Location data | |||
| $locationData = [ | |||
| 4 => [ | |||
| ['code' => 'TAS', 'name' => 'Tasiilaq'], | |||
| ['code' => 'UMI', 'name' => 'Umivik'], | |||
| ['code' => 'SKJ', 'name' => 'Skjoldungen'], | |||
| ], | |||
| 5 => [ | |||
| ['code' => 'PCS', 'name' => 'Prins Chr. Sund'], | |||
| ['code' => 'NAN', 'name' => 'Nanortalik / Tasermiut fjorden'], | |||
| ['code' => 'QAQ', 'name' => 'Qaqortoq / Igaliku fjorden'], | |||
| ['code' => 'NRQ', 'name' => 'Narsaq/Skovfjord/Bredefjord'], | |||
| ['code' => 'NRQ', 'name' => 'Narsaq - Havnelodsning'], | |||
| ['code' => 'NSSQ', 'name' => 'Narsarssuaq/Skovfjord/Bredefjord'], | |||
| ['code' => 'IVI', 'name' => 'Arsuk/Ivigtut/Grønnedal'], | |||
| ['code' => 'PAA', 'name' => 'Paamiut/Kvanefjord'], | |||
| ['code' => 'NUU', 'name' => 'Nuuk/Nuuk Fjorden'], | |||
| ['code' => 'NUU', 'name' => 'Nuuk - Havnelodsning'], | |||
| ], | |||
| 6 => [ | |||
| ['code' => 'MAN', 'name' => 'Maniitsoq/Hamborgsund'], | |||
| ['code' => 'EVI', 'name' => 'Evighedsfjorden'], | |||
| ['code' => 'SFJ', 'name' => 'Kangerlussuaq'], | |||
| ['code' => 'SIS', 'name' => 'Sisimiut'], | |||
| ['code' => 'SIS', 'name' => 'Sisimiut - Havnelodsning'], | |||
| ], | |||
| 7 => [ | |||
| ['code' => 'AAS', 'name' => 'Aasiaat'], | |||
| ['code' => 'QEQ', 'name' => 'Qeqertarsuaq'], | |||
| ['code' => 'QAS', 'name' => 'Qasigiannguit'], | |||
| ['code' => 'ILU', 'name' => 'Ilulissat/Ilimanaq'], | |||
| ['code' => 'QER', 'name' => 'Qeqertaq'], | |||
| ['code' => 'SQQ', 'name' => 'Sarqaq'], | |||
| ['code' => 'VAI', 'name' => 'Vaigat'], | |||
| ['code' => 'UUM', 'name' => 'Uummannaq'], | |||
| ], | |||
| ]; | |||
| try { | |||
| // Import zones | |||
| $zones = []; | |||
| foreach ($zoneData as $zoneId => $zoneName) { | |||
| $zone = new Zone($zoneName); | |||
| $this->entityManager->persist($zone); | |||
| $zones[$zoneId] = $zone; | |||
| $io->writeln(sprintf('Created zone "%s"', $zoneName)); | |||
| } | |||
| // Import locations | |||
| foreach ($locationData as $zoneId => $locations) { | |||
| $zone = $zones[$zoneId]; | |||
| foreach ($locations as $locationInfo) { | |||
| $location = new Location( | |||
| $zone, | |||
| $locationInfo['name'], | |||
| $locationInfo['code'] | |||
| ); | |||
| $this->entityManager->persist($location); | |||
| $io->writeln(sprintf( | |||
| 'Created location "%s" (%s) in zone "%s"', | |||
| $locationInfo['name'], | |||
| $locationInfo['code'], | |||
| $zone->getName() | |||
| )); | |||
| } | |||
| } | |||
| $this->entityManager->flush(); | |||
| $io->success('Import completed successfully'); | |||
| return Command::SUCCESS; | |||
| } catch (\Exception $e) { | |||
| $io->error('Import error: ' . $e->getMessage()); | |||
| return Command::FAILURE; | |||
| } | |||
| } | |||
| } | |||
| @@ -22,6 +22,9 @@ class Location | |||
| #[ORM\JoinColumn(nullable: false)] | |||
| private Zone $zone; | |||
| #[ORM\Column(length: 10)] | |||
| private string $code; | |||
| #[ORM\Column(length: 255)] | |||
| private string $name; | |||
| @@ -40,10 +43,11 @@ class Location | |||
| #[ORM\OneToMany(targetEntity: UserTripWorkLog::class, mappedBy: 'endLocation')] | |||
| private Collection $endWorkLogs; | |||
| public function __construct(Zone $zone, string $name) | |||
| public function __construct(Zone $zone, string $name, string $code) | |||
| { | |||
| $this->zone = $zone; | |||
| $this->name = $name; | |||
| $this->code = $code; | |||
| $this->createdAt = new DateTimeImmutable(); | |||
| $this->tripLocations = new ArrayCollection(); | |||
| $this->userTripLocations = new ArrayCollection(); | |||
| @@ -78,6 +82,16 @@ class Location | |||
| return $this; | |||
| } | |||
| public function getCode(): string | |||
| { | |||
| return $this->code; | |||
| } | |||
| public function setCode(string $code): void | |||
| { | |||
| $this->code = $code; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -21,15 +21,19 @@ class ShippingCompany | |||
| #[ORM\Column(length: 255)] | |||
| private string $name; | |||
| #[ORM\Column(length: 20, unique: true)] | |||
| private string $code; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $createdAt; | |||
| #[ORM\OneToMany(targetEntity: Vessel::class, mappedBy: 'company')] | |||
| private Collection $vessels; | |||
| public function __construct(string $name) | |||
| public function __construct(string $name, string $code) | |||
| { | |||
| $this->name = $name; | |||
| $this->code = $code; | |||
| $this->createdAt = new DateTimeImmutable(); | |||
| $this->vessels = new ArrayCollection(); | |||
| } | |||
| @@ -50,6 +54,16 @@ class ShippingCompany | |||
| return $this; | |||
| } | |||
| public function getCode(): string | |||
| { | |||
| return $this->code; | |||
| } | |||
| public function setCode(string $code): void | |||
| { | |||
| $this->code = $code; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -25,16 +25,20 @@ class Vessel | |||
| #[ORM\Column(length: 255)] | |||
| private string $name; | |||
| #[ORM\Column(length: 20, unique: true)] | |||
| private string $code; | |||
| #[ORM\Column] | |||
| private DateTimeImmutable $createdAt; | |||
| #[ORM\OneToMany(targetEntity: Trip::class, mappedBy: 'vessel')] | |||
| private Collection $trips; | |||
| public function __construct(ShippingCompany $company, string $name) | |||
| public function __construct(ShippingCompany $company, string $name, string $code) | |||
| { | |||
| $this->company = $company; | |||
| $this->name = $name; | |||
| $this->code = $code; | |||
| $this->createdAt = new DateTimeImmutable(); | |||
| $this->trips = new ArrayCollection(); | |||
| } | |||
| @@ -66,6 +70,16 @@ class Vessel | |||
| return $this; | |||
| } | |||
| public function getCode(): string | |||
| { | |||
| return $this->code; | |||
| } | |||
| public function setCode(string $code): void | |||
| { | |||
| $this->code = $code; | |||
| } | |||
| public function getCreatedAt(): DateTimeImmutable | |||
| { | |||
| return $this->createdAt; | |||
| @@ -33,7 +33,7 @@ class LocationApiToEntityMapper implements MapperInterface | |||
| } | |||
| // For new locations, we need the zone | |||
| if (!$dto->zone?->id) { | |||
| if (!$dto->zone) { | |||
| throw new \Exception('Zone is required for new locations'); | |||
| } | |||
| @@ -42,7 +42,7 @@ class LocationApiToEntityMapper implements MapperInterface | |||
| throw new \Exception('Zone not found'); | |||
| } | |||
| return new Location($zone, $dto->name); | |||
| return new Location($zone, $dto->name, $dto->code); | |||
| } | |||
| public function populate(object $from, object $to, array $context): object | |||
| @@ -53,6 +53,15 @@ class LocationApiToEntityMapper implements MapperInterface | |||
| assert($entity instanceof Location); | |||
| $entity->setName($dto->name); | |||
| $entity->setCode($dto->code); | |||
| if ($dto->zone) { | |||
| $zone = $this->zoneRepository->find($dto->zone->id); | |||
| if (!$zone) { | |||
| throw new \Exception('Zone not found'); | |||
| } | |||
| $entity->setZone($zone); | |||
| } | |||
| return $entity; | |||
| } | |||
| @@ -36,14 +36,13 @@ class LocationEntityToApiMapper implements MapperInterface | |||
| assert($dto instanceof LocationApi); | |||
| $dto->name = $entity->getName(); | |||
| $dto->code = $entity->getCode(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| $dto->zone = $this->microMapper->map($entity->getZone(), ZoneApi::class, [ | |||
| MicroMapperInterface::MAX_DEPTH => 1, | |||
| ]); | |||
| $dto->zoneName = $dto->zone->name; | |||
| return $dto; | |||
| } | |||
| } | |||
| @@ -37,6 +37,7 @@ class ShippingCompanyApiToEntityMapper implements MapperInterface | |||
| assert($entity instanceof ShippingCompany); | |||
| $entity->setName($dto->name); | |||
| $entity->setCode($dto->code); | |||
| return $entity; | |||
| } | |||
| @@ -35,6 +35,7 @@ class ShippingCompanyEntityToApiMapper implements MapperInterface | |||
| assert($dto instanceof ShippingCompanyApi); | |||
| $dto->name = $entity->getName(); | |||
| $dto->code = $entity->getCode(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| return $dto; | |||
| @@ -42,7 +42,7 @@ class VesselApiToEntityMapper implements MapperInterface | |||
| throw new \Exception('ShippingCompany not found'); | |||
| } | |||
| return new Vessel($company, $dto->name); | |||
| return new Vessel($company, $dto->name, $dto->code); | |||
| } | |||
| public function populate(object $from, object $to, array $context): object | |||
| @@ -53,6 +53,8 @@ class VesselApiToEntityMapper implements MapperInterface | |||
| assert($entity instanceof Vessel); | |||
| $entity->setName($dto->name); | |||
| $entity->setCode($dto->code); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| return $entity; | |||
| } | |||
| @@ -36,6 +36,7 @@ class VesselEntityToApiMapper implements MapperInterface | |||
| assert($dto instanceof VesselApi); | |||
| $dto->name = $entity->getName(); | |||
| $dto->code = $entity->getCode(); | |||
| $dto->createdAt = $entity->getCreatedAt(); | |||
| $dto->company = $this->microMapper->map($entity->getCompany(), ShippingCompanyApi::class, [ | |||