diff --git a/matsen-tool/src/app/app.module.ts b/matsen-tool/src/app/app.module.ts index 998d79c..621d1e6 100644 --- a/matsen-tool/src/app/app.module.ts +++ b/matsen-tool/src/app/app.module.ts @@ -45,6 +45,7 @@ import { NewTaskNoteComponent } from './tasks/new-task-note/new-task-note.compon import { DocumentsDetailComponent } from './documents/documents-detail/documents-detail.component'; import { SalesComponent } from './sales/sales.component'; import { SalesDetailComponent } from './sales/sales-detail/sales-detail.component'; +import { NewSaleComponent } from './sales/new-sale/new-sale.component'; export function apiConfigFactory(): Configuration { const params: ConfigurationParameters = { @@ -110,7 +111,8 @@ export function HttpLoaderFactory(http: HttpClient) { NewTaskNoteComponent, DocumentsDetailComponent, SalesComponent, - SalesDetailComponent + SalesDetailComponent, + NewSaleComponent ], providers: [ {provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, diff --git a/matsen-tool/src/app/documents/new-document/new-document.component.html b/matsen-tool/src/app/documents/new-document/new-document.component.html index b3aac2c..8673075 100644 --- a/matsen-tool/src/app/documents/new-document/new-document.component.html +++ b/matsen-tool/src/app/documents/new-document/new-document.component.html @@ -16,7 +16,7 @@ + [resultFormatter]="formatter" [editable]="false" (selectItem)="onPartnerSelect($event)"/> @@ -24,7 +24,7 @@ + [resultFormatter]="formatter" [editable]="false" (selectItem)="onProductSelect($event)"/> diff --git a/matsen-tool/src/app/documents/new-document/new-document.component.ts b/matsen-tool/src/app/documents/new-document/new-document.component.ts index 430f809..69bffba 100644 --- a/matsen-tool/src/app/documents/new-document/new-document.component.ts +++ b/matsen-tool/src/app/documents/new-document/new-document.component.ts @@ -82,11 +82,11 @@ export class NewDocumentComponent implements OnInit { ); } - protected onAssignedToSelectPartner(selectedItem: any): void { + protected onPartnerSelect(selectedItem: any): void { this.documentForm.get('partner')?.setValue(selectedItem.item.id); } - protected onAssignedToSelectProduct(selectedItem: any): void { + protected onProductSelect(selectedItem: any): void { this.documentForm.get('product')?.setValue(selectedItem.item.id); } diff --git a/matsen-tool/src/app/sales/new-sale/new-sale.component.html b/matsen-tool/src/app/sales/new-sale/new-sale.component.html new file mode 100644 index 0000000..0c3b316 --- /dev/null +++ b/matsen-tool/src/app/sales/new-sale/new-sale.component.html @@ -0,0 +1,80 @@ +

{{ 'basic.new-sale' | translate }}

+

{{ 'basic.edit-sale' | translate }}

+
+
+
+ + + +
+ +
+ + + +
+ +
+ + +
+ {{ 'form.turnover' | translate }} {{ 'form.mandatory' | translate }}. +
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ diff --git a/matsen-tool/src/app/sales/new-sale/new-sale.component.scss b/matsen-tool/src/app/sales/new-sale/new-sale.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/matsen-tool/src/app/sales/new-sale/new-sale.component.spec.ts b/matsen-tool/src/app/sales/new-sale/new-sale.component.spec.ts new file mode 100644 index 0000000..466a53b --- /dev/null +++ b/matsen-tool/src/app/sales/new-sale/new-sale.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NewSaleComponent } from './new-sale.component'; + +describe('NewSaleComponent', () => { + let component: NewSaleComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [NewSaleComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(NewSaleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/matsen-tool/src/app/sales/new-sale/new-sale.component.ts b/matsen-tool/src/app/sales/new-sale/new-sale.component.ts new file mode 100644 index 0000000..40965b6 --- /dev/null +++ b/matsen-tool/src/app/sales/new-sale/new-sale.component.ts @@ -0,0 +1,126 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import { + MediaObjectService, + PartnerJsonld, + PartnerService, + ProductService, + SaleJsonld, + SaleService +} from "@app/core/api/v1"; +import {ModalStatus} from "@app/_helpers/modal.states"; +import {FormGroup} from "@angular/forms"; +import {debounceTime, distinctUntilChanged, Observable, OperatorFunction, Subscription, switchMap} from "rxjs"; +import {TranslateService} from "@ngx-translate/core"; +import {FormGroupInitializer} from "@app/_helpers/formgroup.initializer"; +import {saleForm} from "@app/_forms/apiForms"; +import {ApiConverter} from "@app/_helpers/api.converter"; +import {filter, map} from "rxjs/operators"; + +@Component({ + selector: 'app-new-sale', + templateUrl: './new-sale.component.html', + styleUrl: './new-sale.component.scss' +}) +export class NewSaleComponent implements OnInit { + @Input() public sale!: SaleJsonld; + @Output() public submit: EventEmitter = new EventEmitter(); + + protected saleForm: FormGroup; + protected saleSub: Subscription; + + protected formatter = (apiData: any) => apiData.name; + + constructor( + private saleService: SaleService, + private partnerService: PartnerService, + private productService: ProductService, + private translateService: TranslateService + ) { + this.saleForm = saleForm; + + this.saleSub = new Subscription(); + } + + ngOnInit(): void { + this.saleForm = FormGroupInitializer.initFormGroup(this.saleForm, this.sale); + } + + protected searchPartners: OperatorFunction = (text$: Observable) => + text$.pipe( + debounceTime(200), + distinctUntilChanged(), + filter((term) => term.length >= 2), + switchMap((term) => this.fetchPartners(term)), + map((partners) => partners.slice(0, 10)), + ); + + protected searchProducts: OperatorFunction = (text$: Observable) => + text$.pipe( + debounceTime(200), + distinctUntilChanged(), + filter((term) => term.length >= 2), + switchMap((term) => this.fetchProducts(term)), + map((products) => products.slice(0, 10)), + ); + + protected fetchPartners(term: string): Observable<{ id: any; name: any }[]> { + return this.partnerService.partnersGetCollection(1, 50, undefined, undefined, term).pipe( + map((response) => response['hydra:member'].map(partner => ({id: partner.id, name: partner.name}))), + ); + } + + protected fetchProducts(term: string): Observable<{ id: any; name: any }[]> { + return this.productService.productsGetCollection(1, 50, term).pipe( + map((response) => response['hydra:member'].map(product => ({id: product.id, name: product.name}))), + ); + } + + protected onPartnerSelect(selectedItem: any): void { + this.saleForm.get('partner')?.setValue(selectedItem.item.id); + } + + protected onProductSelect(selectedItem: any): void { + this.saleForm.get('product')?.setValue(selectedItem.item.id); + } + + onSubmit() { + if (this.saleForm.valid) { + if (this.saleForm.get('profit')?.value > this.saleForm.get('turnover')?.value) { + let alertMessage = ""; + this.translateService.get('system.profit-larger-turnover').subscribe((translation: string) => { + alertMessage = translation; + }); + alert(alertMessage); + return; + } + if (this.sale.id === null || this.sale.id === undefined) { + // Create new sale + this.saleSub = this.saleService.salesPost( + this.saleForm.value as SaleJsonld + ).subscribe( + data => { + this.saleForm.reset(); + this.submit.emit(ModalStatus.Submitted); + } + ); + } else { + // Edit sale + this.saleSub = this.saleService.salesIdPatch( + ApiConverter.extractId(this.sale.id), + this.saleForm.value as SaleJsonld + ).subscribe( + data => { + this.saleForm.reset(); + this.submit.emit(ModalStatus.Submitted); + } + ); + } + } + } +} diff --git a/matsen-tool/src/app/sales/sales.component.ts b/matsen-tool/src/app/sales/sales.component.ts index 5f7bd45..c085eec 100644 --- a/matsen-tool/src/app/sales/sales.component.ts +++ b/matsen-tool/src/app/sales/sales.component.ts @@ -19,6 +19,7 @@ import {ApiConverter} from "@app/_helpers/api.converter"; import {Router} from "@angular/router"; import {registerLocaleData} from "@angular/common"; import localeDe from '@angular/common/locales/de'; +import {NewSaleComponent} from "@app/sales/new-sale/new-sale.component"; registerLocaleData(localeDe); @@ -163,13 +164,14 @@ export class SalesComponent implements OnInit { } openModalNewSale() { - const modalRefContact = this.modalService.open(NewPartnerComponent, this.modalOptions); + const modalRefSale = this.modalService.open(NewSaleComponent, this.modalOptions); let sale: SaleJsonld = {} as SaleJsonld; - modalRefContact.componentInstance.partner = sale; - modalRefContact.componentInstance.submit.subscribe((modalStatus: ModalStatus) => { + modalRefSale.componentInstance.sale = sale; + modalRefSale.componentInstance.submit.subscribe((modalStatus: ModalStatus) => { if (modalStatus === ModalStatus.Submitted) { - modalRefContact.dismiss(); + modalRefSale.dismiss(); this.getSalesData(); + this.getSalesSummaryData(); } }); } diff --git a/matsen-tool/src/assets/i18n/de.json b/matsen-tool/src/assets/i18n/de.json index be2d8cf..31aba50 100644 --- a/matsen-tool/src/assets/i18n/de.json +++ b/matsen-tool/src/assets/i18n/de.json @@ -4,7 +4,8 @@ "delete-image": "Bild löschen", "confirm-delete-image": "Möchten Sie das Bild wirklich löschen?", "delete-file": "Datei löschen", - "confirm-delete-file": "Möchten Sie die Datei wirklich löschen?" + "confirm-delete-file": "Möchten Sie die Datei wirklich löschen?", + "profit-larger-turnover": "Der Gewinn ist größer als der Umsatz!" }, "basic": { @@ -41,6 +42,7 @@ "edit-post": "Notiz bearbeiten", "edit-comment": "Kommentar bearbeiten", "edit-task-note": "Anmerkung bearbeiten", + "edit-sale": "Verkauf bearbeiten", "details": "Details", "comment-it": "Kommentieren", "show-comments": "Kommentare anzeigen", @@ -107,6 +109,8 @@ "prio-high": "hoch", "partner": "Partner", "product": "Produkt", + "turnover": "Umsatz", + "profit": "Gewinn", "send": "Abschicken" }, "sales":