Fixed error to function to create purchase order

This commit is contained in:
2026-05-27 12:20:25 +01:00
parent 56d3d1bea7
commit a7ef707388
10 changed files with 118 additions and 75 deletions
@@ -6,7 +6,7 @@
<nz-form-control nzSpan="12" nzErrorTip="Ce champ est requis"> <nz-form-control nzSpan="12" nzErrorTip="Ce champ est requis">
<nz-select formControlName="supplierId" nzPlaceHolder="Choisir un fournisseur" nzShowSearch> <nz-select formControlName="supplierId" nzPlaceHolder="Choisir un fournisseur" nzShowSearch>
@for (supplier of suppliers(); track supplier.id){ @for (supplier of suppliers(); track supplier.id) {
<nz-option [nzLabel]="supplier.name" [nzValue]="supplier.id"></nz-option> <nz-option [nzLabel]="supplier.name" [nzValue]="supplier.id"></nz-option>
} }
</nz-select> </nz-select>
@@ -9,45 +9,46 @@ import {NzInputNumberComponent} from "ng-zorro-antd/input-number";
import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select"; import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select";
@Component({ @Component({
selector: 'app-add-product-supplier-form', selector: 'app-add-product-supplier-form',
imports: [ imports: [
NzRowDirective, NzRowDirective,
NzFormControlComponent, NzFormControlComponent,
NzFormLabelComponent, NzFormLabelComponent,
ReactiveFormsModule, ReactiveFormsModule,
NzFlexDirective, NzFlexDirective,
NzColDirective, NzColDirective,
NzTableComponent, NzTableComponent,
NzInputNumberComponent, NzInputNumberComponent,
NzOptionComponent, NzOptionComponent,
NzSelectComponent NzSelectComponent
], ],
templateUrl: './add-product-supplier-form.html', templateUrl: './add-product-supplier-form.html',
styleUrl: './add-product-supplier-form.css', styleUrl: './add-product-supplier-form.css',
}) })
export class AddProductSupplierForm { export class AddProductSupplierForm {
addProductForm: FormGroup = new FormGroup({ addProductForm: FormGroup = new FormGroup({
supplierId: new FormControl<number>(null, Validators.required), supplierId: new FormControl<number>(null, Validators.required),
lines: new FormArray([], Validators.required), lines: new FormArray([], Validators.required),
});
suppliers = input.required<GetSupplierDto[]>();
get lines(): FormArray {
return this.addProductForm.get('lines') as FormArray;
}
addProductToForm(selectedProducts: GetProductDto[]) {
this.lines.clear();
selectedProducts.forEach(x => {
this.lines.push(
new FormGroup({
productId: new FormControl(x.id),
name: new FormControl(x.name),
price: new FormControl(0, [Validators.required,Validators.min(0)])
})
);
}); });
}
suppliers = input.required<GetSupplierDto[]>();
products = input.required<GetProductDto[]>();
get lines(): FormArray {
return this.addProductForm.get('lines') as FormArray;
}
addProductToForm() {
this.lines.clear();
this.products().forEach(x => {
this.lines.push(
new FormGroup({
productId: new FormControl(x.id),
name: new FormControl(x.name),
price: new FormControl(0, [Validators.required, Validators.min(0)])
})
);
});
}
} }
@@ -15,8 +15,9 @@
</nz-form-label> </nz-form-label>
<nz-form-control nzSpan="12" nzErrorTip="Ce champ est requis"> <nz-form-control nzSpan="12" nzErrorTip="Ce champ est requis">
<nz-select formControlName="supplierId" nzPlaceHolder="Choisir un fournisseur" nzShowSearch> <nz-select formControlName="supplierId" [nzPlaceHolder]="getBestSupplier().name ?? 'Choisir un fournisseur'"
@for (supplier of suppliers(); track supplier.id){ nzShowSearch>
@for (supplier of suppliers(); track supplier.id) {
<nz-option [nzLabel]="supplier.name" [nzValue]="supplier.id"></nz-option> <nz-option [nzLabel]="supplier.name" [nzValue]="supplier.id"></nz-option>
} }
</nz-select> </nz-select>
@@ -1,4 +1,4 @@
import {Component, input} from '@angular/core'; import {Component, input, OnInit, signal} from '@angular/core';
import {FormBuilder, FormGroup, FormArray, Validators, ReactiveFormsModule, FormControl} from '@angular/forms'; import {FormBuilder, FormGroup, FormArray, Validators, ReactiveFormsModule, FormControl} from '@angular/forms';
import {GetProductDto, GetSupplierDto} from '../../services/api'; import {GetProductDto, GetSupplierDto} from '../../services/api';
import {NzTableComponent} from "ng-zorro-antd/table"; import {NzTableComponent} from "ng-zorro-antd/table";
@@ -8,6 +8,7 @@ import {NzFlexDirective} from "ng-zorro-antd/flex";
import {NzFormControlComponent, NzFormItemComponent, NzFormLabelComponent} from "ng-zorro-antd/form"; import {NzFormControlComponent, NzFormItemComponent, NzFormLabelComponent} from "ng-zorro-antd/form";
import {NzInputDirective} from "ng-zorro-antd/input"; import {NzInputDirective} from "ng-zorro-antd/input";
import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select"; import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select";
import {min} from "rxjs";
@Component({ @Component({
selector: 'app-create-purchaseorder-form', selector: 'app-create-purchaseorder-form',
@@ -29,6 +30,25 @@ import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select";
}) })
export class CreatePurchaseorderForm { export class CreatePurchaseorderForm {
suppliers = input.required<GetSupplierDto[]>(); suppliers = input.required<GetSupplierDto[]>();
products = input.required<GetProductDto[]>();
getBestSupplier() {
let bestSupplier: GetSupplierDto = this.suppliers()[0];
let maxProducts = 0;
const selectedProducts = this.products().map(x => x.id);
this.suppliers().forEach(x => {
const supplierProductsCount = x.prices.filter(p => selectedProducts.includes(p.productId)).length ?? 0;
if (supplierProductsCount > maxProducts) {
maxProducts = supplierProductsCount;
bestSupplier = x;
}
})
return bestSupplier;
}
createPurchaseOrderForm: FormGroup = new FormGroup({ createPurchaseOrderForm: FormGroup = new FormGroup({
purchaseConditions: new FormControl<string | null>(null, Validators.required), purchaseConditions: new FormControl<string | null>(null, Validators.required),
@@ -40,16 +60,21 @@ export class CreatePurchaseorderForm {
return this.createPurchaseOrderForm.get('lines') as FormArray; return this.createPurchaseOrderForm.get('lines') as FormArray;
} }
addProductToForm(selectedProducts: GetProductDto[]) { addProductToForm() {
this.lines.clear(); this.lines.clear();
selectedProducts.forEach(p => { this.products().forEach(x => {
this.lines.push( this.lines.push(
new FormGroup({ new FormGroup({
productId: new FormControl(p.id), productId: new FormControl(x.id),
name: new FormControl(p.name), name: new FormControl(x.name),
quantity: new FormControl(1, [Validators.required,Validators.min(0)]) quantity: new FormControl(1, [Validators.required, Validators.min(0)])
}) })
); );
}); });
const bestSupplier = this.getBestSupplier();
this.createPurchaseOrderForm.patchValue({
supplierId: bestSupplier.id,
});
} }
} }
@@ -1,4 +1,4 @@
import {Component} from '@angular/core'; import {Component, input} from '@angular/core';
import { import {
FormArray, FormArray,
FormBuilder, FormBuilder,
@@ -34,6 +34,8 @@ import {GetProductDto} from "../../services/api";
styleUrl: './create-quotation-form.css', styleUrl: './create-quotation-form.css',
}) })
export class CreateQuotationForm { export class CreateQuotationForm {
products = input.required<GetProductDto[]>();
createQuotationForm: FormGroup = new FormGroup({ createQuotationForm: FormGroup = new FormGroup({
message: new FormControl<string>(null, Validators.required), message: new FormControl<string>(null, Validators.required),
purchaseConditions: new FormControl<string>(null, Validators.required), purchaseConditions: new FormControl<string>(null, Validators.required),
@@ -44,13 +46,13 @@ export class CreateQuotationForm {
return this.createQuotationForm.get('lines') as FormArray; return this.createQuotationForm.get('lines') as FormArray;
} }
addProductToForm(selectedProducts: GetProductDto[]) { addProductToForm() {
this.lines.clear(); this.lines.clear();
selectedProducts.forEach(p => { this.products().forEach(x => {
this.lines.push( this.lines.push(
new FormGroup({ new FormGroup({
productId: new FormControl(p.id), productId: new FormControl(x.id),
name: new FormControl(p.name), name: new FormControl(x.name),
quantity: new FormControl(0, [Validators.required, Validators.min(0)]) quantity: new FormControl(0, [Validators.required, Validators.min(0)])
}) })
); );
@@ -41,7 +41,7 @@ export class StockTable implements OnInit {
modal = viewChild.required<ModalNav>('modalNav'); modal = viewChild.required<ModalNav>('modalNav');
selectionChange = output<number[]>(); selectionChange = output<number[]>();
productsTables = output<ProductWithQuantity[]>(); productsTables = output<GetProductDto[]>();
selectedProduct: GetProductDto | null = null; selectedProduct: GetProductDto | null = null;
checked: boolean = false; checked: boolean = false;
@@ -56,6 +56,7 @@ export class StockTable implements OnInit {
this.productsLoading.set(true); this.productsLoading.set(true);
try { try {
const products = await firstValueFrom(this.productsService.getAllProductsEndpoint()); const products = await firstValueFrom(this.productsService.getAllProductsEndpoint());
this.productsTables.emit(products);
const productsWithQuantity = await Promise.all( const productsWithQuantity = await Promise.all(
products.map(async (x) => { products.map(async (x) => {
@@ -74,7 +75,6 @@ export class StockTable implements OnInit {
}) })
); );
this.products.set(productsWithQuantity); this.products.set(productsWithQuantity);
this.productsTables.emit(productsWithQuantity);
} catch { } catch {
this.notificationService.error('Erreur', 'Erreur de communication avec l\'API'); this.notificationService.error('Erreur', 'Erreur de communication avec l\'API');
} }
+13 -5
View File
@@ -1,5 +1,5 @@
<div class="flex mt-2"> <div class="flex mt-2">
@if (productIds.length) { @if (productIds().length) {
<app-modal-button #modalButtonPurchaseOrder <app-modal-button #modalButtonPurchaseOrder
(click)="openPurchaseOrderForm()" (click)="openPurchaseOrderForm()"
(ok)="onModalPurchaseOrderOk()" (ok)="onModalPurchaseOrderOk()"
@@ -8,7 +8,10 @@
name="Créer un bon de commande" name="Créer un bon de commande"
size="35%" size="35%"
class="ml-4"> class="ml-4">
<app-create-purchaseorder-form #purchaseOrderForm [suppliers]="suppliers()"></app-create-purchaseorder-form> <app-create-purchaseorder-form #purchaseOrderForm
[suppliers]="suppliers()"
[products]="selectedProducts()">
</app-create-purchaseorder-form>
</app-modal-button> </app-modal-button>
<app-modal-button #modalButtonQuotation <app-modal-button #modalButtonQuotation
@@ -19,7 +22,9 @@
(click)="openQuotationForm()" (click)="openQuotationForm()"
(ok)="onModalQuotationOk()" (ok)="onModalQuotationOk()"
(cancel)="onModalQuotationCancel()"> (cancel)="onModalQuotationCancel()">
<app-create-quotation-form #quotationForm></app-create-quotation-form> <app-create-quotation-form #quotationForm
[products]="selectedProducts()">
</app-create-quotation-form>
</app-modal-button> </app-modal-button>
<app-modal-button #modalButtonSupplier <app-modal-button #modalButtonSupplier
@@ -30,13 +35,16 @@
(click)="openSupplierForm()" (click)="openSupplierForm()"
(ok)="onModalSupplierOk()" (ok)="onModalSupplierOk()"
(cancel)="onModalSupplierCancel()"> (cancel)="onModalSupplierCancel()">
<app-add-product-supplier-form #supplierForm [suppliers]="suppliers()"></app-add-product-supplier-form> <app-add-product-supplier-form #supplierForm
[suppliers]="suppliers()"
[products]="selectedProducts()">
</app-add-product-supplier-form>
</app-modal-button> </app-modal-button>
} }
</div> </div>
<div class="mt-4"> <div class="mt-4">
<app-stock-table (selectionChange)="productIds = $event" <app-stock-table (selectionChange)="onSelectionChange($event)"
(productsTables)="products.set($event)"> (productsTables)="products.set($event)">
</app-stock-table> </app-stock-table>
</div> </div>
+18 -13
View File
@@ -4,6 +4,8 @@ import {ModalButton} from "../../components/modal-button/modal-button";
import {CreatePurchaseorderForm} from "../../components/create-purchaseorder-form/create-purchaseorder-form"; import {CreatePurchaseorderForm} from "../../components/create-purchaseorder-form/create-purchaseorder-form";
import {NzNotificationService} from "ng-zorro-antd/notification"; import {NzNotificationService} from "ng-zorro-antd/notification";
import { import {
CreatePurchaseOrderDto,
GetProductDto,
GetSupplierDto, GetSupplierDto,
PurchaseordersService, PurchaseordersService,
QuotationsService, QuotationsService,
@@ -39,35 +41,36 @@ export class Stock implements OnInit {
private suppliersService = inject(SuppliersService); private suppliersService = inject(SuppliersService);
private notificationService = inject(NzNotificationService); private notificationService = inject(NzNotificationService);
products = signal([]); products = signal<GetProductDto[]>([]);
suppliers = signal<GetSupplierDto[]>([]); suppliers = signal<GetSupplierDto[]>([]);
selectedProducts = signal([]);
productIds = []; productIds = signal<number[]>([]);
async ngOnInit() { async ngOnInit() {
try { try {
const suppliers = await firstValueFrom(this.suppliersService.getAllSuppliersEndpoint()); const suppliers = await firstValueFrom(this.suppliersService.getAllSuppliersEndpoint());
this.suppliers.set(suppliers); this.suppliers.set(suppliers);
} } catch {
catch {
this.notificationService.error('Erreur', 'Erreur de communication avec l\'API'); this.notificationService.error('Erreur', 'Erreur de communication avec l\'API');
} }
} }
getSelectedProducts() { onSelectionChange(ids: number[]) {
return this.products().filter(x => this.productIds.includes(x.id)); this.productIds.set(ids);
this.selectedProducts.set(this.products().filter(x => ids.includes(x.id)));
} }
openPurchaseOrderForm() { openPurchaseOrderForm() {
this.createPurchaseOrder().addProductToForm(this.getSelectedProducts()); this.createPurchaseOrder().addProductToForm();
} }
openQuotationForm() { openQuotationForm() {
this.createQuotation().addProductToForm(this.getSelectedProducts()); this.createQuotation().addProductToForm();
} }
openSupplierForm() { openSupplierForm() {
this.addProduct().addProductToForm(this.getSelectedProducts()); this.addProduct().addProductToForm();
} }
async addPurchaseOrder() { async addPurchaseOrder() {
@@ -88,9 +91,10 @@ export class Stock implements OnInit {
return; return;
} }
const purchaseOrder = { const purchaseOrder: CreatePurchaseOrderDto = {
purchaseConditions: form.get('purchaseConditions')!.value, purchaseConditions: form.value.purchaseConditions,
products: orderLines products: orderLines,
supplierId: form.value.supplierId
}; };
try { try {
@@ -163,7 +167,8 @@ export class Stock implements OnInit {
); );
success++; success++;
} catch {} } catch {
}
} }
this.notificationService.success('Succès', `${success} produits ajoutés`); this.notificationService.success('Succès', `${success} produits ajoutés`);
} }
+3 -3
View File
@@ -59,9 +59,9 @@ In your Angular project:
```typescript ```typescript
import {ApplicationConfig} from '@angular/core'; import { ApplicationConfig } from '@angular/core';
import {provideHttpClient} from '@angular/common/http'; import { provideHttpClient } from '@angular/common/http';
import {provideApi} from ''; import { provideApi } from '';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [
@@ -12,6 +12,7 @@ import {CreatePurchaseOrderProductDto} from './create-purchase-order-product-dto
export interface CreatePurchaseOrderDto { export interface CreatePurchaseOrderDto {
purchaseConditions?: string | null; purchaseConditions?: string | null;
supplierId?: number;
products?: Array<CreatePurchaseOrderProductDto> | null; products?: Array<CreatePurchaseOrderProductDto> | null;
} }