feat: Enhance customer and inventory components with new features and improvements
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
<p-dialog header="فرم مشتری" [(visible)]="visible" [modal]="true" [style]="{ width: '600px' }" [closable]="true">
|
||||
<p-dialog
|
||||
header="فرم مشتری"
|
||||
[(visible)]="visible"
|
||||
[modal]="true"
|
||||
[style]="{ width: '600px', zIndex: '100000' }"
|
||||
appendTo="body"
|
||||
[closable]="true"
|
||||
>
|
||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||
<app-input label="نام" [control]="form.controls.firstName" name="firstName" />
|
||||
<app-input label="نام خانوادگی" [control]="form.controls.lastName" name="lastName" />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<uikit-field label="مشتری" [control]="control" [showLabel]="showLabel" [showErrors]="showErrors">
|
||||
<p-select
|
||||
[loading]="loading()"
|
||||
[options]="items()"
|
||||
optionLabel="name"
|
||||
optionLabel="fullName"
|
||||
[optionValue]="selectOptionValue"
|
||||
placeholder="انتخاب مشتری"
|
||||
[formControl]="control"
|
||||
@@ -9,5 +10,21 @@
|
||||
[filter]="true"
|
||||
appendTo="body"
|
||||
>
|
||||
@if (canInsert) {
|
||||
<ng-template #footer>
|
||||
<div class="p-3">
|
||||
<p-button
|
||||
label="افزودن مشتری جدید"
|
||||
fluid
|
||||
severity="secondary"
|
||||
text
|
||||
size="small"
|
||||
icon="pi pi-plus"
|
||||
(onClick)="onOpenForm()"
|
||||
/>
|
||||
</div>
|
||||
</ng-template>
|
||||
}
|
||||
</p-select>
|
||||
<customer-form [(visible)]="isOpenFormDialog" (onSubmit)="refresh()" />
|
||||
</uikit-field>
|
||||
|
||||
@@ -2,14 +2,16 @@ import { AbstractSelectComponent } from '@/shared/components';
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { Component } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { Button } from 'primeng/button';
|
||||
import { Select } from 'primeng/select';
|
||||
import { ICustomerResponse } from '../../models';
|
||||
import { CustomersService } from '../../services/main.service';
|
||||
import { CustomerFormComponent } from '../form.component';
|
||||
|
||||
@Component({
|
||||
selector: 'customers-select-field',
|
||||
templateUrl: './select.component.html',
|
||||
imports: [ReactiveFormsModule, Select, UikitFieldComponent],
|
||||
imports: [ReactiveFormsModule, Select, UikitFieldComponent, Button, CustomerFormComponent],
|
||||
})
|
||||
export class CustomersSelectComponent extends AbstractSelectComponent<ICustomerResponse> {
|
||||
constructor(private service: CustomersService) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||
import { getFullName } from '@/utils';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { CUSTOMERS_API_ROUTES } from '../constants';
|
||||
import { ICustomerRawResponse, ICustomerRequest, ICustomerResponse } from '../models';
|
||||
|
||||
@@ -12,11 +13,22 @@ export class CustomersService {
|
||||
private apiRoutes = CUSTOMERS_API_ROUTES;
|
||||
|
||||
getAll(): Observable<IPaginatedResponse<ICustomerResponse>> {
|
||||
return this.http.get<IPaginatedResponse<ICustomerRawResponse>>(this.apiRoutes.list());
|
||||
return this.http.get<IPaginatedResponse<ICustomerRawResponse>>(this.apiRoutes.list()).pipe(
|
||||
map((res) => {
|
||||
return {
|
||||
meta: res.meta,
|
||||
data: res.data.map((item) => ({ ...item, fullName: getFullName(item) })),
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
getSingle(customerId: string): Observable<ICustomerResponse> {
|
||||
return this.http.get<ICustomerRawResponse>(this.apiRoutes.single(customerId));
|
||||
return this.http.get<ICustomerRawResponse>(this.apiRoutes.single(customerId)).pipe(
|
||||
map((res) => {
|
||||
return { ...res, fullName: getFullName(res) };
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
create(data: ICustomerRequest): Observable<ICustomerResponse> {
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
/>
|
||||
</td>
|
||||
<td>{{ movement.receiptId }}</td>
|
||||
<td><catalog-movement-reference-tag [type]="movement.info.referenceType" /></td>
|
||||
<td>
|
||||
<catalog-movement-reference-tag [type]="movement.info.referenceType" [movementType]="movement.info.type" />
|
||||
</td>
|
||||
<td>{{ movement.count }}</td>
|
||||
<td>{{ movement.info.quantity }}</td>
|
||||
<td><span [appPriceMask]="movement.info.totalCost"></span></td>
|
||||
|
||||
@@ -95,7 +95,6 @@
|
||||
@if (!form.controls.fromInventory.value) {
|
||||
<div class="text-center text-gray-500 py-10">لطفا انبار مبدا را انتخاب کنید</div>
|
||||
} @else {
|
||||
{{ form.controls.items.value.length }}
|
||||
<p-table [value]="form.controls.items.controls" class="w-full">
|
||||
<ng-template #header>
|
||||
<tr>
|
||||
@@ -107,13 +106,7 @@
|
||||
<tr>
|
||||
<td>{{ item.controls.product.value?.name }}</td>
|
||||
<td>
|
||||
<input
|
||||
pInputText
|
||||
type="number"
|
||||
min="1"
|
||||
[max]="item.controls.product.value?.quantity"
|
||||
[formControl]="form.controls.items.at(rowIndex).controls.count"
|
||||
/>
|
||||
<app-uikit-counter [min]="1" [max]="10" [control]="item.controls.count" />
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { InputComponent } from '@/shared/components';
|
||||
import { UikitFieldComponent } from '@/uikit';
|
||||
import { UikitCounterComponent, UikitFieldComponent } from '@/uikit';
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
@@ -32,6 +32,7 @@ import { InventoriesSelectComponent } from '../select/select.component';
|
||||
TableModule,
|
||||
InputText,
|
||||
ButtonDirective,
|
||||
UikitCounterComponent,
|
||||
],
|
||||
})
|
||||
export class InventoriesTransferFormComponent {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Maybe } from '@/core';
|
||||
import { KeyValueComponent } from '@/shared/components';
|
||||
import { DetailsInfoCardComponent } from '@/shared/components/detailsInfoCard/details-info-card.component';
|
||||
import { PriceMaskDirective } from '@/shared/directives';
|
||||
import { formatWithCurrency } from '@/utils';
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { Button, ButtonDirective } from 'primeng/button';
|
||||
@@ -83,7 +84,7 @@ export class InventoryComponent {
|
||||
{
|
||||
icon: 'pi pi-dollar',
|
||||
label: 'ارزش کلی کالاهای موجود',
|
||||
value: this.data()?.availableProductsCost,
|
||||
value: formatWithCurrency(this.data()?.availableProductsCost || 0),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<div class="bg-surface-card w-md shrink-0 h-full overflow-hidden rounded-xl p-4 pb-0 flex flex-col">
|
||||
<div class="shrink-0 sticky top-0">
|
||||
<customers-select-field [canInsert]="true" />
|
||||
<customers-select-field
|
||||
[canInsert]="true"
|
||||
[value]="selectedCustomer()"
|
||||
(valueChange)="updateCustomer($event)"
|
||||
[isFullDataOptionValue]="true"
|
||||
/>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="grow overflow-auto flex flex-col">
|
||||
@@ -61,7 +66,7 @@
|
||||
<app-uikit-counter
|
||||
[min]="1"
|
||||
[max]="inOrderProduct.maxQuantity"
|
||||
[value]="inOrderProduct.quantity"
|
||||
[value]="inOrderProduct.count"
|
||||
(valueChange)="updateInOrderProductQuantity(inOrderProduct.productId, $event)"
|
||||
></app-uikit-counter>
|
||||
</div>
|
||||
@@ -76,7 +81,15 @@
|
||||
<div class="flex flex-col sticky bottom-0 py-2">
|
||||
<pos-order-price-info-card />
|
||||
<div class="grid grid-cols grid-cols-2 sticky bottom-0 gap-2 pt-4">
|
||||
<button pButton type="button" label="ثبت سفارش" severity="primary" icon="pi pi-check" class="w-full"></button>
|
||||
<button
|
||||
pButton
|
||||
type="button"
|
||||
label="ثبت سفارش"
|
||||
severity="primary"
|
||||
icon="pi pi-check"
|
||||
class="w-full"
|
||||
(click)="submit()"
|
||||
></button>
|
||||
<button pButton type="button" label="لغو" outlined icon="pi pi-times" class="w-full"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { CustomersSelectComponent } from '@/modules/customers/components/select/select.component';
|
||||
import { ICustomerResponse } from '@/modules/customers/models';
|
||||
import { PriceMaskDirective } from '@/shared/directives';
|
||||
import { UikitCounterComponent } from '@/uikit';
|
||||
import { Component, computed, signal } from '@angular/core';
|
||||
@@ -25,13 +27,15 @@ import { POSOrderPriceInfoCardComponent } from './price-info-card.component';
|
||||
],
|
||||
})
|
||||
export class PosOrderCardComponent {
|
||||
constructor(private store: POSStore) {}
|
||||
constructor(private store: POSStore) {
|
||||
this.selectedCustomer.set(this.store.selectedCustomer());
|
||||
}
|
||||
|
||||
placeholderImage = images.placeholders.default;
|
||||
|
||||
inOrderProducts = computed(() => this.store.inOrderProducts());
|
||||
|
||||
value = signal(0);
|
||||
selectedCustomer = signal<Maybe<ICustomerResponse>>(null);
|
||||
|
||||
removeProductFromOrder(productId: number) {
|
||||
this.store.removeFromInOrderProducts(productId);
|
||||
@@ -41,8 +45,10 @@ export class PosOrderCardComponent {
|
||||
this.store.updateInOrderProductQuantity(productId, quantity);
|
||||
}
|
||||
|
||||
updateInOrderProductFee(productId: number, $event: Event, prevFee: string) {
|
||||
const fee = $event.target ? String(($event.target as HTMLInputElement).ariaValueNow) : prevFee;
|
||||
updateInOrderProductFee(productId: number, $event: Event, prevFee: number) {
|
||||
const fee = $event.target
|
||||
? parseFloat(($event.target as HTMLInputElement).ariaValueNow || prevFee.toString())
|
||||
: prevFee;
|
||||
|
||||
this.store.updateInOrderProductFee(productId, fee);
|
||||
}
|
||||
@@ -50,4 +56,12 @@ export class PosOrderCardComponent {
|
||||
clearOrderList() {
|
||||
this.store.resetInOrderProducts();
|
||||
}
|
||||
|
||||
updateCustomer(customer: Maybe<ICustomerResponse>) {
|
||||
this.store.setSelectedCustomer(customer);
|
||||
}
|
||||
|
||||
submit() {
|
||||
this.store.submitOrder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<p-card class="border border-surface-border">
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex justify-between items-center">
|
||||
<span>جمع قیمت</span>
|
||||
<span [appPriceMask]="priceInfo().totalAmount"></span>
|
||||
@if (priceInfo().totalAmount == priceInfo().totalBaseAmount) {
|
||||
<span [appPriceMask]="priceInfo().totalAmount"></span>
|
||||
} @else {
|
||||
<div class="flex flex-col items-end">
|
||||
<span class="line-through text-muted-color text-xs" [appPriceMask]="priceInfo().totalBaseAmount"></span>
|
||||
<span [appPriceMask]="priceInfo().totalAmount"></span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<div class="flex justify-between items-center">
|
||||
<span>مالیات (۱۰٪)</span>
|
||||
<span [appPriceMask]="priceInfo().taxAmount"></span>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="flex justify-between font-bold text-lg">
|
||||
<div class="flex justify-between items-center font-bold text-lg">
|
||||
<span>مجموع کل</span>
|
||||
<span [appPriceMask]="priceInfo().payableAmount"></span>
|
||||
</div>
|
||||
|
||||
@@ -4,4 +4,5 @@ export const POS_API_ROUTES = {
|
||||
info: () => `${baseUrl}`,
|
||||
stock: () => `${baseUrl}/stock`,
|
||||
productCategories: () => `${baseUrl}/product-categories`,
|
||||
submitOrder: () => `${baseUrl}/orders/create`,
|
||||
};
|
||||
|
||||
@@ -13,8 +13,8 @@ interface ICategorySummary {
|
||||
|
||||
export interface IPosOrderItem {
|
||||
productId: number;
|
||||
quantity: number;
|
||||
fee: string;
|
||||
count: number;
|
||||
fee: number;
|
||||
}
|
||||
|
||||
export interface IPosInOrderProduct extends IPosOrderItem {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { POS_API_ROUTES } from '../constants';
|
||||
import {
|
||||
IPosInfoRawResponse,
|
||||
IPosInfoResponse,
|
||||
IPosOrderRequest,
|
||||
IPosProductCategoriesRawResponse,
|
||||
IPosProductCategoriesResponse,
|
||||
IPosStockRawResponse,
|
||||
@@ -31,4 +32,8 @@ export class PosService {
|
||||
this.apiRoutes.productCategories(),
|
||||
);
|
||||
}
|
||||
|
||||
submitOrder(payload: IPosOrderRequest): Observable<any> {
|
||||
return this.http.post<any>(this.apiRoutes.submitOrder(), payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { ICustomerResponse } from '@/modules/customers/models';
|
||||
import { computed, Injectable, signal } from '@angular/core';
|
||||
import { map } from 'rxjs';
|
||||
import { IPosInfoResponse, IPosProductCategoriesResponse, IPosStockResponse } from '../models';
|
||||
@@ -14,6 +15,7 @@ interface IPosState {
|
||||
productCategories: Maybe<IPosProductCategoriesResponse[]>;
|
||||
activeProductCategory: Maybe<number>;
|
||||
inOrderProducts: IPosInOrderProduct[];
|
||||
selectedCustomer: Maybe<ICustomerResponse>;
|
||||
}
|
||||
|
||||
export const INITIAL_POS_STATE: IPosState = {
|
||||
@@ -25,6 +27,7 @@ export const INITIAL_POS_STATE: IPosState = {
|
||||
productCategories: null,
|
||||
activeProductCategory: null,
|
||||
inOrderProducts: [],
|
||||
selectedCustomer: null,
|
||||
};
|
||||
|
||||
@Injectable({ providedIn: 'any' })
|
||||
@@ -41,6 +44,7 @@ export class POSStore {
|
||||
readonly productCategories = computed(() => this.state$().productCategories);
|
||||
readonly getProductCategoriesLoading = computed(() => this.state$().getProductCategoriesLoading);
|
||||
readonly activeProductCategory = computed(() => this.state$().activeProductCategory);
|
||||
readonly selectedCustomer = computed(() => this.state$().selectedCustomer);
|
||||
readonly activatedCategoryProducts = computed(() => {
|
||||
if (this.activeProductCategory() === 0) {
|
||||
return this.state$().stock;
|
||||
@@ -52,14 +56,14 @@ export class POSStore {
|
||||
|
||||
readonly orderPricingInfo = computed(() => {
|
||||
const totalAmount = this.inOrderProducts().reduce(
|
||||
(acc, curr) => acc + parseFloat(curr.fee) * curr.quantity,
|
||||
(acc, curr) => acc + curr.fee * curr.count,
|
||||
0,
|
||||
);
|
||||
const taxAmount = totalAmount * 0.1;
|
||||
return {
|
||||
totalItems: this.inOrderProducts().reduce((acc, curr) => acc + curr.quantity, 0),
|
||||
totalItems: this.inOrderProducts().reduce((acc, curr) => acc + curr.count, 0),
|
||||
totalBaseAmount: this.inOrderProducts().reduce(
|
||||
(acc, curr) => acc + parseFloat(curr.product.salePrice) * curr.quantity,
|
||||
(acc, curr) => acc + parseFloat(curr.product.salePrice) * curr.count,
|
||||
0,
|
||||
),
|
||||
totalAmount,
|
||||
@@ -156,7 +160,7 @@ export class POSStore {
|
||||
if (this.state$().inOrderProducts.some((p) => p.productId === productId)) {
|
||||
this.updateInOrderProductQuantity(
|
||||
productId,
|
||||
this.state$().inOrderProducts.find((p) => p.productId === productId)!.quantity + 1,
|
||||
this.state$().inOrderProducts.find((p) => p.productId === productId)!.count + 1,
|
||||
);
|
||||
} else {
|
||||
this.setState({
|
||||
@@ -165,8 +169,8 @@ export class POSStore {
|
||||
{
|
||||
product,
|
||||
productId: product.id,
|
||||
quantity: 1,
|
||||
fee: product.salePrice,
|
||||
count: 1,
|
||||
fee: parseFloat(product.salePrice),
|
||||
maxQuantity: productStock.quantity,
|
||||
},
|
||||
],
|
||||
@@ -190,7 +194,7 @@ export class POSStore {
|
||||
} else {
|
||||
const updatedProducts = inOrderProducts.map((p) => {
|
||||
if (p.productId === productId) {
|
||||
return { ...p, quantity: Math.min(quantity, p.maxQuantity) };
|
||||
return { ...p, count: Math.min(quantity, p.maxQuantity) };
|
||||
}
|
||||
return p;
|
||||
});
|
||||
@@ -198,7 +202,7 @@ export class POSStore {
|
||||
}
|
||||
}
|
||||
|
||||
updateInOrderProductFee(productId: number, fee: string) {
|
||||
updateInOrderProductFee(productId: number, fee: number) {
|
||||
const inOrderProducts = this.state$().inOrderProducts;
|
||||
|
||||
if (inOrderProducts.some((p) => p.productId === productId)) {
|
||||
@@ -215,4 +219,22 @@ export class POSStore {
|
||||
resetInOrderProducts() {
|
||||
this.setState({ inOrderProducts: [] });
|
||||
}
|
||||
|
||||
setSelectedCustomer(customer: Maybe<ICustomerResponse>) {
|
||||
console.log(customer);
|
||||
|
||||
this.setState({ selectedCustomer: customer });
|
||||
}
|
||||
|
||||
submitOrder() {
|
||||
const orderPayload = {
|
||||
customerId: this.selectedCustomer()?.id,
|
||||
items: this.inOrderProducts()?.map((item) => ({
|
||||
productId: item.productId,
|
||||
count: item.count,
|
||||
fee: item.fee,
|
||||
})),
|
||||
};
|
||||
this.service.submitOrder(orderPayload).subscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
header="فرم برند کالا"
|
||||
[(visible)]="visible"
|
||||
[modal]="true"
|
||||
[style]="{ width: '500px' }"
|
||||
[style]="{ width: '500px', zIndex: '10000' }"
|
||||
[closable]="true"
|
||||
appendTo="body"
|
||||
>
|
||||
|
||||
+4
-3
@@ -28,19 +28,20 @@ export class PurchaseReceiptProductRowComponent {
|
||||
|
||||
@Output() onRemove = new EventEmitter<void>();
|
||||
|
||||
editMode = signal(false);
|
||||
editMode = signal(true);
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {
|
||||
this.purchaseItemControl?.controls.product.valueChanges.subscribe((res) => {
|
||||
this.purchaseItemControl?.controls.fee.setValue(Number(res?.salePrice) || 0);
|
||||
});
|
||||
this.purchaseItemControl?.controls.count.valueChanges.subscribe(() => {
|
||||
this.updateTotal();
|
||||
});
|
||||
this.purchaseItemControl?.controls.fee.valueChanges.subscribe(() => {
|
||||
this.updateTotal();
|
||||
});
|
||||
|
||||
console.log('purchase item control', this.purchaseItemControl);
|
||||
}
|
||||
|
||||
updateTotal() {
|
||||
|
||||
+12
-12
@@ -6,9 +6,9 @@
|
||||
<div class="grid grid-cols-2 gap-4 border-b border-surface-700 pb-4">
|
||||
<div class="grid grid-cols-1 gap-2">
|
||||
<div class="w-full flex items-center gap-2 h-10">
|
||||
<span [class]="formIsSubmitted() && form.controls.inventory.invalid ? ' text-error' : 'text-muted-color'"
|
||||
>انبار:</span
|
||||
>
|
||||
<span [class]="formIsSubmitted() && form.controls.inventory.invalid ? ' text-error' : 'text-muted-color'">
|
||||
انبار:
|
||||
</span>
|
||||
<shared-inline-edit>
|
||||
<ng-template #data>
|
||||
<span class="font-bold">{{ form.controls.inventory.value?.name || "وارد نشده" }}</span>
|
||||
@@ -24,9 +24,9 @@
|
||||
</shared-inline-edit>
|
||||
</div>
|
||||
<div class="w-full flex items-center gap-2 h-10">
|
||||
<span [class]="formIsSubmitted() && form.controls.supplier.invalid ? ' text-error' : 'text-muted-color'"
|
||||
>تامین کننده:</span
|
||||
>
|
||||
<span [class]="formIsSubmitted() && form.controls.supplier.invalid ? ' text-error' : 'text-muted-color'">
|
||||
تامین کننده:
|
||||
</span>
|
||||
<shared-inline-edit>
|
||||
<ng-template #data>
|
||||
<span class="font-bold">{{ form.controls.supplier.value?.fullname || "وارد نشده" }}</span>
|
||||
@@ -46,9 +46,9 @@
|
||||
<div class="">
|
||||
<div class="flex flex-col gap-2 max-w-xs items-end ms-auto w-full">
|
||||
<div class="w-full flex items-center gap-2 h-10">
|
||||
<span [class]="formIsSubmitted() && form.controls.code.invalid ? ' text-error' : 'text-muted-color'"
|
||||
>شماره رسید:</span
|
||||
>
|
||||
<span [class]="formIsSubmitted() && form.controls.code.invalid ? ' text-error' : 'text-muted-color'">
|
||||
شماره رسید:
|
||||
</span>
|
||||
<shared-inline-edit>
|
||||
<ng-template #data>
|
||||
<span class="font-bold">{{ form.controls.code.value || "وارد نشده" }}</span>
|
||||
@@ -59,9 +59,9 @@
|
||||
</shared-inline-edit>
|
||||
</div>
|
||||
<div class="w-full flex items-center gap-2 h-10">
|
||||
<span [class]="formIsSubmitted() && form.controls.buyAt.invalid ? ' text-error' : 'text-muted-color'"
|
||||
>تاریخ رسید:</span
|
||||
>
|
||||
<span [class]="formIsSubmitted() && form.controls.buyAt.invalid ? ' text-error' : 'text-muted-color'">
|
||||
تاریخ رسید:
|
||||
</span>
|
||||
<shared-inline-edit>
|
||||
<ng-template #data>
|
||||
<span class="font-bold">{{ form.controls.buyAt.value || "وارد نشده" }}</span>
|
||||
|
||||
+22
-16
@@ -12,6 +12,7 @@ import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, inject, Input, signal } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import dayjs from 'dayjs';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
import { Card } from 'primeng/card';
|
||||
import { TableModule } from 'primeng/table';
|
||||
@@ -91,22 +92,22 @@ export class PurchaseReceiptTemplateComponent {
|
||||
] as IColumn[];
|
||||
|
||||
form = this.fb.group({
|
||||
totalAmount: [300000, [Validators.required, Validators.min(0)]],
|
||||
code: ['122132', [Validators.required]],
|
||||
totalAmount: [0, [Validators.required, Validators.min(0)]],
|
||||
code: ['', [Validators.required]],
|
||||
isSettled: [false],
|
||||
buyAt: ['2025-12-01', Validators.required],
|
||||
buyAt: [dayjs().calendar('jalali').format('YYYY/MM/DD'), Validators.required],
|
||||
description: [''],
|
||||
products: this.fb.array([
|
||||
this.fb.group({
|
||||
product: [{ id: 1 } as Maybe<IProductResponse>, [Validators.required]],
|
||||
count: [2, [Validators.required, Validators.min(1)]],
|
||||
fee: [150000, [Validators.required, Validators.min(0)]],
|
||||
product: [null as Maybe<IProductResponse>, [Validators.required]],
|
||||
count: [0, [Validators.required, Validators.min(1)]],
|
||||
fee: [0, [Validators.required, Validators.min(0)]],
|
||||
description: [''],
|
||||
total: [300000, [Validators.required, Validators.min(0)]],
|
||||
total: [0, [Validators.required, Validators.min(0)]],
|
||||
}),
|
||||
]),
|
||||
inventory: [{ id: 2 } as Maybe<IInventorySummaryResponse>, [Validators.required]],
|
||||
supplier: [{ id: 1 } as Maybe<ISupplierResponse>, [Validators.required]],
|
||||
inventory: [null as Maybe<IInventorySummaryResponse>, [Validators.required]],
|
||||
supplier: [null as Maybe<ISupplierResponse>, [Validators.required]],
|
||||
});
|
||||
|
||||
constructor(
|
||||
@@ -114,6 +115,8 @@ export class PurchaseReceiptTemplateComponent {
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.form.controls.products.valueChanges.subscribe((products) => {
|
||||
console.log('first');
|
||||
|
||||
let totalAmount = 0;
|
||||
products.forEach((p: any) => {
|
||||
totalAmount += p.total || 0;
|
||||
@@ -126,14 +129,17 @@ export class PurchaseReceiptTemplateComponent {
|
||||
|
||||
ngOnInit() {
|
||||
this.formIsSubmitted.set(false);
|
||||
this.form.controls.products.controls.pop();
|
||||
if (this.product) {
|
||||
this.form.controls.products.at(0).setValue({
|
||||
product: this.product,
|
||||
count: 0,
|
||||
fee: 0,
|
||||
description: '',
|
||||
total: 0,
|
||||
});
|
||||
this.form.controls.products.setValue([
|
||||
{
|
||||
product: this.product,
|
||||
count: 0,
|
||||
fee: 0,
|
||||
description: '',
|
||||
total: 0,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user