Added checkbox in stock page

This commit is contained in:
2026-05-26 18:35:44 +01:00
parent 4dd1d7e81d
commit 961551e926
8 changed files with 310 additions and 189 deletions
@@ -0,0 +1,40 @@
<form [formGroup]="addProductForm">
<nz-form-item nz-flex>
<nz-form-label nzSpan="12" nzRequired>
Fournisseur
</nz-form-label>
<nz-form-control nzSpan="12" nzErrorTip="Ce champ est requis">
<nz-select formControlName="supplierId" nzPlaceHolder="Choisir un fournisseur" nzShowSearch>
@for (supplier of suppliers(); track supplier.id){
<nz-option [nzLabel]="supplier.name" [nzValue]="supplier.id"></nz-option>
}
</nz-select>
</nz-form-control>
</nz-form-item>
<div class="overflow-x-auto mt-6">
<nz-table [nzBordered]="true" class="mx-auto text-center">
<thead>
<tr>
<th class="text-center">Produit</th>
<th class="text-center">Prix</th>
</tr>
</thead>
<tbody formArrayName="lines">
@for (line of lines.controls; let i = $index; track i) {
<tr [formGroupName]="i" class="text-center">
<td class="text-center">{{ line.value.name }}</td>
<td class="text-center">
<nz-input-number
formControlName="price"
[nzMin]="1"
[nzStep]="1">
</nz-input-number>
</td>
</tr>
}
</tbody>
</nz-table>
</div>
</form>
@@ -0,0 +1,68 @@
import {Component, inject, OnInit, signal} from '@angular/core';
import {FormArray, FormControl, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
import {GetProductDto, GetSupplierDto, SuppliersService} from "../../services/api";
import {NzColDirective, NzRowDirective} from "ng-zorro-antd/grid";
import {NzFormControlComponent, NzFormLabelComponent} from "ng-zorro-antd/form";
import {NzFlexDirective} from "ng-zorro-antd/flex";
import {NzTableComponent} from "ng-zorro-antd/table";
import {NzInputNumberComponent} from "ng-zorro-antd/input-number";
import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select";
import {firstValueFrom} from "rxjs";
import {NzNotificationService} from "ng-zorro-antd/notification";
@Component({
selector: 'app-add-product-supplier-form',
imports: [
NzRowDirective,
NzFormControlComponent,
NzFormLabelComponent,
ReactiveFormsModule,
NzFlexDirective,
NzColDirective,
NzTableComponent,
NzInputNumberComponent,
NzOptionComponent,
NzSelectComponent
],
templateUrl: './add-product-supplier-form.html',
styleUrl: './add-product-supplier-form.css',
})
export class AddProductSupplierForm implements OnInit {
addProductForm: FormGroup = new FormGroup({
supplierId: new FormControl<number>(null, Validators.required),
lines: new FormArray([], Validators.required),
});
private suppliersServices = inject(SuppliersService);
private notificationService = inject(NzNotificationService);
suppliers = signal<GetSupplierDto[]>([]);
async ngOnInit() {
try {
const suppliers = await firstValueFrom(this.suppliersServices.getAllSuppliersEndpoint());
this.suppliers.set(suppliers);
}
catch {
this.notificationService.error('Erreur', 'Erreur de communication avec l\'API');
}
}
get lines(): FormArray {
return this.addProductForm.get('lines') as FormArray;
}
addProductToForm(selectedProducts: GetProductDto[]) {
this.lines.clear();
selectedProducts.forEach(p => {
this.lines.push(
new FormGroup({
productId: new FormControl(p.id),
name: new FormControl(p.name),
price: new FormControl(1, [Validators.required,Validators.min(0)])
})
);
});
}
}
@@ -1,18 +1,16 @@
<nz-table <nz-table
[nzData]="filteredProducts()" [nzData]="products()"
[nzFrontPagination]="false" [nzFrontPagination]="false"
[nzLoading]="productsLoading()" [nzLoading]="productsLoading()"
(nzCurrentPageDataChange)="onCurrentPageDataChange($event)"
> >
<thead> <thead>
<tr class="text-center"> <tr class="text-center">
<th nzWidth="40px"> <th nzWidth="40px">
<label <label nz-checkbox
nz-checkbox [(ngModel)]="checked"
[(ngModel)]="checked" [nzIndeterminate]="indeterminate"
[nzIndeterminate]="indeterminate" (ngModelChange)="allCheck($event)">
(ngModelChange)="onAllChecked($event)" </label>
></label>
</th> </th>
<th>Nom</th> <th>Nom</th>
<th>Référence</th> <th>Référence</th>
@@ -27,16 +25,15 @@
</thead> </thead>
<tbody class="text-center"> <tbody class="text-center">
@for (product of filteredProducts(); track product.id) { @for (product of products(); track product.id) {
<tr> <tr>
<td nzWidth="40px"> <td nzWidth="40px">
<label <label
nz-checkbox nz-checkbox
[ngModel]="setOfCheckedId.has(product.id)" [ngModel]="selectedIds.includes(product.id)"
(ngModelChange)="onItemChecked(product.id, $event)" (ngModelChange)="onItemChecked(product.id, $event)"
></label> ></label>
</td> </td>
<td>{{ product.name }}</td> <td>{{ product.name }}</td>
<td>{{ product.references }}</td> <td>{{ product.references }}</td>
<td>{{ product.nec }}</td> <td>{{ product.nec }}</td>
+70 -121
View File
@@ -1,14 +1,14 @@
import {Component, computed, inject, OnInit, output, signal, viewChild} from '@angular/core'; import {Component, inject, OnInit, output, signal, viewChild} from '@angular/core';
import {NzTableComponent, NzThMeasureDirective} from "ng-zorro-antd/table"; import {NzTableComponent, NzThMeasureDirective} from "ng-zorro-antd/table";
import {ModalNav} from "../modal-nav/modal-nav"; import {ModalNav} from "../modal-nav/modal-nav";
import {NzIconDirective} from "ng-zorro-antd/icon"; import {NzIconDirective} from "ng-zorro-antd/icon";
import {StockForm} from "../stock-form/stock-form"; import {StockForm} from "../stock-form/stock-form";
import {NzDividerComponent} from "ng-zorro-antd/divider"; import {NzDividerComponent} from "ng-zorro-antd/divider";
import {FormsModule} from "@angular/forms"; import {FormsModule} from "@angular/forms";
import {NzCheckboxComponent} from "ng-zorro-antd/checkbox";
import {GetProductDto, ProductsService, WarehouseproductsService} from "../../services/api"; import {GetProductDto, ProductsService, WarehouseproductsService} from "../../services/api";
import {NzNotificationService} from "ng-zorro-antd/notification"; import {NzNotificationService} from "ng-zorro-antd/notification";
import {firstValueFrom} from "rxjs"; import {first, firstValueFrom} from "rxjs";
import {NzCheckboxComponent} from "ng-zorro-antd/checkbox";
interface ProductWithQuantity extends GetProductDto { interface ProductWithQuantity extends GetProductDto {
totalQuantity?: number; totalQuantity?: number;
@@ -23,8 +23,8 @@ interface ProductWithQuantity extends GetProductDto {
StockForm, StockForm,
NzDividerComponent, NzDividerComponent,
FormsModule, FormsModule,
NzCheckboxComponent,
NzThMeasureDirective, NzThMeasureDirective,
NzCheckboxComponent,
], ],
templateUrl: './stock-table.html', templateUrl: './stock-table.html',
styleUrl: './stock-table.css', styleUrl: './stock-table.css',
@@ -34,109 +34,49 @@ export class StockTable implements OnInit {
private productsService = inject(ProductsService); private productsService = inject(ProductsService);
private wareHousseProductsService = inject(WarehouseproductsService) private wareHousseProductsService = inject(WarehouseproductsService)
private notificationService = inject(NzNotificationService) private notificationService = inject(NzNotificationService)
products = signal<ProductWithQuantity[]>([]); products = signal<ProductWithQuantity[]>([]);
productsLoading = signal<boolean>(false); productsLoading = signal<boolean>(false);
updateProduct = viewChild.required<StockForm>('stockForm');
modal = viewChild.required<ModalNav>('modalNav'); modal = viewChild.required<ModalNav>('modalNav');
checked = false; selectionChange = output<number[]>();
indeterminate = false; productsTables = output<ProductWithQuantity[]>();
setOfCheckedId = new Set<number>();
selectionChange = output<boolean>()
currentPageData: GetProductDto[] = [];
private searchQuery = signal<string>(''); selectedProduct: GetProductDto | null = null;
checked: boolean = false;
filteredProducts = computed(() => { indeterminate: boolean = false;
const q = this.searchQuery().toLowerCase().trim(); selectedIds: number[] = [];
if (!q) return this.products();
return this.products().filter(s => {
const name = (s.name ?? '').toLowerCase();
return name.includes(q);
});
});
applySearch(query: string) {
this.searchQuery.set(query);
}
get hasSelection(): boolean {
return this.setOfCheckedId.size > 0;
}
updateCheckedSet(id: number, checked: boolean): void {
if (checked) this.setOfCheckedId.add(id);
else this.setOfCheckedId.delete(id);
}
onItemChecked(id: number, checked: boolean): void {
this.updateCheckedSet(id, checked);
this.refreshCheckedStatus();
}
onAllChecked(checked: boolean): void {
this.currentPageData.forEach(item =>
this.updateCheckedSet(item.id, checked)
);
this.refreshCheckedStatus();
}
onCurrentPageDataChange($event: GetProductDto[]): void {
this.currentPageData = $event;
this.refreshCheckedStatus();
}
refreshCheckedStatus(): void {
const total = this.currentPageData.length;
const checkedCount = this.currentPageData.filter(p => this.setOfCheckedId.has(p.id)).length;
this.checked = checkedCount === total;
this.indeterminate = checkedCount > 0 && checkedCount < total;
setTimeout(() => this.selectionChange.emit(this.hasSelection));
}
get selectedIds() {
return Array.from(this.setOfCheckedId);
}
async ngOnInit() { async ngOnInit() {
await this.fetchProducts(); await this.fetchProducts();
} }
async fetchTotalQuantity(product: ProductWithQuantity) {
try {
const res = await firstValueFrom(
this.wareHousseProductsService.getTotalQuantityEndpoint(product.id)
);
product.totalQuantity = res.totalQuantity;
} catch (e) {
product.totalQuantity = 0;
}
}
async fetchProducts() { async fetchProducts() {
this.productsLoading.set(true); this.productsLoading.set(true);
try { try {
const products = await firstValueFrom(this.productsService.getAllProductsEndpoint()); const products = await firstValueFrom(this.productsService.getAllProductsEndpoint());
// transforme chaque produit en ProductWithQuantity const productsWithQuantity = await Promise.all(
const productsWithQuantity: ProductWithQuantity[] = products.map(p => ({...p})); products.map(async (x) => {
try {
this.products.set(productsWithQuantity); const quantity = await firstValueFrom(this.wareHousseProductsService.getTotalQuantityEndpoint(x.id));
return {
// récupérer la quantité pour chaque produit en parallèle ...x,
await Promise.all(productsWithQuantity.map(p => this.fetchTotalQuantity(p))); totalQuantity: quantity.totalQuantity ?? 0
};
// déclencher la mise à jour du signal } catch {
this.products.set([...productsWithQuantity]); return {
} catch (e) { ...x,
this.notificationService.error( totalQuantity: 0
'Erreur', };
'Erreur de communication avec l\'API' }
})
); );
this.products.set(productsWithQuantity);
this.productsTables.emit(productsWithQuantity);
} catch {
this.notificationService.error('Erreur', 'Erreur de communication avec l\'API');
} }
this.productsLoading.set(false); this.productsLoading.set(false);
} }
@@ -144,48 +84,28 @@ export class StockTable implements OnInit {
async delete(productId: number) { async delete(productId: number) {
try { try {
await firstValueFrom(this.productsService.deleteProductEndpoint(productId)) await firstValueFrom(this.productsService.deleteProductEndpoint(productId))
this.notificationService.success( this.notificationService.success('Success', 'Suppression effectuée');
'Success', } catch {
'Suppression effectuée' this.notificationService.error('Erreur', 'Impossible de supprimer la ligne');
)
} catch (e) {
this.notificationService.error(
'Erreur',
'Impossible de supprimer la ligne'
)
} }
await this.fetchProducts(); await this.fetchProducts();
} }
async edit(id: number, updateProductComponent: StockForm) { async edit(id: number, updateProductComponent: StockForm) {
if (updateProductComponent.stockForm.invalid) { if (updateProductComponent.stockForm.invalid) {
this.notificationService.error( this.notificationService.error('Erreur', 'Erreur d\'écriture dans le formulaire')
'Erreur',
'Erreur d\'écriture dans le formulaire'
)
return; return;
} }
try { try {
const products = updateProductComponent.stockForm.getRawValue(); const products = updateProductComponent.stockForm.getRawValue();
await firstValueFrom(this.productsService.patchProductMinimalStockEndpoint(id, products)) await firstValueFrom(this.productsService.patchProductMinimalStockEndpoint(id, products));
await this.fetchProducts();
this.notificationService.success( this.notificationService.success('Success', 'Limite de stock modifiée');
'Success', } catch {
'Limite de stock modifiée' this.notificationService.error('Erreur', 'Erreur lors de la modification');
)
} catch (e) {
console.error(e);
this.notificationService.error(
'Erreur',
'Erreur lors de la modification'
)
} }
} }
selectedProduct: GetProductDto | null = null;
openEditModal(product: GetProductDto) { openEditModal(product: GetProductDto) {
this.selectedProduct = {...product}; this.selectedProduct = {...product};
this.modal().showModal(); this.modal().showModal();
@@ -193,7 +113,6 @@ export class StockTable implements OnInit {
async onModalOk(productId: number, updateProductComponent: StockForm, modal: ModalNav) { async onModalOk(productId: number, updateProductComponent: StockForm, modal: ModalNav) {
if (!this.selectedProduct) return; if (!this.selectedProduct) return;
await this.edit(productId, updateProductComponent); await this.edit(productId, updateProductComponent);
updateProductComponent.stockForm.reset(); updateProductComponent.stockForm.reset();
modal.isVisible = false; modal.isVisible = false;
@@ -203,4 +122,34 @@ export class StockTable implements OnInit {
onModalCancel(modal: ModalNav) { onModalCancel(modal: ModalNav) {
modal.isVisible = false; modal.isVisible = false;
} }
updateCheck(id: number, checked: boolean) {
if (checked) {
if (!this.selectedIds.includes(id)) {
this.selectedIds.push(id);
}
} else this.selectedIds = this.selectedIds.filter(x => x !== id);
}
refreshCheckStatus() {
const total = this.products().length;
const checkedCount = this.selectedIds.length;
this.checked = checkedCount === total;
this.indeterminate = checkedCount > 0 && checkedCount < total;
this.selectionChange.emit(this.selectedIds);
}
allCheck(checked: boolean) {
this.products().forEach(x =>
this.updateCheck(x.id, checked)
);
this.refreshCheckStatus();
}
onItemChecked(id: number, checked: boolean): void {
this.updateCheck(id, checked);
this.refreshCheckStatus();
}
} }
@@ -22,6 +22,8 @@ import {GetSupplierDto} from "../../services/api";
styleUrl: './supplier-form.css', styleUrl: './supplier-form.css',
}) })
export class SupplierForm { export class SupplierForm {
supplier = input<GetSupplierDto>();
supplierForm: FormGroup = new FormGroup({ supplierForm: FormGroup = new FormGroup({
name: new FormControl<string>(null, [Validators.required]), name: new FormControl<string>(null, [Validators.required]),
email: new FormControl<string>(null, [Validators.required]), email: new FormControl<string>(null, [Validators.required]),
@@ -33,8 +35,6 @@ export class SupplierForm {
}) })
supplier = input<GetSupplierDto>();
constructor() { constructor() {
effect(() => { effect(() => {
if (this.supplier()) { if (this.supplier()) {
+17 -4
View File
@@ -1,9 +1,9 @@
<div class="flex mt-2"> <div class="flex mt-2">
@if (hasSelection) { @if (productIds.length) {
<app-modal-button #modalButtonPurchaseOrder <app-modal-button #modalButtonPurchaseOrder
(click)="openPurchaseOrderForm()" (click)="openPurchaseOrderForm()"
(ok)="onModalOk()" (ok)="onModalPurchaseOrderOk()"
(cancel)="onModalCancel()" (cancel)="onModalPurchaseOrderCancel()"
type="default" type="default"
name="Créer un bon de commande" name="Créer un bon de commande"
size="35%" size="35%"
@@ -21,9 +21,22 @@
(cancel)="onModalQuotationCancel()"> (cancel)="onModalQuotationCancel()">
<app-create-quotation-form #quotationForm></app-create-quotation-form> <app-create-quotation-form #quotationForm></app-create-quotation-form>
</app-modal-button> </app-modal-button>
<app-modal-button #modalButtonSupplier
type="default"
name="Associer à un fournisseur"
size="35%"
class="ml-4"
(click)="openSupplierForm()"
(ok)="onModalSupplierOk()"
(cancel)="onModalSupplierCancel()">
<app-add-product-supplier-form #supplierForm></app-add-product-supplier-form>
</app-modal-button>
} }
</div> </div>
<div class="mt-4"> <div class="mt-4">
<app-stock-table #stockTable (selectionChange)="onSelectionChange($event)"></app-stock-table> <app-stock-table (selectionChange)="productIds = $event"
(productsTables)="products.set($event)">
</app-stock-table>
</div> </div>
+105 -51
View File
@@ -1,11 +1,12 @@
import {Component, inject, viewChild} from '@angular/core'; import {Component, inject, signal, viewChild} from '@angular/core';
import {StockTable} from "../../components/stock-table/stock-table"; import {StockTable} from "../../components/stock-table/stock-table";
import {ModalButton} from "../../components/modal-button/modal-button"; import {ModalButton} from "../../components/modal-button/modal-button";
import {PurchaseordersService, QuotationsService} from "../../services/api";
import {NzNotificationService} from "ng-zorro-antd/notification";
import {firstValueFrom} from "rxjs";
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 {CreatePriceDto, PurchaseordersService, QuotationsService, SuppliersService} from "../../services/api";
import {firstValueFrom} from "rxjs";
import {CreateQuotationForm} from "../../components/create-quotation-form/create-quotation-form"; import {CreateQuotationForm} from "../../components/create-quotation-form/create-quotation-form";
import {AddProductSupplierForm} from "../../components/add-product-supplier-form/add-product-supplier-form";
@Component({ @Component({
selector: 'app-stock', selector: 'app-stock',
@@ -14,6 +15,7 @@ import {CreateQuotationForm} from "../../components/create-quotation-form/create
ModalButton, ModalButton,
CreatePurchaseorderForm, CreatePurchaseorderForm,
CreateQuotationForm, CreateQuotationForm,
AddProductSupplierForm,
], ],
templateUrl: './stock.html', templateUrl: './stock.html',
styleUrl: './stock.css', styleUrl: './stock.css',
@@ -22,112 +24,164 @@ import {CreateQuotationForm} from "../../components/create-quotation-form/create
export class Stock { export class Stock {
createPurchaseOrder = viewChild.required<CreatePurchaseorderForm>('purchaseOrderForm'); createPurchaseOrder = viewChild.required<CreatePurchaseorderForm>('purchaseOrderForm');
createQuotation = viewChild.required<CreateQuotationForm>('quotationForm'); createQuotation = viewChild.required<CreateQuotationForm>('quotationForm');
productTable = viewChild.required<StockTable>('stockTable'); addProduct = viewChild.required<AddProductSupplierForm>('supplierForm');
private purchaseordersService = inject(PurchaseordersService)
private quotationsService = inject(QuotationsService)
private notificationService = inject(NzNotificationService)
modalButtonPurchaseOrder = viewChild.required<ModalButton>('modalButtonPurchaseOrder'); modalButtonPurchaseOrder = viewChild.required<ModalButton>('modalButtonPurchaseOrder');
modalButtonQuotation = viewChild.required<ModalButton>('modalButtonQuotation'); modalButtonQuotation = viewChild.required<ModalButton>('modalButtonQuotation');
modalButtonSupplier = viewChild.required<ModalButton>('modalButtonSupplier');
hasSelection = false; private purchaseOrdersService = inject(PurchaseordersService);
private quotationsService = inject(QuotationsService);
private suppliersService = inject(SuppliersService);
private notificationService = inject(NzNotificationService);
onSelectionChange(value: boolean) { products = signal([]);
this.hasSelection = value;
productIds = [];
getSelectedProducts() {
return this.products().filter(x => this.productIds.includes(x.id));
}
openPurchaseOrderForm() {
this.createPurchaseOrder().syncSelectedProducts(this.getSelectedProducts());
}
openQuotationForm() {
this.createQuotation().syncSelectedProducts(this.getSelectedProducts());
}
openSupplierForm() {
this.addProduct().addProductToForm(this.getSelectedProducts());
} }
async addPurchaseOrder() { async addPurchaseOrder() {
const form = this.createPurchaseOrder().createPurchaseOrderForm; const form = this.createPurchaseOrder().createPurchaseOrderForm;
if (form.invalid) { if (form.invalid) {
this.notificationService.error('Erreur', 'Formulaire invalide'); this.notificationService.error('Erreur', 'Formulaire invalide');
return; return;
} }
const orderLines = this.createPurchaseOrder().lines.value.map(line => ({ const orderLines = this.createPurchaseOrder().lines.value.map(line => ({
productId: line.productId, productId: line.productId,
quantity: line.quantity quantity: line.quantity
})); }));
if (orderLines.length === 0) {
if (!orderLines.length) {
this.notificationService.error('Erreur', 'Aucun produit sélectionné'); this.notificationService.error('Erreur', 'Aucun produit sélectionné');
return; return;
} }
const purchaseOrder = { const purchaseOrder = {
purchaseConditions: form.get('purchaseConditions')!.value, purchaseConditions: form.get('purchaseConditions')!.value,
products: orderLines products: orderLines
}; };
try { try {
await firstValueFrom( await firstValueFrom(this.purchaseOrdersService.createPurchaseOrder(purchaseOrder));
this.purchaseordersService.createPurchaseOrder(purchaseOrder)
);
this.notificationService.success('Succès', 'Bon de commande créé'); this.notificationService.success('Succès', 'Bon de commande créé');
} catch (e) { } catch {
this.notificationService.error('Erreur', 'Erreur lors de la création du bon de commande.'); this.notificationService.error('Erreur', 'Erreur lors de la création du bon de commande.');
} }
}
async onModalOk() {
await this.addPurchaseOrder();
this.createPurchaseOrder().createPurchaseOrderForm.reset();
this.modalButtonPurchaseOrder().isVisible = false;
await this.productTable().fetchProducts();
}
onModalCancel() {
this.modalButtonPurchaseOrder().isVisible = false;
}
openPurchaseOrderForm() {
const selectedProducts = this.productTable().products().filter(p =>
this.productTable().selectedIds.includes(p.id)
);
this.createPurchaseOrder().syncSelectedProducts(selectedProducts);
} }
async addQuotation() { async addQuotation() {
if (this.createQuotation().createQuotationForm.invalid) { const form = this.createQuotation().createQuotationForm;
if (form.invalid) {
this.notificationService.error('Erreur', 'Formulaire invalide'); this.notificationService.error('Erreur', 'Formulaire invalide');
return; return;
} }
const orderLines = this.createQuotation().lines.value.map(line => ({ const orderLines = this.createQuotation().lines.value.map(line => ({
productId: line.productId, productId: line.productId,
quantity: line.quantity quantity: line.quantity
})); }));
if (orderLines.length === 0) {
if (!orderLines.length) {
this.notificationService.error('Erreur', 'Aucun produit sélectionné'); this.notificationService.error('Erreur', 'Aucun produit sélectionné');
return; return;
} }
const quotation = { const quotation = {
message: this.createQuotation().createQuotationForm.get('message')!.value, message: this.createQuotation().createQuotationForm.get('message')!.value,
purchaseConditions: this.createQuotation().createQuotationForm.get('purchaseConditions')!.value, purchaseConditions: this.createQuotation().createQuotationForm.get('purchaseConditions')!.value,
products: orderLines products: orderLines
}; };
try { try {
await firstValueFrom( await firstValueFrom(this.quotationsService.createQuotationEndpoint(quotation));
this.quotationsService.createQuotationEndpoint(quotation) this.notificationService.success('Succès', 'Bon de commande créé');
); } catch {
this.notificationService.success('Succès', 'Devis créé'); this.notificationService.error('Erreur', 'Erreur lors de la création du bon de commande.');
} catch (e) { }
console.log(this.createQuotation()); }
this.notificationService.error('Erreur', 'Erreur lors de la création du devis.');
async addProductFromSupplier() {
const form = this.addProduct().addProductForm;
let success = 0;
if (form.invalid) {
this.notificationService.error('Erreur', 'Formulaire invalide');
return;
} }
const supplierId = form.value.supplierId;
const lines = this.addProduct().lines.value;
if (!lines.length) {
this.notificationService.error('Erreur', 'Aucun produit sélectionné');
return;
}
for (const line of lines) {
try {
await firstValueFrom(
this.suppliersService.addProductToSupplierEndpoint(
supplierId,
line.productId,
{
sellingPrice: line.price
}
)
);
success++;
} catch {}
}
this.notificationService.success('Succès', `${success} produits ajoutés`);
}
async onModalPurchaseOrderOk() {
await this.addPurchaseOrder();
this.createPurchaseOrder().createPurchaseOrderForm.reset();
this.modalButtonPurchaseOrder().isVisible = false;
this.onModalPurchaseOrderCancel();
}
onModalPurchaseOrderCancel() {
this.modalButtonPurchaseOrder().isVisible = false;
} }
async onModalQuotationOk() { async onModalQuotationOk() {
console.log(this.createQuotation().createQuotationForm.getRawValue());
await this.addQuotation(); await this.addQuotation();
this.createQuotation().createQuotationForm.reset(); this.createQuotation().createQuotationForm.reset();
this.modalButtonQuotation().isVisible = false; this.modalButtonQuotation().isVisible = false;
await this.productTable().fetchProducts(); this.onModalQuotationCancel();
} }
onModalQuotationCancel() { onModalQuotationCancel() {
this.modalButtonQuotation().isVisible = false; this.modalButtonQuotation().isVisible = false;
} }
openQuotationForm() { async onModalSupplierOk() {
const selectedProducts = this.productTable().products().filter(p => await this.addProductFromSupplier();
this.productTable().selectedIds.includes(p.id) this.addProduct().addProductForm.reset();
); this.modalButtonSupplier().isVisible = false;
this.createQuotation().syncSelectedProducts(selectedProducts); this.onModalSupplierCancel();
}
onModalSupplierCancel() {
this.modalButtonSupplier().isVisible = false;
} }
} }