feat: rename 'fee' to 'unitPrice' across purchase components and models
- Updated form component to use 'unitPrice' instead of 'fee'. - Adjusted product charge row form fields and templates to reflect the new naming. - Modified receipt template and related components to utilize 'unitPrice'. - Changed models and interfaces to replace 'fee' with 'unitPrice'. - Updated supplier invoice and statistics components to align with the new naming convention. - Added new API routes for dashboard and statistics modules.
This commit is contained in:
+3
-1
@@ -3,6 +3,7 @@ import { BANK_ACCOUNTS_ROUTES } from '@/modules/bankAccounts/constants';
|
|||||||
import { BANK_BRANCHES_ROUTES } from '@/modules/bankBranches/constants';
|
import { BANK_BRANCHES_ROUTES } from '@/modules/bankBranches/constants';
|
||||||
import { CARDEX_ROUTES } from '@/modules/cardex/constants';
|
import { CARDEX_ROUTES } from '@/modules/cardex/constants';
|
||||||
import { CUSTOMERS_ROUTES } from '@/modules/customers/constants';
|
import { CUSTOMERS_ROUTES } from '@/modules/customers/constants';
|
||||||
|
import { DASHBOARD_ROUTES } from '@/modules/dashboard/constants';
|
||||||
import { INVENTORIES_ROUTES } from '@/modules/inventories/constants';
|
import { INVENTORIES_ROUTES } from '@/modules/inventories/constants';
|
||||||
import { POSComponent } from '@/modules/pos/views/pos.component';
|
import { POSComponent } from '@/modules/pos/views/pos.component';
|
||||||
import { PRODUCT_BRANDS_ROUTES } from '@/modules/productBrands/constants';
|
import { PRODUCT_BRANDS_ROUTES } from '@/modules/productBrands/constants';
|
||||||
@@ -21,7 +22,8 @@ export const appRoutes: Routes = [
|
|||||||
path: '',
|
path: '',
|
||||||
component: AppLayout,
|
component: AppLayout,
|
||||||
children: [
|
children: [
|
||||||
{ path: '', component: Dashboard },
|
{ path: 'ng', component: Dashboard },
|
||||||
|
...DASHBOARD_ROUTES,
|
||||||
...USERS_ROUTES,
|
...USERS_ROUTES,
|
||||||
...SUPPLIERS_ROUTES,
|
...SUPPLIERS_ROUTES,
|
||||||
...PRODUCT_BRANDS_ROUTES,
|
...PRODUCT_BRANDS_ROUTES,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<app-page-data-list
|
<app-page-data-list
|
||||||
[pageTitle]="'مدیریت شعب بانک'"
|
[pageTitle]="'مدیریت حسابهای بانک'"
|
||||||
[addNewCtaLabel]="'افزودن شعبهی جدید'"
|
[addNewCtaLabel]="'افزودن حساب جدید'"
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[showAdd]="true"
|
[showAdd]="true"
|
||||||
emptyPlaceholderTitle="شعبهای یافت نشد"
|
emptyPlaceholderTitle="حسابی یافت نشد"
|
||||||
emptyPlaceholderDescription="برای افزودن شعبه جدید، روی دکمهٔ بالا کلیک کنید."
|
emptyPlaceholderDescription="برای افزودن حساب جدید، روی دکمهٔ بالا کلیک کنید."
|
||||||
[items]="items()"
|
[items]="items()"
|
||||||
[loading]="loading()"
|
[loading]="loading()"
|
||||||
[showDetails]="true"
|
[showDetails]="true"
|
||||||
|
|||||||
@@ -1 +1,8 @@
|
|||||||
<div class=""></div>
|
<app-page-data-list
|
||||||
|
[pageTitle]="'تراکنشهای حسابهای بانک'"
|
||||||
|
[columns]="columns"
|
||||||
|
emptyPlaceholderTitle="تراکنشی یافت نشد"
|
||||||
|
[items]="items()"
|
||||||
|
[loading]="loading()"
|
||||||
|
[showDetails]="true"
|
||||||
|
/>
|
||||||
|
|||||||
@@ -1,9 +1,48 @@
|
|||||||
import { Component } from '@angular/core';
|
import {
|
||||||
|
IColumn,
|
||||||
|
PageDataListComponent,
|
||||||
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
|
import { Component, signal } from '@angular/core';
|
||||||
|
import { IBankAccountsResponse } from '../models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bank-account',
|
selector: 'app-bank-account',
|
||||||
templateUrl: './single.component.html',
|
templateUrl: './single.component.html',
|
||||||
|
imports: [PageDataListComponent],
|
||||||
})
|
})
|
||||||
export class BankAccountComponent {
|
export class BankAccountComponent {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
columns = [
|
||||||
|
{ field: 'id', header: 'شناسه', width: '60px' },
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
header: 'نام',
|
||||||
|
minWidth: '100px',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'accountNumber',
|
||||||
|
header: 'شماره حساب بانکی',
|
||||||
|
canCopy: true,
|
||||||
|
minWidth: '160px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'iban',
|
||||||
|
header: 'شماره شبا',
|
||||||
|
canCopy: true,
|
||||||
|
minWidth: '200px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'cardNumber',
|
||||||
|
header: 'شماره کارت بانکی',
|
||||||
|
canCopy: true,
|
||||||
|
minWidth: '160px',
|
||||||
|
},
|
||||||
|
{ field: 'createdAt', header: 'تاریخ ایجاد', type: 'date' },
|
||||||
|
{ field: 'updatedAt', header: 'تاریخ بهروزرسانی', type: 'date' },
|
||||||
|
] as IColumn[];
|
||||||
|
|
||||||
|
loading = signal(false);
|
||||||
|
items = signal<IBankAccountsResponse[]>([]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-center!">
|
<td class="text-center!">
|
||||||
@if (item.type === "IN") {
|
@if (item.type === "IN") {
|
||||||
<span [appPriceMask]="item.fee"></span>
|
<span [appPriceMask]="item.unitPrice"></span>
|
||||||
} @else {
|
} @else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@@ -68,13 +68,13 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-center!">
|
<td class="text-center!">
|
||||||
@if (item.type === "OUT") {
|
@if (item.type === "OUT") {
|
||||||
<span [appPriceMask]="item.fee"></span>
|
<span [appPriceMask]="item.unitPrice"></span>
|
||||||
} @else {
|
} @else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center!">{{ item.remainedInStock }}</td>
|
<td class="text-center!">{{ item.remainedInStock }}</td>
|
||||||
<!-- <td class="text-center!"><span [appPriceMask]="item.fee"></span></td>
|
<!-- <td class="text-center!"><span [appPriceMask]="item.unitPrice"></span></td>
|
||||||
<td class="text-center!"><span [appPriceMask]="item.totalCost"></span></td> -->
|
<td class="text-center!"><span [appPriceMask]="item.totalCost"></span></td> -->
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ export interface ICardexRawResponse {
|
|||||||
id: number;
|
id: number;
|
||||||
type: string;
|
type: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
totalCost: number;
|
totalCost: number;
|
||||||
referenceType: string;
|
referenceType: string;
|
||||||
referenceId: string;
|
referenceId: string;
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const baseUrl = '/api/v1/pos';
|
||||||
|
|
||||||
|
export const POS_API_ROUTES = {
|
||||||
|
info: (posId: number) => `${baseUrl}/${posId}`,
|
||||||
|
stock: (posId: number) => `${baseUrl}/${posId}/stock`,
|
||||||
|
productCategories: (posId: number) => `${baseUrl}/${posId}/product-categories`,
|
||||||
|
submitOrder: (posId: number) => `${baseUrl}/${posId}/orders/create`,
|
||||||
|
};
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './apiRoutes';
|
||||||
|
export * from './routes';
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { NamedRoutes } from '@/core';
|
||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
export const dashboardNamedRoutes: NamedRoutes<any> = {
|
||||||
|
POS: {
|
||||||
|
path: '',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('../../views/dashboard.component').then((m) => m.DashboardComponent),
|
||||||
|
meta: {
|
||||||
|
title: 'داشبورد',
|
||||||
|
pagePath: () => ``,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TDashboardRouteNames = keyof typeof dashboardNamedRoutes;
|
||||||
|
|
||||||
|
export const DASHBOARD_ROUTES: Routes = Object.values(dashboardNamedRoutes);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="">
|
||||||
|
<div class="grid grid-cols-2 gap-4">
|
||||||
|
<app-statistics-shared-top-alert-stocks class="block h-[300px]" />
|
||||||
|
<app-statistics-shared-top-sales class="block h-[300px]" />
|
||||||
|
<app-statistics-shared-top-supplier-debts class="block h-[300px]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { StatisticsSharedTopAlertStocksComponent } from '@/modules/statistics/shared/components/top-alert-stocks.component';
|
||||||
|
import { StatisticsSharedTopSalesComponent } from '@/modules/statistics/shared/components/top-sales.component';
|
||||||
|
import { StatisticsSharedTopSupplierDebtsComponent } from '@/modules/statistics/shared/components/top-supplier-debts.component';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import images from 'src/assets/images';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-dashboard',
|
||||||
|
templateUrl: './dashboard.component.html',
|
||||||
|
imports: [
|
||||||
|
StatisticsSharedTopAlertStocksComponent,
|
||||||
|
StatisticsSharedTopSalesComponent,
|
||||||
|
StatisticsSharedTopSupplierDebtsComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class DashboardComponent {
|
||||||
|
placeholderLogo = images.placeholders.logo;
|
||||||
|
|
||||||
|
now = new Date();
|
||||||
|
|
||||||
|
// info = this.store.info;
|
||||||
|
// infoLoading = this.store.getInfoLoading;
|
||||||
|
|
||||||
|
// getInfo() {
|
||||||
|
// this.infoLoading.set(true);
|
||||||
|
// this.service.getInfo(Number(this.posId)).subscribe({
|
||||||
|
// next: (res) => {
|
||||||
|
// this.info.set(res);
|
||||||
|
// this.infoLoading.set(false);
|
||||||
|
// },
|
||||||
|
// error: () => {
|
||||||
|
// this.infoLoading.set(false);
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -74,10 +74,10 @@
|
|||||||
<p-sortIcon field="quantity" />
|
<p-sortIcon field="quantity" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th pSortableColumn="fee">
|
<th pSortableColumn="unitPrice">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
قیمت واحد
|
قیمت واحد
|
||||||
<p-sortIcon field="fee" />
|
<p-sortIcon field="unitPrice" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th pSortableColumn="totalCost">
|
<th pSortableColumn="totalCost">
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
<td>{{ movement.product.id }}</td>
|
<td>{{ movement.product.id }}</td>
|
||||||
<td>{{ movement.product.name }}</td>
|
<td>{{ movement.product.name }}</td>
|
||||||
<td>{{ movement.quantity }}</td>
|
<td>{{ movement.quantity }}</td>
|
||||||
<td><span [appPriceMask]="movement.fee"></span></td>
|
<td><span [appPriceMask]="movement.unitPrice"></span></td>
|
||||||
<td><span [appPriceMask]="movement.totalCost"></span></td>
|
<td><span [appPriceMask]="movement.totalCost"></span></td>
|
||||||
<td>
|
<td>
|
||||||
<p-button type="button" icon="pi pi-search" [routerLink]="'/products/' + movement.product.id" />
|
<p-button type="button" icon="pi pi-search" [routerLink]="'/products/' + movement.product.id" />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
[optionValue]="selectOptionValue"
|
[optionValue]="selectOptionValue"
|
||||||
placeholder="انتخاب انبار"
|
placeholder="انتخاب انبار"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
[showClear]="true"
|
[showClear]="showClear"
|
||||||
[filter]="true"
|
[filter]="true"
|
||||||
appendTo="body"
|
appendTo="body"
|
||||||
(onChange)="change($event.value)"
|
(onChange)="change($event.value)"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { IProductRawResponse } from '@/modules/products/models';
|
|||||||
export interface IInventoryMovement {
|
export interface IInventoryMovement {
|
||||||
id: number;
|
id: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
totalCost: number;
|
totalCost: number;
|
||||||
avgCost: number;
|
avgCost: number;
|
||||||
product: IInventoryProduct;
|
product: IInventoryProduct;
|
||||||
@@ -27,7 +27,7 @@ export interface IInventoryInfo {
|
|||||||
date: string;
|
date: string;
|
||||||
type: string;
|
type: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
totalCost: number;
|
totalCost: number;
|
||||||
referenceType: string;
|
referenceType: string;
|
||||||
referenceId: string;
|
referenceId: string;
|
||||||
|
|||||||
@@ -26,10 +26,10 @@
|
|||||||
<p-sortIcon field="quantity" />
|
<p-sortIcon field="quantity" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th pSortableColumn="fee">
|
<th pSortableColumn="unitPrice">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
قیمت متوسط
|
قیمت متوسط
|
||||||
<p-sortIcon field="fee" />
|
<p-sortIcon field="unitPrice" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th style="width: 4rem"></th>
|
<th style="width: 4rem"></th>
|
||||||
|
|||||||
@@ -80,10 +80,10 @@
|
|||||||
<p-sortIcon field="quantity" />
|
<p-sortIcon field="quantity" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th pSortableColumn="fee">
|
<th pSortableColumn="unitPrice">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
قیمت متوسط
|
قیمت متوسط
|
||||||
<p-sortIcon field="fee" />
|
<p-sortIcon field="unitPrice" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th style="width: 4rem"></th>
|
<th style="width: 4rem"></th>
|
||||||
|
|||||||
@@ -48,16 +48,17 @@
|
|||||||
<div class="flex items-center gap-4 mt-auto">
|
<div class="flex items-center gap-4 mt-auto">
|
||||||
<p-inplace>
|
<p-inplace>
|
||||||
<ng-template #display>
|
<ng-template #display>
|
||||||
<span class="font-bold text-lg shrink-0" [appPriceMask]="inOrderProduct.fee"></span>
|
<span class="font-bold text-lg shrink-0" [appPriceMask]="inOrderProduct.unitPrice"></span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #content let-closeCallback="closeCallback">
|
<ng-template #content let-closeCallback="closeCallback">
|
||||||
<p-input-number
|
<p-input-number
|
||||||
type="text"
|
type="text"
|
||||||
inputStyleClass="w-24"
|
inputStyleClass="w-24"
|
||||||
[min]="0"
|
[min]="0"
|
||||||
[(ngModel)]="inOrderProduct.fee"
|
[(ngModel)]="inOrderProduct.unitPrice"
|
||||||
(onBlur)="
|
(onBlur)="
|
||||||
updateInOrderProductFee(inOrderProduct.productId, $event, inOrderProduct.fee); closeCallback()
|
updateInOrderProductFee(inOrderProduct.productId, $event, inOrderProduct.unitPrice);
|
||||||
|
closeCallback()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ export class PosOrderCardComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateInOrderProductFee(productId: number, $event: Event, prevFee: number) {
|
updateInOrderProductFee(productId: number, $event: Event, prevFee: number) {
|
||||||
const fee = $event.target
|
const unitPrice = $event.target
|
||||||
? parseFloat(($event.target as HTMLInputElement).ariaValueNow || prevFee.toString())
|
? parseFloat(($event.target as HTMLInputElement).ariaValueNow || prevFee.toString())
|
||||||
: prevFee;
|
: prevFee;
|
||||||
|
|
||||||
this.store.updateInOrderProductFee(productId, fee);
|
this.store.updateInOrderProductFee(productId, unitPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearOrderList() {
|
clearOrderList() {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface ICategorySummary {
|
|||||||
export interface IPosOrderItem {
|
export interface IPosOrderItem {
|
||||||
productId: number;
|
productId: number;
|
||||||
count: number;
|
count: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPosInOrderProduct extends IPosOrderItem {
|
export interface IPosInOrderProduct extends IPosOrderItem {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export class POSStore {
|
|||||||
|
|
||||||
readonly orderPricingInfo = computed(() => {
|
readonly orderPricingInfo = computed(() => {
|
||||||
const totalAmount = this.inOrderProducts().reduce(
|
const totalAmount = this.inOrderProducts().reduce(
|
||||||
(acc, curr) => acc + curr.fee * curr.count,
|
(acc, curr) => acc + curr.unitPrice * curr.count,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
const taxAmount = totalAmount * 0.1;
|
const taxAmount = totalAmount * 0.1;
|
||||||
@@ -188,7 +188,7 @@ export class POSStore {
|
|||||||
product,
|
product,
|
||||||
productId: product.id,
|
productId: product.id,
|
||||||
count: 1,
|
count: 1,
|
||||||
fee: parseFloat(product.salePrice),
|
unitPrice: parseFloat(product.salePrice),
|
||||||
maxQuantity: productStock.quantity,
|
maxQuantity: productStock.quantity,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -220,13 +220,13 @@ export class POSStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInOrderProductFee(productId: number, fee: number) {
|
updateInOrderProductFee(productId: number, unitPrice: number) {
|
||||||
const inOrderProducts = this.state$().inOrderProducts;
|
const inOrderProducts = this.state$().inOrderProducts;
|
||||||
|
|
||||||
if (inOrderProducts.some((p) => p.productId === productId)) {
|
if (inOrderProducts.some((p) => p.productId === productId)) {
|
||||||
const updatedProducts = inOrderProducts.map((p) => {
|
const updatedProducts = inOrderProducts.map((p) => {
|
||||||
if (p.productId === productId) {
|
if (p.productId === productId) {
|
||||||
return { ...p, fee: fee };
|
return { ...p, unitPrice: unitPrice };
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
});
|
});
|
||||||
@@ -255,7 +255,7 @@ export class POSStore {
|
|||||||
items: this.inOrderProducts()?.map((item) => ({
|
items: this.inOrderProducts()?.map((item) => ({
|
||||||
productId: item.productId,
|
productId: item.productId,
|
||||||
count: item.count,
|
count: item.count,
|
||||||
fee: item.fee,
|
unitPrice: item.unitPrice,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
this.service.submitOrder(this.posId, orderPayload).subscribe();
|
this.service.submitOrder(this.posId, orderPayload).subscribe();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<suppliers-select-field [control]="form.controls.supplierId" />
|
<suppliers-select-field [control]="form.controls.supplierId" />
|
||||||
<app-input label="تعداد" [control]="form.controls.count" />
|
<app-input label="تعداد" [control]="form.controls.count" />
|
||||||
|
|
||||||
<app-input label="قیمت اولیه" [control]="form.controls.fee" />
|
<app-input label="قیمت اولیه" [control]="form.controls.unitPrice" />
|
||||||
|
|
||||||
<app-input label="مبلغ کل" [control]="form.controls.totalAmount" />
|
<app-input label="مبلغ کل" [control]="form.controls.totalAmount" />
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class ProductChargeFormComponent {
|
|||||||
|
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
count: [0, [Validators.required, Validators.min(1)]],
|
count: [0, [Validators.required, Validators.min(1)]],
|
||||||
fee: [0, [Validators.required, Validators.min(0)]],
|
unitPrice: [0, [Validators.required, Validators.min(0)]],
|
||||||
totalAmount: [0, [Validators.required, Validators.min(0)]],
|
totalAmount: [0, [Validators.required, Validators.min(0)]],
|
||||||
isSettled: [false],
|
isSettled: [false],
|
||||||
buyAt: ['', Validators.required],
|
buyAt: ['', Validators.required],
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ export interface IProductChargeRaw {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
count: number;
|
count: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
totalAmount: number;
|
totalAmount: number;
|
||||||
isSettled?: boolean;
|
isSettled?: boolean;
|
||||||
buyAt: string;
|
buyAt: string;
|
||||||
@@ -20,7 +20,7 @@ export interface IProductChargeResponse extends IProductChargeRaw {}
|
|||||||
export interface IProductChargeRequest {
|
export interface IProductChargeRequest {
|
||||||
name: string;
|
name: string;
|
||||||
count: number;
|
count: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
totalAmount: number;
|
totalAmount: number;
|
||||||
isSettled?: boolean;
|
isSettled?: boolean;
|
||||||
buyAt: string;
|
buyAt: string;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export class ProductChargesComponent {
|
|||||||
{ field: 'id', header: 'شناسه' },
|
{ field: 'id', header: 'شناسه' },
|
||||||
{ field: 'name', header: 'نام' },
|
{ field: 'name', header: 'نام' },
|
||||||
{ field: 'count', header: 'تعداد' },
|
{ field: 'count', header: 'تعداد' },
|
||||||
{ field: 'fee', header: 'هزینه' },
|
{ field: 'unitPrice', header: 'هزینه' },
|
||||||
{ field: 'totalAmount', header: 'مبلغ کل' },
|
{ field: 'totalAmount', header: 'مبلغ کل' },
|
||||||
{ field: 'isSettled', header: 'تسویه شده' },
|
{ field: 'isSettled', header: 'تسویه شده' },
|
||||||
{ field: 'buyAt', header: 'تاریخ خرید' },
|
{ field: 'buyAt', header: 'تاریخ خرید' },
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export class PurchaseFormComponent {
|
|||||||
this.fb.group({
|
this.fb.group({
|
||||||
productId: [this.product?.id || 0, [Validators.required]],
|
productId: [this.product?.id || 0, [Validators.required]],
|
||||||
count: [0, [Validators.required, Validators.min(1)]],
|
count: [0, [Validators.required, Validators.min(1)]],
|
||||||
fee: [0, [Validators.required, Validators.min(0)]],
|
unitPrice: [0, [Validators.required, Validators.min(0)]],
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
inventoryId: [this.inventory?.id || 0, [Validators.required]],
|
inventoryId: [this.inventory?.id || 0, [Validators.required]],
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
<products-select-field [control]="productIdControl" />
|
<products-select-field [control]="productIdControl" />
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<app-input label="تعداد" [control]="countControl" name="count" />
|
<app-input label="تعداد" [control]="countControl" name="count" />
|
||||||
<app-input label="قیمت" [control]="feeControl" name="fee" />
|
<app-input label="قیمت" [control]="feeControl" name="unitPrice" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<product-charge-row-form-fields
|
<product-charge-row-form-fields
|
||||||
[productIdControl]="$any(product.get('productId'))"
|
[productIdControl]="$any(product.get('productId'))"
|
||||||
[countControl]="$any(product.get('count'))"
|
[countControl]="$any(product.get('count'))"
|
||||||
[feeControl]="$any(product.get('fee'))"
|
[feeControl]="$any(product.get('unitPrice'))"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class ProductChargeRowFormComponent implements OnInit {
|
|||||||
FormGroup<{
|
FormGroup<{
|
||||||
productId: FormControl<Maybe<number>>;
|
productId: FormControl<Maybe<number>>;
|
||||||
count: FormControl<Maybe<number>>;
|
count: FormControl<Maybe<number>>;
|
||||||
fee: FormControl<Maybe<number>>;
|
unitPrice: FormControl<Maybe<number>>;
|
||||||
}>
|
}>
|
||||||
>;
|
>;
|
||||||
@Input() isSingleProduct = false;
|
@Input() isSingleProduct = false;
|
||||||
@@ -43,7 +43,7 @@ export class ProductChargeRowFormComponent implements OnInit {
|
|||||||
const productFormGroup = this.fb.group({
|
const productFormGroup = this.fb.group({
|
||||||
productId: [0, [Validators.required]],
|
productId: [0, [Validators.required]],
|
||||||
count: [1, [Validators.required, Validators.min(1)]],
|
count: [1, [Validators.required, Validators.min(1)]],
|
||||||
fee: [0, [Validators.required, Validators.min(0)]],
|
unitPrice: [0, [Validators.required, Validators.min(0)]],
|
||||||
});
|
});
|
||||||
this.productsControl.push(productFormGroup);
|
this.productsControl.push(productFormGroup);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -28,27 +28,27 @@
|
|||||||
[autoResize]="false"
|
[autoResize]="false"
|
||||||
></textarea>
|
></textarea>
|
||||||
</td>
|
</td>
|
||||||
<td><app-input [control]="purchaseItemControl.controls.fee" [showErrors]="false" /></td>
|
<td><app-input [control]="purchaseItemControl.controls.unitPrice" [showErrors]="false" type="price" /></td>
|
||||||
<td><app-input [control]="purchaseItemControl.controls.count" /></td>
|
<td><app-input [control]="purchaseItemControl.controls.count" /></td>
|
||||||
<td><span [appPriceMask]="purchaseItemControl.controls.total.value || 0"></span></td>
|
<td><span [appPriceMask]="purchaseItemControl.controls.total.value || 0"></span></td>
|
||||||
<td>
|
<!-- <td>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<button pButton type="button" icon="pi pi-check" text size="small" (click)="toggleEditMode()"></button>
|
<button pButton type="button" icon="pi pi-check" text size="small" (click)="toggleEditMode()"></button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td> -->
|
||||||
} @else {
|
} @else {
|
||||||
<td>{{ purchaseItemControl.controls.product.value?.sku || "" }}</td>
|
<td>{{ purchaseItemControl.controls.product.value?.sku || "" }}</td>
|
||||||
<td>{{ purchaseItemControl.controls.product.value?.name || "" }}</td>
|
<td>{{ purchaseItemControl.controls.product.value?.name || "" }}</td>
|
||||||
<td>{{ purchaseItemControl.controls.description.value || "" }}</td>
|
<td>{{ purchaseItemControl.controls.description.value || "" }}</td>
|
||||||
<td><span [appPriceMask]="purchaseItemControl.controls.fee.value || 0"></span></td>
|
<td><span [appPriceMask]="purchaseItemControl.controls.unitPrice.value || 0"></span></td>
|
||||||
<td>{{ purchaseItemControl.controls.count.value }}</td>
|
<td>{{ purchaseItemControl.controls.count.value }}</td>
|
||||||
<td><span [appPriceMask]="purchaseItemControl.controls.total.value || 0"></span></td>
|
<td><span [appPriceMask]="purchaseItemControl.controls.total.value || 0"></span></td>
|
||||||
<td>
|
<!-- <td>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<button pButton type="button" icon="pi pi-pencil" text size="small" (click)="toggleEditMode()"></button>
|
<button pButton type="button" icon="pi pi-pencil" text size="small" (click)="toggleEditMode()"></button>
|
||||||
@if (canRemove) {
|
@if (canRemove) {
|
||||||
<button pButton type="button" icon="pi pi-trash" text size="small" (click)="onDeleteClick()"></button>
|
<button pButton type="button" icon="pi pi-trash" text size="small" (click)="onDeleteClick()"></button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td> -->
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -34,12 +34,12 @@ export class PurchaseReceiptProductRowComponent {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.purchaseItemControl?.controls.product.valueChanges.subscribe((res) => {
|
this.purchaseItemControl?.controls.product.valueChanges.subscribe((res) => {
|
||||||
this.purchaseItemControl?.controls.fee.setValue(Number(res?.salePrice) || 0);
|
this.purchaseItemControl?.controls.unitPrice.setValue(Number(res?.salePrice) || 0);
|
||||||
});
|
});
|
||||||
this.purchaseItemControl?.controls.count.valueChanges.subscribe(() => {
|
this.purchaseItemControl?.controls.count.valueChanges.subscribe(() => {
|
||||||
this.updateTotal();
|
this.updateTotal();
|
||||||
});
|
});
|
||||||
this.purchaseItemControl?.controls.fee.valueChanges.subscribe(() => {
|
this.purchaseItemControl?.controls.unitPrice.valueChanges.subscribe(() => {
|
||||||
this.updateTotal();
|
this.updateTotal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ export class PurchaseReceiptProductRowComponent {
|
|||||||
updateTotal() {
|
updateTotal() {
|
||||||
this.purchaseItemControl.controls.total.setValue(
|
this.purchaseItemControl.controls.total.setValue(
|
||||||
(this.purchaseItemControl.controls.count.value || 0) *
|
(this.purchaseItemControl.controls.count.value || 0) *
|
||||||
(this.purchaseItemControl.controls.fee.value || 0),
|
(this.purchaseItemControl.controls.unitPrice.value || 0),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+45
-27
@@ -9,38 +9,47 @@
|
|||||||
<span [class]="formIsSubmitted() && form.controls.inventory.invalid ? ' text-error' : 'text-muted-color'">
|
<span [class]="formIsSubmitted() && form.controls.inventory.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
انبار:
|
انبار:
|
||||||
</span>
|
</span>
|
||||||
<shared-inline-edit>
|
<p-inplace [disabled]="!!inventory">
|
||||||
<ng-template #data>
|
<ng-template #display>
|
||||||
<span class="font-bold">{{ form.controls.inventory.value?.name || "وارد نشده" }}</span>
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-bold">{{ form.controls.inventory.value?.name || "وارد نشده" }}</span>
|
||||||
|
@if (!inventory) {
|
||||||
|
<i class="pi pi-pencil text-sm text-muted-color cursor-pointer"></i>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #field>
|
<ng-template #content let-closeCallback="closeCallback">
|
||||||
<inventories-select-field
|
<inventories-select-field
|
||||||
[control]="form.controls.inventory"
|
[control]="form.controls.inventory"
|
||||||
[isFullDataOptionValue]="true"
|
[isFullDataOptionValue]="true"
|
||||||
[showErrors]="false"
|
[showErrors]="false"
|
||||||
[showLabel]="false"
|
[showLabel]="false"
|
||||||
|
[showClear]="false"
|
||||||
/>
|
/>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</shared-inline-edit>
|
</p-inplace>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2 h-10">
|
<div class="w-full flex items-center gap-2 h-10">
|
||||||
<span [class]="formIsSubmitted() && form.controls.supplier.invalid ? ' text-error' : 'text-muted-color'">
|
<span [class]="formIsSubmitted() && form.controls.supplier.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
تامین کننده:
|
تامین کننده:
|
||||||
</span>
|
</span>
|
||||||
<shared-inline-edit>
|
<p-inplace>
|
||||||
<ng-template #data>
|
<ng-template #display>
|
||||||
<span class="font-bold">{{ form.controls.supplier.value?.fullname || "وارد نشده" }}</span>
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-bold">{{ form.controls.supplier.value?.fullname || "وارد نشده" }}</span>
|
||||||
|
<i class="pi pi-pencil text-sm text-muted-color cursor-pointer"></i>
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
<ng-template #content let-closeCallback="closeCallback">
|
||||||
<ng-template #field>
|
|
||||||
<suppliers-select-field
|
<suppliers-select-field
|
||||||
[control]="form.controls.supplier"
|
[control]="form.controls.supplier"
|
||||||
[isFullDataOptionValue]="true"
|
[isFullDataOptionValue]="true"
|
||||||
[showErrors]="false"
|
[showErrors]="false"
|
||||||
[showLabel]="false"
|
[showLabel]="false"
|
||||||
|
[showClear]="false"
|
||||||
/>
|
/>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</shared-inline-edit>
|
</p-inplace>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="">
|
||||||
@@ -49,27 +58,33 @@
|
|||||||
<span [class]="formIsSubmitted() && form.controls.code.invalid ? ' text-error' : 'text-muted-color'">
|
<span [class]="formIsSubmitted() && form.controls.code.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
شماره رسید:
|
شماره رسید:
|
||||||
</span>
|
</span>
|
||||||
<shared-inline-edit>
|
<p-inplace>
|
||||||
<ng-template #data>
|
<ng-template #display>
|
||||||
<span class="font-bold">{{ form.controls.code.value || "وارد نشده" }}</span>
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-bold">{{ form.controls.code.value || "وارد نشده" }}</span>
|
||||||
|
<i class="pi pi-pencil text-sm text-muted-color cursor-pointer"></i>
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #field>
|
<ng-template #content let-closeCallback="closeCallback">
|
||||||
<app-input [control]="form.controls.code" [showErrors]="false" />
|
<app-input [control]="form.controls.code" [showErrors]="false" (onBlur)="closeCallback()" />
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</shared-inline-edit>
|
</p-inplace>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2 h-10">
|
<div class="w-full flex items-center gap-2 h-10">
|
||||||
<span [class]="formIsSubmitted() && form.controls.buyAt.invalid ? ' text-error' : 'text-muted-color'">
|
<span [class]="formIsSubmitted() && form.controls.buyAt.invalid ? ' text-error' : 'text-muted-color'">
|
||||||
تاریخ خرید:
|
تاریخ خرید:
|
||||||
</span>
|
</span>
|
||||||
<shared-inline-edit>
|
<p-inplace>
|
||||||
<ng-template #data>
|
<ng-template #display>
|
||||||
<span class="font-bold">{{ form.controls.buyAt.value || "وارد نشده" }}</span>
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-bold">{{ form.controls.buyAt.value || "وارد نشده" }}</span>
|
||||||
|
<i class="pi pi-pencil text-sm text-muted-color cursor-pointer"></i>
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #field>
|
<ng-template #content let-closeCallback="closeCallback">
|
||||||
<uikit-datepicker [control]="form.controls.buyAt" [showErrors]="false" [showLabel]="false" />
|
<uikit-datepicker [control]="form.controls.buyAt" [showErrors]="false" [showLabel]="false" />
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</shared-inline-edit>
|
</p-inplace>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -116,7 +131,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</shared-inline-edit>
|
</shared-inline-edit>
|
||||||
} @else if (col.field === "total") {
|
} @else if (col.field === "total") {
|
||||||
{{ product["fee"] * product["count"] || 0 }}
|
{{ product["unitPrice"] * product["count"] || 0 }}
|
||||||
} @else if (col.field === "action") {
|
} @else if (col.field === "action") {
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button></button>
|
<button></button>
|
||||||
@@ -130,7 +145,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #footer>
|
<ng-template #footer>
|
||||||
<tr>
|
<tr>
|
||||||
<td [attr.colspan]="8" class="p-0!">
|
<td [attr.colspan]="7" class="p-0!">
|
||||||
<div class="flex justify-center p-3">
|
<div class="flex justify-center p-3">
|
||||||
<button
|
<button
|
||||||
pButton
|
pButton
|
||||||
@@ -143,7 +158,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td [attr.colspan]="6" class="border-e border-surface-700"></td>
|
<td [attr.colspan]="5" class="border-e border-surface-700"></td>
|
||||||
<td [attr.colspan]="2" class="p-0!">
|
<td [attr.colspan]="2" class="p-0!">
|
||||||
<div class="flex flex-col gap-4 w-full border-s border-surface-700 px-3 py-6">
|
<div class="flex flex-col gap-4 w-full border-s border-surface-700 px-3 py-6">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
@@ -158,7 +173,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td [attr.colspan]="6" class="p-0! border-none!">
|
<td [attr.colspan]="5" class="p-0! border-none!">
|
||||||
<div class="w-full flex items-center gap-2 py-10 border-surface-700 border-t-4">
|
<div class="w-full flex items-center gap-2 py-10 border-surface-700 border-t-4">
|
||||||
<span>مبلغ قابل پرداخت:</span>
|
<span>مبلغ قابل پرداخت:</span>
|
||||||
<span [appPriceAlphabet]="totalAmount + totalAmount * 0.1" class="font-bold text-lg"></span>
|
<span [appPriceAlphabet]="totalAmount + totalAmount * 0.1" class="font-bold text-lg"></span>
|
||||||
@@ -180,6 +195,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (purchaseReceiptResponse()) {
|
@if (purchaseReceiptResponse()) {
|
||||||
<app-purchase-receipt-payment-wrapper [purchaseReceipt]="purchaseReceiptResponse()!" />
|
<app-purchase-receipt-payment-wrapper
|
||||||
|
[purchaseReceipt]="purchaseReceiptResponse()!"
|
||||||
|
(onSubmit)="paymentSubmitted()"
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+22
-13
@@ -5,7 +5,7 @@ import { IInventorySummaryResponse } from '@/modules/inventories/models';
|
|||||||
import { IProductResponse } from '@/modules/products/models';
|
import { IProductResponse } from '@/modules/products/models';
|
||||||
import { SuppliersSelectComponent } from '@/modules/suppliers/components/select/select.component';
|
import { SuppliersSelectComponent } from '@/modules/suppliers/components/select/select.component';
|
||||||
import { ISupplierResponse } from '@/modules/suppliers/models';
|
import { ISupplierResponse } from '@/modules/suppliers/models';
|
||||||
import { InlineEditComponent, InputComponent } from '@/shared/components';
|
import { InputComponent } from '@/shared/components';
|
||||||
import { IColumn } from '@/shared/components/pageDataList/page-data-list.component';
|
import { IColumn } from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
import { PurchaseReceiptPaymentWrapperComponent } from '@/shared/components/purchaseReceiptPayment/wrapper.component';
|
import { PurchaseReceiptPaymentWrapperComponent } from '@/shared/components/purchaseReceiptPayment/wrapper.component';
|
||||||
import { PriceAlphabetDirective, PriceMaskDirective } from '@/shared/directives';
|
import { PriceAlphabetDirective, PriceMaskDirective } from '@/shared/directives';
|
||||||
@@ -16,6 +16,7 @@ import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Card } from 'primeng/card';
|
import { Card } from 'primeng/card';
|
||||||
|
import { Inplace } from 'primeng/inplace';
|
||||||
import { TableModule } from 'primeng/table';
|
import { TableModule } from 'primeng/table';
|
||||||
import { IPurchaseReceiptResponse, IPurchaseRequest } from '../../models';
|
import { IPurchaseReceiptResponse, IPurchaseRequest } from '../../models';
|
||||||
import { PurchasesService } from '../../services/main.service';
|
import { PurchasesService } from '../../services/main.service';
|
||||||
@@ -32,7 +33,6 @@ import { PurchaseReceiptProductRowComponent } from './purchase-receipt-product-r
|
|||||||
SuppliersSelectComponent,
|
SuppliersSelectComponent,
|
||||||
InputComponent,
|
InputComponent,
|
||||||
TableModule,
|
TableModule,
|
||||||
InlineEditComponent,
|
|
||||||
PurchaseReceiptProductRowComponent,
|
PurchaseReceiptProductRowComponent,
|
||||||
PriceAlphabetDirective,
|
PriceAlphabetDirective,
|
||||||
PriceMaskDirective,
|
PriceMaskDirective,
|
||||||
@@ -41,6 +41,7 @@ import { PurchaseReceiptProductRowComponent } from './purchase-receipt-product-r
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
UikitFlatpickrJalaliComponent,
|
UikitFlatpickrJalaliComponent,
|
||||||
PurchaseReceiptPaymentWrapperComponent,
|
PurchaseReceiptPaymentWrapperComponent,
|
||||||
|
Inplace,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PurchaseReceiptTemplateComponent {
|
export class PurchaseReceiptTemplateComponent {
|
||||||
@@ -65,6 +66,7 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
field: 'name',
|
field: 'name',
|
||||||
header: 'نام کالا',
|
header: 'نام کالا',
|
||||||
minWidth: '160px',
|
minWidth: '160px',
|
||||||
|
width: '160px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'description',
|
field: 'description',
|
||||||
@@ -72,9 +74,9 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
width: '200px',
|
width: '200px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'fee',
|
field: 'unitPrice',
|
||||||
header: 'قیمت واحد',
|
header: 'قیمت واحد',
|
||||||
width: '120px',
|
width: '200px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'count',
|
field: 'count',
|
||||||
@@ -82,15 +84,16 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
width: '80px',
|
width: '80px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'total',
|
field: 'totalPrice',
|
||||||
header: 'مبلغ کل',
|
header: 'مبلغ کل',
|
||||||
|
type: 'price',
|
||||||
width: '140px',
|
width: '140px',
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
field: 'action',
|
// field: 'action',
|
||||||
header: '',
|
// header: '',
|
||||||
width: '100px',
|
// width: '100px',
|
||||||
},
|
// },
|
||||||
] as IColumn[];
|
] as IColumn[];
|
||||||
|
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
@@ -104,7 +107,7 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
this.fb.group({
|
this.fb.group({
|
||||||
product: [null as Maybe<IProductResponse>, [Validators.required]],
|
product: [null as Maybe<IProductResponse>, [Validators.required]],
|
||||||
count: [0, [Validators.required, Validators.min(1)]],
|
count: [0, [Validators.required, Validators.min(1)]],
|
||||||
fee: [0, [Validators.required, Validators.min(0)]],
|
unitPrice: [0, [Validators.required, Validators.min(0)]],
|
||||||
description: [''],
|
description: [''],
|
||||||
total: [0, [Validators.required, Validators.min(0)]],
|
total: [0, [Validators.required, Validators.min(0)]],
|
||||||
}),
|
}),
|
||||||
@@ -154,7 +157,7 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
{
|
{
|
||||||
product: this.product,
|
product: this.product,
|
||||||
count: 0,
|
count: 0,
|
||||||
fee: 0,
|
unitPrice: 0,
|
||||||
description: '',
|
description: '',
|
||||||
total: 0,
|
total: 0,
|
||||||
},
|
},
|
||||||
@@ -171,7 +174,7 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
this.fb.group({
|
this.fb.group({
|
||||||
product: [null as Maybe<IProductResponse>, [Validators.required]],
|
product: [null as Maybe<IProductResponse>, [Validators.required]],
|
||||||
count: [0, [Validators.required, Validators.min(1)]],
|
count: [0, [Validators.required, Validators.min(1)]],
|
||||||
fee: [0, [Validators.required, Validators.min(0)]],
|
unitPrice: [0, [Validators.required, Validators.min(0)]],
|
||||||
description: [''],
|
description: [''],
|
||||||
total: [0, [Validators.required, Validators.min(0)]],
|
total: [0, [Validators.required, Validators.min(0)]],
|
||||||
}),
|
}),
|
||||||
@@ -218,4 +221,10 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onCancel() {}
|
onCancel() {}
|
||||||
|
|
||||||
|
paymentSubmitted() {
|
||||||
|
this.purchaseReceiptResponse.set(null);
|
||||||
|
this.form.reset();
|
||||||
|
this.formIsSubmitted.set(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export * from './io';
|
|||||||
export interface IPurchaseItemFormGroup extends FormGroup<{
|
export interface IPurchaseItemFormGroup extends FormGroup<{
|
||||||
product: FormControl<IProductResponse | null>;
|
product: FormControl<IProductResponse | null>;
|
||||||
count: FormControl<number>;
|
count: FormControl<number>;
|
||||||
fee: FormControl<number>;
|
unitPrice: FormControl<number>;
|
||||||
description: FormControl<string>;
|
description: FormControl<string>;
|
||||||
total: FormControl<number>;
|
total: FormControl<number>;
|
||||||
}> {}
|
}> {}
|
||||||
|
|||||||
+3
-3
@@ -17,7 +17,7 @@ export interface IPurchaseReceiptResponse extends IPurchaseReceiptRawResponse {}
|
|||||||
export interface IPurchaseItemRawResponse {
|
export interface IPurchaseItemRawResponse {
|
||||||
id: number;
|
id: number;
|
||||||
count: number;
|
count: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
total: number;
|
total: number;
|
||||||
productId: number;
|
productId: number;
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ export interface IPurchaseRequest {
|
|||||||
export interface IPurchaseItemRequest {
|
export interface IPurchaseItemRequest {
|
||||||
productId: number;
|
productId: number;
|
||||||
count: number;
|
count: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ export interface IPurchaseForm {
|
|||||||
export interface IPurchaseItemForm {
|
export interface IPurchaseItemForm {
|
||||||
product: Maybe<IProductResponse>;
|
product: Maybe<IProductResponse>;
|
||||||
count: number;
|
count: number;
|
||||||
fee: number;
|
unitPrice: number;
|
||||||
total: number;
|
total: number;
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const baseUrl = '/api/v1/pos';
|
||||||
|
|
||||||
|
export const POS_API_ROUTES = {
|
||||||
|
info: (posId: number) => `${baseUrl}/${posId}`,
|
||||||
|
stock: (posId: number) => `${baseUrl}/${posId}/stock`,
|
||||||
|
productCategories: (posId: number) => `${baseUrl}/${posId}/product-categories`,
|
||||||
|
submitOrder: (posId: number) => `${baseUrl}/${posId}/orders/create`,
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './apiRoutes';
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="card p-0! h-full!">
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-2 justify-between p-4 border-b border-surface-border bg-surface-card sticky top-0 z-10"
|
||||||
|
>
|
||||||
|
<span class="text-lg font-bold">{{ title }}</span>
|
||||||
|
<button pButton icon="pi pi-refresh" outlined (click)="onRefresh.emit()" [loading]="loading"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-4 h-full overflow-auto"><ng-content></ng-content></div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { ButtonDirective } from 'primeng/button';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-statistics-shared-card',
|
||||||
|
templateUrl: './card.component.html',
|
||||||
|
imports: [ButtonDirective],
|
||||||
|
host: {
|
||||||
|
class: 'block h-full overflow-auto',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export class StatisticsSharedCardComponent {
|
||||||
|
@Input() title!: string;
|
||||||
|
@Input() loading: boolean = false;
|
||||||
|
@Output() onRefresh = new EventEmitter<void>();
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<app-statistics-shared-card title="لیست کالاهای رو به اتمام" [loading]="loading()" (onRefresh)="getData()">
|
||||||
|
<app-page-data-list
|
||||||
|
[columns]="column"
|
||||||
|
[items]="items()"
|
||||||
|
[loading]="loading()"
|
||||||
|
emptyPlaceholderDescription="در حال حاضر تمامی کالاها به مقدار کافی وجود دارند"
|
||||||
|
>
|
||||||
|
<ng-template #actionTpl let-item>
|
||||||
|
<button pButton icon="pi pi-cart-plus" outlined [routerLink]="['/products', item.id, 'purchase']"></button>
|
||||||
|
</ng-template>
|
||||||
|
</app-page-data-list>
|
||||||
|
</app-statistics-shared-card>
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import {
|
||||||
|
IColumn,
|
||||||
|
PageDataListComponent,
|
||||||
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
|
import { Component, signal, TemplateRef, ViewChild } from '@angular/core';
|
||||||
|
import { RouterLink } from '@angular/router';
|
||||||
|
import { ButtonDirective } from 'primeng/button';
|
||||||
|
import { IStatisticsTopAlertStockResponse } from '../models/io';
|
||||||
|
import { SharedStatisticsService } from '../services/main.service';
|
||||||
|
import { StatisticsSharedCardComponent } from './card.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-statistics-shared-top-alert-stocks',
|
||||||
|
templateUrl: './top-alert-stocks.component.html',
|
||||||
|
imports: [StatisticsSharedCardComponent, PageDataListComponent, ButtonDirective, RouterLink],
|
||||||
|
})
|
||||||
|
export class StatisticsSharedTopAlertStocksComponent {
|
||||||
|
items = signal<IStatisticsTopAlertStockResponse[]>([]);
|
||||||
|
loading = signal<boolean>(false);
|
||||||
|
column = [] as IColumn[];
|
||||||
|
@ViewChild('actionTpl', { static: true }) actionTpl!: TemplateRef<any>;
|
||||||
|
|
||||||
|
constructor(private readonly service: SharedStatisticsService) {
|
||||||
|
this.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.column = [
|
||||||
|
{ field: 'sku', header: 'شناسه' },
|
||||||
|
{ field: 'name', header: 'عنوان' },
|
||||||
|
{
|
||||||
|
field: 'brand',
|
||||||
|
header: 'برند',
|
||||||
|
type: 'nested',
|
||||||
|
nestedPath: 'name',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'stock',
|
||||||
|
header: 'موجودی ',
|
||||||
|
},
|
||||||
|
{ field: 'minimumStockAlertLevel', header: 'حد هشدار' },
|
||||||
|
{
|
||||||
|
field: 'chargeAction',
|
||||||
|
header: '',
|
||||||
|
customDataModel: this.actionTpl,
|
||||||
|
width: '40px',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.loading.set(true);
|
||||||
|
this.service.getTopAlertStock().subscribe({
|
||||||
|
next: (res) => {
|
||||||
|
this.items.set(res.data);
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toPurchase(item: IStatisticsTopAlertStockResponse) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<app-statistics-shared-card title="لیست پرفروشترین کالاها" [loading]="loading()" (onRefresh)="getData()">
|
||||||
|
<app-page-data-list
|
||||||
|
[columns]="column"
|
||||||
|
[items]="items()"
|
||||||
|
[loading]="loading()"
|
||||||
|
emptyPlaceholderDescription="در حال حاضر فروشی انجام نشده است."
|
||||||
|
>
|
||||||
|
</app-page-data-list>
|
||||||
|
</app-statistics-shared-card>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import {
|
||||||
|
IColumn,
|
||||||
|
PageDataListComponent,
|
||||||
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
|
import { Component, signal, TemplateRef, ViewChild } from '@angular/core';
|
||||||
|
import { RouterLink } from '@angular/router';
|
||||||
|
import { ButtonDirective } from 'primeng/button';
|
||||||
|
import { IStatisticsTopSalesResponse } from '../models/io';
|
||||||
|
import { SharedStatisticsService } from '../services/main.service';
|
||||||
|
import { StatisticsSharedCardComponent } from './card.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-statistics-shared-top-sales',
|
||||||
|
templateUrl: './top-sales.component.html',
|
||||||
|
imports: [StatisticsSharedCardComponent, PageDataListComponent, ButtonDirective, RouterLink],
|
||||||
|
})
|
||||||
|
export class StatisticsSharedTopSalesComponent {
|
||||||
|
items = signal<IStatisticsTopSalesResponse[]>([]);
|
||||||
|
loading = signal<boolean>(false);
|
||||||
|
column = [] as IColumn[];
|
||||||
|
@ViewChild('actionTpl', { static: true }) actionTpl!: TemplateRef<any>;
|
||||||
|
|
||||||
|
constructor(private readonly service: SharedStatisticsService) {
|
||||||
|
this.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.column = [
|
||||||
|
{ field: 'sku', header: 'شناسه' },
|
||||||
|
{ field: 'name', header: 'عنوان' },
|
||||||
|
{
|
||||||
|
field: 'brand',
|
||||||
|
header: 'برند',
|
||||||
|
type: 'nested',
|
||||||
|
nestedPath: 'name',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.loading.set(true);
|
||||||
|
this.service.getTopSales().subscribe({
|
||||||
|
next: (res) => {
|
||||||
|
this.items.set(res.data);
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<app-statistics-shared-card title="لیست بدهی به تامینکنندگان" [loading]="loading()" (onRefresh)="getData()">
|
||||||
|
<app-page-data-list
|
||||||
|
[columns]="column"
|
||||||
|
[items]="items()"
|
||||||
|
[loading]="loading()"
|
||||||
|
emptyPlaceholderDescription="در حال حاضر بدهی به تامینکنندگان ندارید."
|
||||||
|
>
|
||||||
|
</app-page-data-list>
|
||||||
|
</app-statistics-shared-card>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import {
|
||||||
|
IColumn,
|
||||||
|
PageDataListComponent,
|
||||||
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
|
import { Component, signal, TemplateRef, ViewChild } from '@angular/core';
|
||||||
|
import { IStatisticsTopSupplierDebtsResponse } from '../models/io';
|
||||||
|
import { SharedStatisticsService } from '../services/main.service';
|
||||||
|
import { StatisticsSharedCardComponent } from './card.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-statistics-shared-top-supplier-debts',
|
||||||
|
templateUrl: './top-supplier-debts.component.html',
|
||||||
|
imports: [StatisticsSharedCardComponent, PageDataListComponent],
|
||||||
|
})
|
||||||
|
export class StatisticsSharedTopSupplierDebtsComponent {
|
||||||
|
items = signal<IStatisticsTopSupplierDebtsResponse[]>([]);
|
||||||
|
loading = signal<boolean>(false);
|
||||||
|
column = [] as IColumn[];
|
||||||
|
@ViewChild('actionTpl', { static: true }) actionTpl!: TemplateRef<any>;
|
||||||
|
|
||||||
|
constructor(private readonly service: SharedStatisticsService) {
|
||||||
|
this.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.column = [
|
||||||
|
{ field: 'name', header: 'عنوان' },
|
||||||
|
{
|
||||||
|
field: 'totalDebt',
|
||||||
|
header: 'بدهی کل',
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unpaidReceipts',
|
||||||
|
header: 'فاکتورهای تسویهنشده',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.loading.set(true);
|
||||||
|
this.service.getTopSupplierDebts().subscribe({
|
||||||
|
next: (res) => {
|
||||||
|
this.items.set(res.data);
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const baseUrl = '/api/v1/statistics';
|
||||||
|
|
||||||
|
export const SHARED_STATISTICS_API_ROUTES = {
|
||||||
|
topAlertStock: `${baseUrl}/top-alert-stocks`,
|
||||||
|
topSales: `${baseUrl}/top-sales`,
|
||||||
|
topSupplierDebts: `${baseUrl}/top-supplier-debts`,
|
||||||
|
topSellProducts: `${baseUrl}/top-sell-products`,
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './apiRoutes';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './io';
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import ISummary from '@/core/models/summary';
|
||||||
|
|
||||||
|
export interface IStatisticsTopAlertStockRawResponse {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
sku: string;
|
||||||
|
minimumStockAlertLevel: string;
|
||||||
|
stockBalances: any[];
|
||||||
|
category: ISummary;
|
||||||
|
brand: ISummary;
|
||||||
|
deficit: number;
|
||||||
|
}
|
||||||
|
export interface IStatisticsTopAlertStockResponse extends IStatisticsTopAlertStockRawResponse {}
|
||||||
|
|
||||||
|
export interface IStatisticsTopSalesRawResponse {}
|
||||||
|
export interface IStatisticsTopSalesResponse extends IStatisticsTopSalesRawResponse {}
|
||||||
|
|
||||||
|
export interface IStatisticsTopSupplierDebtsRawResponse {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
totalDebt: number;
|
||||||
|
unpaidReceipts: number;
|
||||||
|
}
|
||||||
|
export interface IStatisticsTopSupplierDebtsResponse extends IStatisticsTopSupplierDebtsRawResponse {}
|
||||||
|
|
||||||
|
export interface IStatisticsTopSellProductsRawResponse {}
|
||||||
|
export interface IStatisticsTopSellProductsResponse extends IStatisticsTopSellProductsRawResponse {}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { SHARED_STATISTICS_API_ROUTES } from '../constants';
|
||||||
|
import {
|
||||||
|
IStatisticsTopAlertStockRawResponse,
|
||||||
|
IStatisticsTopAlertStockResponse,
|
||||||
|
IStatisticsTopSalesRawResponse,
|
||||||
|
IStatisticsTopSalesResponse,
|
||||||
|
IStatisticsTopSellProductsRawResponse,
|
||||||
|
IStatisticsTopSellProductsResponse,
|
||||||
|
IStatisticsTopSupplierDebtsRawResponse,
|
||||||
|
IStatisticsTopSupplierDebtsResponse,
|
||||||
|
} from '../models';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class SharedStatisticsService {
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
private apiRoutes = SHARED_STATISTICS_API_ROUTES;
|
||||||
|
|
||||||
|
getTopAlertStock(): Observable<IPaginatedResponse<IStatisticsTopAlertStockResponse>> {
|
||||||
|
return this.http.get<IPaginatedResponse<IStatisticsTopAlertStockRawResponse>>(
|
||||||
|
`${this.apiRoutes.topAlertStock}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTopSales(): Observable<IPaginatedResponse<IStatisticsTopSalesResponse>> {
|
||||||
|
return this.http.get<IPaginatedResponse<IStatisticsTopSalesRawResponse>>(
|
||||||
|
`${this.apiRoutes.topSales}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTopSupplierDebts(): Observable<IPaginatedResponse<IStatisticsTopSupplierDebtsResponse>> {
|
||||||
|
return this.http.get<IPaginatedResponse<IStatisticsTopSupplierDebtsRawResponse>>(
|
||||||
|
`${this.apiRoutes.topSupplierDebts}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTopSellProducts(): Observable<IPaginatedResponse<IStatisticsTopSellProductsResponse>> {
|
||||||
|
return this.http.get<IPaginatedResponse<IStatisticsTopSellProductsRawResponse>>(
|
||||||
|
`${this.apiRoutes.topSellProducts}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,10 +85,10 @@
|
|||||||
<p-sortIcon field="quantity" />
|
<p-sortIcon field="quantity" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th pSortableColumn="fee">
|
<th pSortableColumn="unitPrice">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
قیمت واحد
|
قیمت واحد
|
||||||
<p-sortIcon field="fee" />
|
<p-sortIcon field="unitPrice" />
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th pSortableColumn="totalCost">
|
<th pSortableColumn="totalCost">
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
<td>{{ item.product.id }}</td>
|
<td>{{ item.product.id }}</td>
|
||||||
<td>{{ item.product.name }}</td>
|
<td>{{ item.product.name }}</td>
|
||||||
<td>{{ item.count }}</td>
|
<td>{{ item.count }}</td>
|
||||||
<td><span [appPriceMask]="item.fee"></span></td>
|
<td><span [appPriceMask]="item.unitPrice"></span></td>
|
||||||
<td><span [appPriceMask]="item.total"></span></td>
|
<td><span [appPriceMask]="item.total"></span></td>
|
||||||
<td>
|
<td>
|
||||||
<p-button type="button" icon="pi pi-search" [routerLink]="'/products/' + item.product.id" />
|
<p-button type="button" icon="pi pi-search" [routerLink]="'/products/' + item.product.id" />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[optionValue]="selectOptionValue"
|
[optionValue]="selectOptionValue"
|
||||||
placeholder="انتخاب تامینکننده"
|
placeholder="انتخاب تامینکننده"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
[showClear]="true"
|
[showClear]="showClear"
|
||||||
[filter]="true"
|
[filter]="true"
|
||||||
appendTo="body"
|
appendTo="body"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export interface ISupplierInventorySummary {
|
|||||||
export interface ISupplierReceiptItemSummary {
|
export interface ISupplierReceiptItemSummary {
|
||||||
id: number;
|
id: number;
|
||||||
count: string;
|
count: string;
|
||||||
fee: string;
|
unitPrice: string;
|
||||||
total: string;
|
total: string;
|
||||||
product: {
|
product: {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-center!">
|
<td class="text-center!">
|
||||||
@if (item.type === "IN") {
|
@if (item.type === "IN") {
|
||||||
<span [appPriceMask]="item.fee"></span>
|
<span [appPriceMask]="item.unitPrice"></span>
|
||||||
} @else {
|
} @else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@@ -54,13 +54,13 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-center!">
|
<td class="text-center!">
|
||||||
@if (item.type === "OUT") {
|
@if (item.type === "OUT") {
|
||||||
<span [appPriceMask]="item.fee"></span>
|
<span [appPriceMask]="item.unitPrice"></span>
|
||||||
} @else {
|
} @else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center!">{{ item.remainedInStock }}</td>
|
<td class="text-center!">{{ item.remainedInStock }}</td>
|
||||||
<!-- <td class="text-center!"><span [appPriceMask]="item.fee"></span></td>
|
<!-- <td class="text-center!"><span [appPriceMask]="item.unitPrice"></span></td>
|
||||||
<td class="text-center!"><span [appPriceMask]="item.totalCost"></span></td> -->
|
<td class="text-center!"><span [appPriceMask]="item.totalCost"></span></td> -->
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
[required]="isRequired"
|
[required]="isRequired"
|
||||||
[invalid]="control.invalid && (control.touched || control.dirty)"
|
[invalid]="control.invalid && (control.touched || control.dirty)"
|
||||||
(input)="onInput($event)"
|
(input)="onInput($event)"
|
||||||
|
(onBlur)="blur.emit()"
|
||||||
/>
|
/>
|
||||||
<p-inputgroup-addon>ریال</p-inputgroup-addon>
|
<p-inputgroup-addon>ریال</p-inputgroup-addon>
|
||||||
</p-inputgroup>
|
</p-inputgroup>
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
[required]="isRequired"
|
[required]="isRequired"
|
||||||
[invalid]="control.invalid && (control.touched || control.dirty)"
|
[invalid]="control.invalid && (control.touched || control.dirty)"
|
||||||
(input)="onInput($event)"
|
(input)="onInput($event)"
|
||||||
|
(onBlur)="blur.emit()"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@if (hint) {
|
@if (hint) {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export class InputComponent {
|
|||||||
@Input() showErrors = false;
|
@Input() showErrors = false;
|
||||||
@Input() hint?: string;
|
@Input() hint?: string;
|
||||||
@Output() valueChange = new EventEmitter<string | number>();
|
@Output() valueChange = new EventEmitter<string | number>();
|
||||||
|
@Output() blur = new EventEmitter<void>();
|
||||||
|
|
||||||
onInput(ev: Event) {
|
onInput(ev: Event) {
|
||||||
const v = (ev.target as HTMLInputElement).value;
|
const v = (ev.target as HTMLInputElement).value;
|
||||||
|
|||||||
@@ -5,5 +5,6 @@
|
|||||||
[supplierId]="purchaseReceipt.supplierId.toString()"
|
[supplierId]="purchaseReceipt.supplierId.toString()"
|
||||||
[inventoryId]="purchaseReceipt.inventoryId.toString()"
|
[inventoryId]="purchaseReceipt.inventoryId.toString()"
|
||||||
[invoiceId]="purchaseReceipt.id.toString()"
|
[invoiceId]="purchaseReceipt.id.toString()"
|
||||||
|
(onSubmit)="submitted()"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ToastService } from '@/core/services/toast.service';
|
import { ToastService } from '@/core/services/toast.service';
|
||||||
import { SupplierInvoicePayFormComponent } from '@/modules/suppliers/components/invoices/pay-form.component';
|
import { SupplierInvoicePayFormComponent } from '@/modules/suppliers/components/invoices/pay-form.component';
|
||||||
import { Component, Input, signal } from '@angular/core';
|
import { Component, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||||
import { IPurchaseReceiptResponse } from '../../../modules/purchases/models';
|
import { IPurchaseReceiptResponse } from '../../../modules/purchases/models';
|
||||||
import { ConfirmationDialogService } from '../confirmationDialog/confirmation-dialog.service';
|
import { ConfirmationDialogService } from '../confirmationDialog/confirmation-dialog.service';
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@ import { ConfirmationDialogService } from '../confirmationDialog/confirmation-di
|
|||||||
export class PurchaseReceiptPaymentWrapperComponent {
|
export class PurchaseReceiptPaymentWrapperComponent {
|
||||||
@Input() purchaseReceipt!: IPurchaseReceiptResponse;
|
@Input() purchaseReceipt!: IPurchaseReceiptResponse;
|
||||||
|
|
||||||
|
@Output() onSubmit = new EventEmitter<void>();
|
||||||
|
|
||||||
showPaymentForm = signal(false);
|
showPaymentForm = signal(false);
|
||||||
constructor(
|
constructor(
|
||||||
private confirmService: ConfirmationDialogService,
|
private confirmService: ConfirmationDialogService,
|
||||||
@@ -40,7 +42,12 @@ export class PurchaseReceiptPaymentWrapperComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {}
|
submitted() {
|
||||||
|
console.log('submitted');
|
||||||
|
|
||||||
|
this.showPaymentForm.set(false);
|
||||||
|
this.onSubmit.emit();
|
||||||
|
}
|
||||||
|
|
||||||
toPaymentForm() {
|
toPaymentForm() {
|
||||||
this.showPaymentForm.set(true);
|
this.showPaymentForm.set(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user