Florian Eisenmenger před 1 rokem
rodič
revize
4862288bed
9 změnil soubory, kde provedl 247 přidání a 10 odebrání
  1. +3
    -1
      matsen-tool/src/app/app.module.ts
  2. +2
    -2
      matsen-tool/src/app/documents/new-document/new-document.component.html
  3. +2
    -2
      matsen-tool/src/app/documents/new-document/new-document.component.ts
  4. +80
    -0
      matsen-tool/src/app/sales/new-sale/new-sale.component.html
  5. +0
    -0
      matsen-tool/src/app/sales/new-sale/new-sale.component.scss
  6. +23
    -0
      matsen-tool/src/app/sales/new-sale/new-sale.component.spec.ts
  7. +126
    -0
      matsen-tool/src/app/sales/new-sale/new-sale.component.ts
  8. +6
    -4
      matsen-tool/src/app/sales/sales.component.ts
  9. +5
    -1
      matsen-tool/src/assets/i18n/de.json

+ 3
- 1
matsen-tool/src/app/app.module.ts Zobrazit soubor

@@ -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},


+ 2
- 2
matsen-tool/src/app/documents/new-document/new-document.component.html Zobrazit soubor

@@ -16,7 +16,7 @@
<label for="partner" class="form-label">{{ 'form.partner' | translate }}:</label>
<input type="text" class="form-control" id="partner" [ngbTypeahead]="searchPartners"
[inputFormatter]="formatter" [value]="documentForm.get('partnerName')?.value"
[resultFormatter]="formatter" [editable]="false" (selectItem)="onAssignedToSelectPartner($event)"/>
[resultFormatter]="formatter" [editable]="false" (selectItem)="onPartnerSelect($event)"/>
<input type="hidden" formControlName="partner"/>
</div>

@@ -24,7 +24,7 @@
<label for="product" class="form-label">{{ 'form.product' | translate }}:</label>
<input type="text" class="form-control" id="product" [ngbTypeahead]="searchProducts"
[inputFormatter]="formatter" [value]="documentForm.get('productName')?.value"
[resultFormatter]="formatter" [editable]="false" (selectItem)="onAssignedToSelectProduct($event)"/>
[resultFormatter]="formatter" [editable]="false" (selectItem)="onProductSelect($event)"/>
<input type="hidden" formControlName="product"/>
</div>



+ 2
- 2
matsen-tool/src/app/documents/new-document/new-document.component.ts Zobrazit soubor

@@ -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);
}



+ 80
- 0
matsen-tool/src/app/sales/new-sale/new-sale.component.html Zobrazit soubor

@@ -0,0 +1,80 @@
<h2 *ngIf="!sale.id">{{ 'basic.new-sale' | translate }}</h2>
<h2 *ngIf="sale.id">{{ 'basic.edit-sale' | translate }}</h2>
<div class="spt-form">
<form [formGroup]="saleForm" (ngSubmit)="onSubmit()">
<div class="mb-3">
<label for="partner" class="form-label">{{ 'form.partner' | translate }}:</label>
<input type="text" class="form-control" id="partner" [ngbTypeahead]="searchPartners"
[inputFormatter]="formatter" [value]="saleForm.get('partnerName')?.value"
[resultFormatter]="formatter" [editable]="false" (selectItem)="onPartnerSelect($event)"/>
<input type="hidden" formControlName="partner"/>
</div>

<div class="mb-3">
<label for="product" class="form-label">{{ 'form.product' | translate }}:</label>
<input type="text" class="form-control" id="product" [ngbTypeahead]="searchProducts"
[inputFormatter]="formatter" [value]="saleForm.get('productName')?.value"
[resultFormatter]="formatter" [editable]="false" (selectItem)="onProductSelect($event)"/>
<input type="hidden" formControlName="product"/>
</div>

<div class="mb-3">
<label for="turnover" class="form-label">{{ 'form.turnover' | translate }}:</label>
<input type="number" class="form-control" id="turnover" formControlName="turnover" min="0" step="1" />
<div class="form-text" *ngIf="saleForm.get('turnover')?.invalid && saleForm.get('turnover')?.touched">
{{ 'form.turnover' | translate }} {{ 'form.mandatory' | translate }}.
</div>
</div>

<div class="mb-3">
<label for="profit" class="form-label">{{ 'form.profit' | translate }}:</label>
<input type="number" class="form-control" id="profit" formControlName="profit" min="0" step="1" />
</div>

<!-- <div class="mb-3">-->
<!-- <label for="street" class="form-label">{{ 'form.street' | translate }}:</label>-->
<!-- <input type="text" class="form-control" id="street" formControlName="street"/>-->
<!-- </div>-->

<!-- <div class="mb-3">-->
<!-- <label for="streetNo" class="form-label">{{ 'form.street-no' | translate }}:</label>-->
<!-- <input type="text" class="form-control" id="streetNo" formControlName="streetNo"/>-->
<!-- </div>-->

<!-- <div class="mb-3">-->
<!-- <label for="zip" class="form-label">{{ 'form.zip' | translate }}:</label>-->
<!-- <input type="text" class="form-control" id="zip" formControlName="zip"/>-->
<!-- </div>-->

<!-- <div class="mb-3">-->
<!-- <label for="city" class="form-label">{{ 'form.city' | translate }}:</label>-->
<!-- <input type="text" class="form-control" id="city" formControlName="city"/>-->
<!-- </div>-->

<!-- <div class="mb-3">-->
<!-- <label for="country" class="form-label">{{ 'form.country' | translate }}:</label>-->
<!-- <input type="text" class="form-control" id="country" formControlName="country"/>-->
<!-- </div>-->

<!-- <div class="mb-3">-->
<!-- <label for="website" class="form-label">{{ 'form.website' | translate }}:</label>-->
<!-- <input type="text" class="form-control" id="website" formControlName="website"/>-->
<!-- </div>-->

<!-- <div class="mb-3" *ngIf="partnerForm.get('logoUrl')?.value === null">-->
<!-- <label for="logo" class="form-label">{{ 'form.upload-image' | translate }}:</label>-->
<!-- <input type="file" class="form-control" id="logo" (change)="onFileSelected($event)" accept="image/*"/>-->
<!-- </div>-->

<!-- <div class="mb-3" *ngIf="partnerForm.get('logoUrl')?.value !== null">-->
<!-- <div class="delete-image" (click)="onDeleteImage()">-->
<!-- <img src="{{partner.logoUrl}}" width="40" height="40"/>-->
<!-- <p class="mb-0 ms-3">{{ 'system.delete-image' | translate }}</p>-->
<!-- </div>-->
<!-- </div>-->

<button type="submit" class="btn btn-primary" [disabled]="saleForm.invalid">{{ 'form.send' | translate }}
</button>
</form>
</div>


+ 0
- 0
matsen-tool/src/app/sales/new-sale/new-sale.component.scss Zobrazit soubor


+ 23
- 0
matsen-tool/src/app/sales/new-sale/new-sale.component.spec.ts Zobrazit soubor

@@ -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<NewSaleComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [NewSaleComponent]
})
.compileComponents();
fixture = TestBed.createComponent(NewSaleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 126
- 0
matsen-tool/src/app/sales/new-sale/new-sale.component.ts Zobrazit soubor

@@ -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<ModalStatus> = new EventEmitter<ModalStatus>();

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<string, readonly {
id: any;
name: any
}[]> = (text$: Observable<string>) =>
text$.pipe(
debounceTime(200),
distinctUntilChanged(),
filter((term) => term.length >= 2),
switchMap((term) => this.fetchPartners(term)),
map((partners) => partners.slice(0, 10)),
);

protected searchProducts: OperatorFunction<string, readonly {
id: any;
name: any
}[]> = (text$: Observable<string>) =>
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);
}
);
}
}
}
}

+ 6
- 4
matsen-tool/src/app/sales/sales.component.ts Zobrazit soubor

@@ -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();
}
});
}


+ 5
- 1
matsen-tool/src/assets/i18n/de.json Zobrazit soubor

@@ -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":


Načítá se…
Zrušit
Uložit