- @for (product of quotation.getQuotationProductDto; track product.productId) {
+ @for (product of quotation.products; track product.productId) {
| {{ product.productReferences }} |
{{ product.productName }} |
Price ??? |
- Quantité ??? |
+ {{ product.quantity }} |
-
+
+
+
|
@@ -70,4 +72,10 @@
+
+
+
\ No newline at end of file
diff --git a/src/app/components/quotation-table/quotation-table.ts b/src/app/components/quotation-table/quotation-table.ts
index 5c63d21..eab961d 100644
--- a/src/app/components/quotation-table/quotation-table.ts
+++ b/src/app/components/quotation-table/quotation-table.ts
@@ -5,10 +5,16 @@ import {ModalNav} from "../modal-nav/modal-nav";
import {NzDividerComponent} from "ng-zorro-antd/divider";
import {NzIconDirective} from "ng-zorro-antd/icon";
import {QuotationForm} from "../quotation-form/quotation-form";
-import {GetQuotationDto, QuotationsService} from "../../services/api";
+import {
+ GetQuotationDto,
+ GetQuotationProductDto,
+ QuotationproductsService,
+ QuotationsService
+} from "../../services/api";
import {NzNotificationService} from "ng-zorro-antd/notification";
import {firstValueFrom} from "rxjs";
import {FileService} from "../../services/file.service";
+import {QuantityForm} from "../quantity-form/quantity-form";
@Component({
selector: 'app-quotation-table',
@@ -19,6 +25,7 @@ import {FileService} from "../../services/file.service";
NzIconDirective,
NzTableComponent,
QuotationForm,
+ QuantityForm,
],
templateUrl: './quotation-table.html',
styleUrl: './quotation-table.css',
@@ -27,10 +34,12 @@ import {FileService} from "../../services/file.service";
export class QuotationTable implements OnInit {
private quotationsService = inject(QuotationsService);
private notificationService = inject(NzNotificationService);
+ private quotationProductsService = inject(QuotationproductsService)
private fileService = inject(FileService);
quotations = signal([]);
quotationsLoading = signal(false);
modal = viewChild.required('modalNav');
+ modalQuantity = viewChild.required('modalQuantity');
async ngOnInit() {
await this.fetchQuotations();
@@ -102,6 +111,43 @@ export class QuotationTable implements OnInit {
}
}
+ async deleteProduct(productId: number, quotationId: number) {
+ this.quotationsLoading.set(true)
+ try {
+ await firstValueFrom(this.quotationProductsService.deleteQuotationProductEndpoint(productId, quotationId))
+ this.notificationService.success(
+ 'Success',
+ 'Suppression effectuée'
+ )
+ } catch (e) {
+ this.notificationService.error(
+ 'Erreur',
+ 'Impossible de supprimer la ligne'
+ )
+ }
+ this.quotationsLoading.set(false)
+ await this.fetchQuotations();
+ }
+
+ async editQuantity(productId: number, quotationId: number, updateQuantityComponent: QuantityForm) {
+ if (updateQuantityComponent.quantityForm.invalid) {
+ this.notificationService.error(
+ 'Erreur',
+ 'Erreur d\'écriture dans le formulaire'
+ )
+ return;
+ }
+
+ try {
+ const quantity = updateQuantityComponent.quantityForm.getRawValue();
+ await firstValueFrom(this.quotationProductsService.patchQuotationProductQuantityEndpoint(productId, quotationId, quantity))
+
+ this.notificationService.success('Success', 'Quantité modifiée')
+ } catch (e) {
+ this.notificationService.error('Erreur', 'Erreur lors de la modification')
+ }
+ }
+
selectedQuotation: GetQuotationDto | null = null;
openEditModal(quotation: GetQuotationDto) {
this.selectedQuotation = { ...quotation };
@@ -120,5 +166,20 @@ export class QuotationTable implements OnInit {
onModalCancel(modal: ModalNav) {
modal.isVisible = false;
}
+
+ selectedQuantity: GetQuotationProductDto | null = null;
+ openEditQuantityModal(quantity: GetQuotationProductDto) {
+ this.selectedQuantity = { ...quantity };
+ this.modalQuantity().showModal();
+ }
+
+ async onModalQuantityOk(productId: number, quotationId: number, updateQuantityComponent: QuantityForm, modal: ModalNav) {
+ if (!this.selectedQuantity) return;
+
+ await this.editQuantity(productId, quotationId, updateQuantityComponent);
+ updateQuantityComponent.quantityForm.reset();
+ modal.isVisible = false;
+ await this.fetchQuotations();
+ }
}
diff --git a/src/app/pages/stock/stock.html b/src/app/pages/stock/stock.html
index d44d876..f123e20 100644
--- a/src/app/pages/stock/stock.html
+++ b/src/app/pages/stock/stock.html
@@ -11,8 +11,15 @@
-
-
+
+
}
diff --git a/src/app/pages/stock/stock.ts b/src/app/pages/stock/stock.ts
index fa0a89a..4b53257 100644
--- a/src/app/pages/stock/stock.ts
+++ b/src/app/pages/stock/stock.ts
@@ -2,12 +2,12 @@ import {Component, inject, viewChild} from '@angular/core';
import {StockTable} from "../../components/stock-table/stock-table";
import {Search} from "../../components/search/search";
import {ModalButton} from "../../components/modal-button/modal-button";
-import {PurchaseOrderForm} from "../../components/purchase-order-form/purchase-order-form";
import {QuotationForm} from "../../components/quotation-form/quotation-form";
-import {ProductsService, PurchaseordersService} from "../../services/api";
+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 {CreateQuotationForm} from "../../components/create-quotation-form/create-quotation-form";
@Component({
selector: 'app-stock',
@@ -15,85 +15,22 @@ import {CreatePurchaseorderForm} from "../../components/create-purchaseorder-for
StockTable,
Search,
ModalButton,
- QuotationForm,
CreatePurchaseorderForm,
+ CreateQuotationForm,
],
templateUrl: './stock.html',
styleUrl: './stock.css',
})
export class Stock {
- createQuotation = viewChild.required('quotationForm');
createPurchaseOrder = viewChild.required('purchaseOrderForm');
+ createQuotation = viewChild.required('quotationForm');
productTable = viewChild.required('stockTable');
- private productsService = inject(ProductsService);
private purchaseordersService = inject(PurchaseordersService)
+ private quotationsService = inject(QuotationsService)
private notificationService = inject(NzNotificationService)
modalButtonPurchaseOrder = viewChild.required('modalButtonPurchaseOrder');
-
- onProductSearch(query: string) {
- this.productTable().applySearch(query);
- }
-
- async addPurchaseOrder() {
- if (this.createPurchaseOrder().createPurchaseOrderForm.invalid) return;
-
- const orderLines = this.createPurchaseOrder().lines.value.map(line => ({
- productId: line.productId,
- quantity: line.quantity
- }));
-
- try {
- const purchaseOrder = this.createPurchaseOrder().createPurchaseOrderForm.getRawValue();
- await firstValueFrom(this.purchaseordersService.createPurchaseOrder(purchaseOrder));
- this.notificationService.success('Succès', 'Bon de commande crée')
- }catch (e) {
- console.error(e);
- this.notificationService.error('Erreur', 'Erreur lors de la création du bon de commande.')
- }
- }
-
- async onModalOk() {
- const form = this.createPurchaseOrder().createPurchaseOrderForm;
-
- if (form.invalid) {
- this.notificationService.error('Erreur', 'Formulaire invalide');
- return;
- }
-
- const orderLines = this.createPurchaseOrder().lines.value.map(line => ({
- productId: line.productId,
- quantity: line.quantity
- }));
-
- if (orderLines.length === 0) {
- this.notificationService.error('Erreur', 'Aucun produit sélectionné');
- return;
- }
-
- const purchaseOrder = {
- purchaseConditions: form.get('purchaseConditions')!.value,
- products: orderLines
- };
- console.log('DTO envoyé :', purchaseOrder);
- try {
- await firstValueFrom(
- this.purchaseordersService.createPurchaseOrder(purchaseOrder)
- );
- this.notificationService.success('Succès', 'Bon de commande créé');
- form.reset();
- this.modalButtonPurchaseOrder().isVisible = false;
- await this.productTable().fetchProducts();
-
- } catch (e) {
- console.error(e);
- this.notificationService.error('Erreur', 'Erreur lors de la création du bon de commande.');
- }
- }
-
- onModalCancel() {
- this.modalButtonPurchaseOrder().isVisible = false;
- }
+ modalButtonQuotation = viewChild.required('modalButtonQuotation');
hasSelection = false;
@@ -101,8 +38,48 @@ export class Stock {
this.hasSelection = value;
}
- test(){
- console.log(this.productTable().selectedIds);
+ onProductSearch(query: string) {
+ this.productTable().applySearch(query);
+ }
+
+ async addPurchaseOrder() {
+ const form = this.createPurchaseOrder().createPurchaseOrderForm;
+ if (form.invalid) {
+ this.notificationService.error('Erreur', 'Formulaire invalide');
+ return;
+ }
+ const orderLines = this.createPurchaseOrder().lines.value.map(line => ({
+ productId: line.productId,
+ quantity: line.quantity
+ }));
+ if (orderLines.length === 0) {
+ this.notificationService.error('Erreur', 'Aucun produit sélectionné');
+ return;
+ }
+ const purchaseOrder = {
+ purchaseConditions: form.get('purchaseConditions')!.value,
+ products: orderLines
+ };
+ try {
+ await firstValueFrom(
+ this.purchaseordersService.createPurchaseOrder(purchaseOrder)
+ );
+ this.notificationService.success('Succès', 'Bon de commande créé');
+ } catch (e) {
+ 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() {
@@ -111,4 +88,51 @@ export class Stock {
);
this.createPurchaseOrder().syncSelectedProducts(selectedProducts);
}
+
+ async addQuotation() {
+ if (this.createQuotation().createQuotationForm.invalid) {
+ this.notificationService.error('Erreur', 'Formulaire invalide');
+ return;
+ }
+ const orderLines = this.createQuotation().lines.value.map(line => ({
+ productId: line.productId,
+ quantity: line.quantity
+ }));
+ if (orderLines.length === 0) {
+ this.notificationService.error('Erreur', 'Aucun produit sélectionné');
+ return;
+ }
+ const quotation = {
+ message: this.createQuotation().createQuotationForm.get('message')!.value,
+ purchaseConditions: this.createQuotation().createQuotationForm.get('purchaseConditions')!.value,
+ products: orderLines
+ };
+ try {
+ await firstValueFrom(
+ this.quotationsService.createQuotationEndpoint(quotation)
+ );
+ this.notificationService.success('Succès', 'Devis créé');
+ } catch (e) {
+ this.notificationService.error('Erreur', 'Erreur lors de la création du devis.');
+ }
+
+ }
+
+ async onModalQuotationOk() {
+ await this.addQuotation();
+ this.createQuotation().createQuotationForm.reset();
+ this.modalButtonQuotation().isVisible = false;
+ await this.productTable().fetchProducts();
+ }
+
+ onModalQuotationCancel() {
+ this.modalButtonQuotation().isVisible = false;
+ }
+
+ openQuotationForm() {
+ const selectedProducts = this.productTable().products().filter(p =>
+ this.productTable().selectedIds.includes(p.id)
+ );
+ this.createQuotation().syncSelectedProducts(selectedProducts);
+ }
}
diff --git a/src/app/services/api/.openapi-generator/FILES b/src/app/services/api/.openapi-generator/FILES
index 0c304de..c32abf7 100644
--- a/src/app/services/api/.openapi-generator/FILES
+++ b/src/app/services/api/.openapi-generator/FILES
@@ -23,9 +23,11 @@ model/connect-user-dto.ts
model/create-deliverer-dto.ts
model/create-delivery-note-dto.ts
model/create-price-dto.ts
+model/create-product-quotation-dto.ts
model/create-purchase-order-dto.ts
model/create-purchase-order-product-dto.ts
model/create-purchase-product-dto.ts
+model/create-quotation-dto.ts
model/create-quotation-product-dto.ts
model/create-setting-dto.ts
model/create-supplier-dto.ts
diff --git a/src/app/services/api/api/quotations.service.ts b/src/app/services/api/api/quotations.service.ts
index 07ec481..7c925c7 100644
--- a/src/app/services/api/api/quotations.service.ts
+++ b/src/app/services/api/api/quotations.service.ts
@@ -16,6 +16,8 @@ import { HttpClient, HttpHeaders, HttpParams,
import { CustomHttpParameterCodec } from '../encoder';
import { Observable } from 'rxjs';
+// @ts-ignore
+import { CreateQuotationDto } from '../model/create-quotation-dto';
// @ts-ignore
import { GetQuotationDto } from '../model/get-quotation-dto';
// @ts-ignore
@@ -39,6 +41,70 @@ export class QuotationsService extends BaseService {
super(basePath, configuration);
}
+ /**
+ * @endpoint post /API/quotations
+ * @param createQuotationDto
+ * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
+ * @param reportProgress flag to report request and response progress.
+ */
+ public createQuotationEndpoint(createQuotationDto: CreateQuotationDto, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable;
+ public createQuotationEndpoint(createQuotationDto: CreateQuotationDto, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable>;
+ public createQuotationEndpoint(createQuotationDto: CreateQuotationDto, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable>;
+ public createQuotationEndpoint(createQuotationDto: CreateQuotationDto, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable {
+ if (createQuotationDto === null || createQuotationDto === undefined) {
+ throw new Error('Required parameter createQuotationDto was null or undefined when calling createQuotationEndpoint.');
+ }
+
+ let localVarHeaders = this.defaultHeaders;
+
+ const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
+ 'application/json'
+ ]);
+ if (localVarHttpHeaderAcceptSelected !== undefined) {
+ localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
+ }
+
+ const localVarHttpContext: HttpContext = options?.context ?? new HttpContext();
+
+ const localVarTransferCache: boolean = options?.transferCache ?? true;
+
+
+ // to determine the Content-Type header
+ const consumes: string[] = [
+ 'application/json'
+ ];
+ const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
+ if (httpContentTypeSelected !== undefined) {
+ localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
+ }
+
+ let responseType_: 'text' | 'json' | 'blob' = 'json';
+ if (localVarHttpHeaderAcceptSelected) {
+ if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
+ responseType_ = 'text';
+ } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
+ responseType_ = 'json';
+ } else {
+ responseType_ = 'blob';
+ }
+ }
+
+ let localVarPath = `/API/quotations`;
+ const { basePath, withCredentials } = this.configuration;
+ return this.httpClient.request('post', `${basePath}${localVarPath}`,
+ {
+ context: localVarHttpContext,
+ body: createQuotationDto,
+ responseType: responseType_,
+ ...(withCredentials ? { withCredentials } : {}),
+ headers: localVarHeaders,
+ observe: observe,
+ ...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}),
+ reportProgress: reportProgress
+ }
+ );
+ }
+
/**
* @endpoint delete /API/quotations/{id}
* @param id
diff --git a/src/app/services/api/model/create-product-quotation-dto.ts b/src/app/services/api/model/create-product-quotation-dto.ts
new file mode 100644
index 0000000..76033ca
--- /dev/null
+++ b/src/app/services/api/model/create-product-quotation-dto.ts
@@ -0,0 +1,16 @@
+/**
+ * PyroFetes
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+export interface CreateProductQuotationDto {
+ productId?: number;
+ quantity?: number;
+}
+
diff --git a/src/app/services/api/model/create-quotation-dto.ts b/src/app/services/api/model/create-quotation-dto.ts
new file mode 100644
index 0000000..7b6faaa
--- /dev/null
+++ b/src/app/services/api/model/create-quotation-dto.ts
@@ -0,0 +1,18 @@
+/**
+ * PyroFetes
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+import { CreateProductQuotationDto } from './create-product-quotation-dto';
+
+
+export interface CreateQuotationDto {
+ message?: string | null;
+ conditionsSale?: string | null;
+ products?: Array | null;
+}
+
diff --git a/src/app/services/api/model/create-quotation-product-dto.ts b/src/app/services/api/model/create-quotation-product-dto.ts
index 95a3c60..b6ea6d3 100644
--- a/src/app/services/api/model/create-quotation-product-dto.ts
+++ b/src/app/services/api/model/create-quotation-product-dto.ts
@@ -19,7 +19,7 @@ export interface CreateQuotationProductDto {
productName?: string | null;
productDuration?: number;
productCaliber?: number;
- productApprovalNumber?: number;
+ productApprovalNumber?: string | null;
productWeight?: number;
productNec?: number;
productImage?: string | null;
diff --git a/src/app/services/api/model/get-quotation-dto.ts b/src/app/services/api/model/get-quotation-dto.ts
index 2143ee1..a8d25be 100644
--- a/src/app/services/api/model/get-quotation-dto.ts
+++ b/src/app/services/api/model/get-quotation-dto.ts
@@ -14,6 +14,6 @@ export interface GetQuotationDto {
id?: number;
message?: string | null;
conditionsSale?: string | null;
- getQuotationProductDto?: Array | null;
+ products?: Array | null;
}
diff --git a/src/app/services/api/model/get-quotation-product-dto.ts b/src/app/services/api/model/get-quotation-product-dto.ts
index 09ca5f0..89eb74d 100644
--- a/src/app/services/api/model/get-quotation-product-dto.ts
+++ b/src/app/services/api/model/get-quotation-product-dto.ts
@@ -19,7 +19,7 @@ export interface GetQuotationProductDto {
productName?: string | null;
productDuration?: number;
productCaliber?: number;
- productApprovalNumber?: number;
+ productApprovalNumber?: string | null;
productWeight?: number;
productNec?: number;
productImage?: string | null;
diff --git a/src/app/services/api/model/models.ts b/src/app/services/api/model/models.ts
index 56ec3fb..f8ad444 100644
--- a/src/app/services/api/model/models.ts
+++ b/src/app/services/api/model/models.ts
@@ -2,9 +2,11 @@ export * from './connect-user-dto';
export * from './create-deliverer-dto';
export * from './create-delivery-note-dto';
export * from './create-price-dto';
+export * from './create-product-quotation-dto';
export * from './create-purchase-order-dto';
export * from './create-purchase-order-product-dto';
export * from './create-purchase-product-dto';
+export * from './create-quotation-dto';
export * from './create-quotation-product-dto';
export * from './create-setting-dto';
export * from './create-supplier-dto';