feat: implement invoice payments component and integrate with supplier invoices
This commit is contained in:
@@ -63,8 +63,6 @@ export class CardexFiltersComponent {
|
|||||||
this.store.setDefaultInventory(inventory);
|
this.store.setDefaultInventory(inventory);
|
||||||
}
|
}
|
||||||
setDefaultProduct(product: IProductResponse) {
|
setDefaultProduct(product: IProductResponse) {
|
||||||
console.log('setDefaultProduct');
|
|
||||||
|
|
||||||
this.store.setDefaultProduct(product);
|
this.store.setDefaultProduct(product);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export interface CardexState extends PaginatedState<ICardexResponse> {
|
|||||||
selectedProduct: Maybe<ICardexProductSummary>;
|
selectedProduct: Maybe<ICardexProductSummary>;
|
||||||
variant: 'inventory' | 'product' | 'general';
|
variant: 'inventory' | 'product' | 'general';
|
||||||
canChangeVariant: boolean;
|
canChangeVariant: boolean;
|
||||||
|
cardexTitle: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -63,6 +64,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
selectedProduct: null,
|
selectedProduct: null,
|
||||||
variant: 'general',
|
variant: 'general',
|
||||||
canChangeVariant: true,
|
canChangeVariant: true,
|
||||||
|
cardexTitle: 'کاردکس',
|
||||||
});
|
});
|
||||||
this.initial();
|
this.initial();
|
||||||
}
|
}
|
||||||
@@ -70,18 +72,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
readonly filters = computed(() => this._state().filters);
|
readonly filters = computed(() => this._state().filters);
|
||||||
readonly variant = computed(() => this._state().variant);
|
readonly variant = computed(() => this._state().variant);
|
||||||
readonly canChangeVariant = computed(() => this._state().canChangeVariant);
|
readonly canChangeVariant = computed(() => this._state().canChangeVariant);
|
||||||
readonly cardexTitle = computed(() => {
|
readonly cardexTitle = computed(() => this._state().cardexTitle);
|
||||||
switch (this._state().variant) {
|
|
||||||
case 'product':
|
|
||||||
return `کاردکس کالای ${this._state().selectedProduct?.name}`;
|
|
||||||
case 'inventory':
|
|
||||||
return `کاردکس انبار ${this._state().selectedInventory?.name}`;
|
|
||||||
default:
|
|
||||||
return `کاردکس ${this._state().selectedProduct ? 'کالای ' + this._state().selectedProduct?.name : ''} ${
|
|
||||||
this._state().selectedInventory ? 'در انبار ' + this._state().selectedInventory?.name : ''
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset state to initial values
|
* Reset state to initial values
|
||||||
@@ -109,6 +100,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
selectedProduct: null,
|
selectedProduct: null,
|
||||||
variant: 'general',
|
variant: 'general',
|
||||||
canChangeVariant: this.state().canChangeVariant,
|
canChangeVariant: this.state().canChangeVariant,
|
||||||
|
cardexTitle: 'کاردکس',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,8 +147,6 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
updateFilter(filters: ICardexRequestPayload) {
|
updateFilter(filters: ICardexRequestPayload) {
|
||||||
this.updateVariant();
|
this.updateVariant();
|
||||||
|
|
||||||
console.log('filters');
|
|
||||||
console.log(filters);
|
|
||||||
const cleanedFilters = this.validateFilters() || {};
|
const cleanedFilters = this.validateFilters() || {};
|
||||||
|
|
||||||
this.router
|
this.router
|
||||||
@@ -169,6 +159,7 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
this.patchState({ filters });
|
this.patchState({ filters });
|
||||||
|
this.updateCardexTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
setProduct(product: Maybe<ICardexProductSummary>) {
|
setProduct(product: Maybe<ICardexProductSummary>) {
|
||||||
@@ -184,10 +175,12 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
|
|
||||||
setDefaultInventory(inventory: ICardexInventorySummary) {
|
setDefaultInventory(inventory: ICardexInventorySummary) {
|
||||||
this.patchState({ selectedInventory: inventory });
|
this.patchState({ selectedInventory: inventory });
|
||||||
|
this.updateCardexTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultProduct(product: ICardexProductSummary) {
|
setDefaultProduct(product: ICardexProductSummary) {
|
||||||
this.patchState({ selectedProduct: product });
|
this.patchState({ selectedProduct: product });
|
||||||
|
this.updateCardexTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateVariant() {
|
private updateVariant() {
|
||||||
@@ -201,7 +194,27 @@ export class CardexStore extends PaginatedStore<ICardexResponse, CardexState> {
|
|||||||
} else if (productIsSelected) {
|
} else if (productIsSelected) {
|
||||||
variant = 'product';
|
variant = 'product';
|
||||||
}
|
}
|
||||||
|
this.updateCardexTitle();
|
||||||
|
|
||||||
this.patchState({ variant });
|
this.patchState({ variant });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateCardexTitle() {
|
||||||
|
let title = '';
|
||||||
|
switch (this._state().variant) {
|
||||||
|
case 'product':
|
||||||
|
title = `کاردکس کالای ${this._state().selectedProduct?.name}`;
|
||||||
|
break;
|
||||||
|
case 'inventory':
|
||||||
|
title = `کاردکس انبار ${this._state().selectedInventory?.name}`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
title = `کاردکس ${this._state().selectedProduct ? 'کالای ' + this._state().selectedProduct?.name : ''} ${
|
||||||
|
this._state().selectedInventory ? 'در انبار ' + this._state().selectedInventory?.name : ''
|
||||||
|
}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.patchState({ cardexTitle: title });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ export class InventoryBankAccountSelectComponent extends AbstractSelectComponent
|
|||||||
|
|
||||||
constructor(private service: InventoryBankAccountsService) {
|
constructor(private service: InventoryBankAccountsService) {
|
||||||
super();
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
console.log(this.inventoryId);
|
||||||
this.getData();
|
this.getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
import { NamedRoutes } from '@/core';
|
import { NamedRoutes } from '@/core';
|
||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
export type TInventoriesRouteNames =
|
export const inventoriesNamedRoutes: NamedRoutes<any> = {
|
||||||
| 'inventories'
|
|
||||||
| 'inventory'
|
|
||||||
| 'transfer'
|
|
||||||
| 'products'
|
|
||||||
| 'productCardex'
|
|
||||||
| 'posAccounts';
|
|
||||||
|
|
||||||
export const inventoriesNamedRoutes: NamedRoutes<TInventoriesRouteNames> = {
|
|
||||||
inventories: {
|
inventories: {
|
||||||
path: 'inventories',
|
path: 'inventories',
|
||||||
loadComponent: () => import('../../views/list.component').then((m) => m.InventoriesComponent),
|
loadComponent: () => import('../../views/list.component').then((m) => m.InventoriesComponent),
|
||||||
@@ -65,6 +57,17 @@ export const inventoriesNamedRoutes: NamedRoutes<TInventoriesRouteNames> = {
|
|||||||
pagePath: () => '/inventories/:inventoryId/pos-accounts',
|
pagePath: () => '/inventories/:inventoryId/pos-accounts',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
purchase: {
|
||||||
|
path: 'inventories/:inventoryId/purchase',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('../../views/purchase.component').then((m) => m.InventoryPurchaseComponent),
|
||||||
|
meta: {
|
||||||
|
title: 'ثبت خرید در انبار',
|
||||||
|
pagePath: () => '/inventories/:inventoryId/purchase',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type TInventoriesRouteNames = keyof typeof inventoriesNamedRoutes;
|
||||||
|
|
||||||
export const INVENTORIES_ROUTES: Routes = Object.values(inventoriesNamedRoutes);
|
export const INVENTORIES_ROUTES: Routes = Object.values(inventoriesNamedRoutes);
|
||||||
|
|||||||
@@ -21,3 +21,24 @@ export interface IInventoryBankAccountRequest extends IBankAccountsRequest {}
|
|||||||
export interface IInventoryAssignBankAccountRequest {
|
export interface IInventoryAssignBankAccountRequest {
|
||||||
bankAccountId: number;
|
bankAccountId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IBankAccountSummary {
|
||||||
|
branch: Branch;
|
||||||
|
accountNumber: string;
|
||||||
|
cardNumber: string;
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
iban: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Branch {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
bank: Bank;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Bank {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
shortName: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,10 +43,13 @@ export class InventoryStore extends EntityStore<IInventoryDetailResponse, Invent
|
|||||||
this.patchState({ loading: true });
|
this.patchState({ loading: true });
|
||||||
this.service.getSingle(inventoryId).subscribe({
|
this.service.getSingle(inventoryId).subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
|
console.log('first');
|
||||||
|
|
||||||
this.patchState({
|
this.patchState({
|
||||||
entities: { [res.id]: res },
|
entities: { [res.id]: res },
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
});
|
||||||
|
console.log(this.entities());
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
this.patchState({ loading: false, error: err });
|
this.patchState({ loading: false, error: err });
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@if (loading()) {
|
||||||
|
} @else {
|
||||||
|
<purchase-receipt-template [inventory]="inventory()" />
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { PurchaseReceiptTemplateComponent } from '@/modules/purchases/components';
|
||||||
|
import { Component, computed, inject } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { InventoryStore } from '../store/inventory.store';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-inventory-purchase',
|
||||||
|
templateUrl: './purchase.component.html',
|
||||||
|
imports: [PurchaseReceiptTemplateComponent],
|
||||||
|
})
|
||||||
|
export class InventoryPurchaseComponent {
|
||||||
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
private readonly store = inject(InventoryStore);
|
||||||
|
|
||||||
|
inventoryId = this.route.snapshot.paramMap.get('inventoryId')!;
|
||||||
|
|
||||||
|
inventory = computed(() => this.store.entities()[this.inventoryId]);
|
||||||
|
loading = this.store.loading;
|
||||||
|
constructor() {
|
||||||
|
this.store.getSingle(this.inventoryId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,14 +14,19 @@
|
|||||||
icon="pi pi-plus"
|
icon="pi pi-plus"
|
||||||
[routerLink]="['/inventories', inventoryId, 'pos-accounts']"
|
[routerLink]="['/inventories', inventoryId, 'pos-accounts']"
|
||||||
></button>
|
></button>
|
||||||
<button pButton type="button" label="افزایش موجودی" icon="pi pi-plus"></button>
|
<button
|
||||||
<!-- [routerLink]="['/inventories', inventoryId, 'purchase']" -->
|
pButton
|
||||||
|
type="button"
|
||||||
|
label="افزایش موجودی"
|
||||||
|
icon="pi pi-plus"
|
||||||
|
[routerLink]="['/inventories', inventoryId, 'purchase']"
|
||||||
|
></button>
|
||||||
<button
|
<button
|
||||||
pButton
|
pButton
|
||||||
type="button"
|
type="button"
|
||||||
label="انتقال کالا"
|
label="انتقال کالا"
|
||||||
icon="pi pi-plus"
|
icon="pi pi-plus"
|
||||||
[routerLink]="['/inventories', inventoryId, 'transfer']"
|
[routerLink]="['/inventories', 'transfer']"
|
||||||
></button>
|
></button>
|
||||||
<button pButton type="button" label="ویرایش" icon="pi pi-pencil"></button>
|
<button pButton type="button" label="ویرایش" icon="pi pi-pencil"></button>
|
||||||
<!-- [routerLink]="['/inventories', inventoryId, 'update']" -->
|
<!-- [routerLink]="['/inventories', inventoryId, 'update']" -->
|
||||||
|
|||||||
+4
-4
@@ -151,8 +151,8 @@
|
|||||||
<span class="font-bold" [appPriceMask]="totalAmount"></span>
|
<span class="font-bold" [appPriceMask]="totalAmount"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span>مالیات (۹٪):</span>
|
<span>مالیات (۱۰٪):</span>
|
||||||
<span class="font-bold" [appPriceMask]="totalAmount * 0.09"></span>
|
<span class="font-bold" [appPriceMask]="totalAmount * 0.1"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -161,12 +161,12 @@
|
|||||||
<td [attr.colspan]="6" class="p-0! border-none!">
|
<td [attr.colspan]="6" 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.09" class="font-bold text-lg"></span>
|
<span [appPriceAlphabet]="totalAmount + totalAmount * 0.1" class="font-bold text-lg"></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td [attr.colspan]="2" class="p-0! border-none!">
|
<td [attr.colspan]="2" class="p-0! border-none!">
|
||||||
<div class="flex h-full items-center justify-end py-10 px-2 border-surface-700 border-t-4 border-r">
|
<div class="flex h-full items-center justify-end py-10 px-2 border-surface-700 border-t-4 border-r">
|
||||||
<span [appPriceMask]="totalAmount + totalAmount * 0.09" class="text-xl font-bold"></span>
|
<span [appPriceMask]="totalAmount + totalAmount * 0.1" class="text-xl font-bold"></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
+10
-1
@@ -10,7 +10,7 @@ import { IColumn } from '@/shared/components/pageDataList/page-data-list.compone
|
|||||||
import { PriceAlphabetDirective, PriceMaskDirective } from '@/shared/directives';
|
import { PriceAlphabetDirective, PriceMaskDirective } from '@/shared/directives';
|
||||||
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, inject, Input, signal } from '@angular/core';
|
import { Component, effect, inject, Input, signal } from '@angular/core';
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
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';
|
||||||
@@ -130,6 +130,15 @@ export class PurchaseReceiptTemplateComponent {
|
|||||||
this.form.controls.paidAmount.setValue(0);
|
this.form.controls.paidAmount.setValue(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
if (this.inventory) {
|
||||||
|
this.form.controls.inventory.setValue(this.inventory);
|
||||||
|
}
|
||||||
|
if (this.supplier) {
|
||||||
|
this.form.controls.supplier.setValue(this.supplier);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formIsSubmitted = signal(false);
|
formIsSubmitted = signal(false);
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<app-page-data-list [items]="items()" [columns]="columns" [loading]="loading()" pageTitle="پرداختهای فاکتور">
|
||||||
|
<ng-template #paymentMethodTpl let-item>
|
||||||
|
<app-catalog-payment-method-type-tag [type]="item.paymentMethod" />
|
||||||
|
</ng-template>
|
||||||
|
</app-page-data-list>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { CatalogPaymentMethodTypeTagComponent } from '@/shared/catalog/paymentMethodTypes';
|
||||||
|
import {
|
||||||
|
IColumn,
|
||||||
|
PageDataListComponent,
|
||||||
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
|
import { Component, Input, signal, TemplateRef, ViewChild } from '@angular/core';
|
||||||
|
import { IInvoicePaymentResponse } from '../../models/invoices.io';
|
||||||
|
import { SupplierInvoicesService } from '../../services';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-invoice-payments',
|
||||||
|
templateUrl: './payments.component.html',
|
||||||
|
imports: [PageDataListComponent, CatalogPaymentMethodTypeTagComponent],
|
||||||
|
})
|
||||||
|
export class InvoicePaymentsComponent {
|
||||||
|
@Input() supplierId!: string;
|
||||||
|
@Input() invoiceId!: string;
|
||||||
|
@ViewChild('paymentMethodTpl', { static: true }) paymentMethodTpl!: TemplateRef<any>;
|
||||||
|
constructor(private readonly service: SupplierInvoicesService) {}
|
||||||
|
|
||||||
|
columns = [] as IColumn[];
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
console.log(this.invoiceId);
|
||||||
|
this.columns = [
|
||||||
|
{
|
||||||
|
field: 'index',
|
||||||
|
header: 'ردیف',
|
||||||
|
type: 'index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'code',
|
||||||
|
header: 'شناسه پرداخت',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'amount',
|
||||||
|
header: 'مبلغ پرداختی',
|
||||||
|
type: 'price',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'paymentMethod',
|
||||||
|
header: 'روش پرداخت',
|
||||||
|
customDataModel: this.paymentMethodTpl,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'bankAccount',
|
||||||
|
header: 'حساب بانکی',
|
||||||
|
customDataModel: (item: IInvoicePaymentResponse) =>
|
||||||
|
`${item.bankAccount.name} - بانک ${item.bankAccount.branch.bank.name} - شعبه ${item.bankAccount.branch.name}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'payedAt',
|
||||||
|
header: 'تاریخ پرداخت',
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
items = signal<IInvoicePaymentResponse[]>([]);
|
||||||
|
loading = signal(false);
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
this.loading.set(true);
|
||||||
|
return this.service.getPayments(this.supplierId!, this.invoiceId!).subscribe({
|
||||||
|
next: (res) => {
|
||||||
|
this.items.set(res.data);
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
this.loading.set(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<span class="text-xl font-bold">دفتر کل تامینکننده</span>
|
<span class="text-xl font-bold">دفتر کل تامینکننده</span>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@if (showViewAllCTA) {
|
@if (showViewAllCTA) {
|
||||||
<button pButton outlined [routerLink]="['/suppliers', supplierId, 'ledger']">مشاهدهی تمامی تراکنشها</button>
|
<button pButton outlined [routerLink]="['/suppliers', supplierId, 'ledger']">مشاهدهی دفتر کل</button>
|
||||||
}
|
}
|
||||||
<button pButton outlined icon="pi pi-refresh" [loading]="loading()" (click)="getAll()"></button>
|
<button pButton outlined icon="pi pi-refresh" [loading]="loading()" (click)="getAll()"></button>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
<ng-template pTemplate="emptymessage">
|
<ng-template pTemplate="emptymessage">
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="7" class="text-center! p-10!">هیچ فاکتوری ثبت نشده است.</td>
|
<td colspan="7" class="text-center! p-10!">هیچ رکوردی ثبت نشده است.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-table>
|
</p-table>
|
||||||
|
|||||||
@@ -4,5 +4,7 @@ export const SUPPLIER_INVOICES_API_ROUTES = (_baseUrl: string) => {
|
|||||||
list: (supplierId: string) => `${baseUrl(supplierId)}`,
|
list: (supplierId: string) => `${baseUrl(supplierId)}`,
|
||||||
single: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}`,
|
single: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}`,
|
||||||
pay: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}/pay`,
|
pay: (supplierId: string, invoiceId: string) => `${baseUrl(supplierId)}/${invoiceId}/pay`,
|
||||||
|
invoicePayments: (supplierId: string, invoiceId: string) =>
|
||||||
|
`${baseUrl(supplierId)}/${invoiceId}/payments`,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import ISummary from '@/core/models/summary';
|
import ISummary from '@/core/models/summary';
|
||||||
|
import { IBankAccountSummary } from '@/modules/inventories/models';
|
||||||
import { PurchaseReceiptStatus } from '@/shared/catalog';
|
import { PurchaseReceiptStatus } from '@/shared/catalog';
|
||||||
import { PaymentMethodType } from '@/shared/catalog/paymentMethodTypes';
|
import { PaymentMethodType } from '@/shared/catalog/paymentMethodTypes';
|
||||||
import { PaymentType } from '@/shared/catalog/paymentTypes';
|
import { PaymentType } from '@/shared/catalog/paymentTypes';
|
||||||
import { ISupplierReceiptItemSummary } from './types';
|
import { IReceiptInfo, ISupplierReceiptItemSummary } from './types';
|
||||||
|
|
||||||
export interface ISupplierInvoicesRawResponse {
|
export interface ISupplierInvoicesRawResponse {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -37,3 +38,18 @@ export interface IPayRawResponse {
|
|||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
export interface IPayResponse extends IPayRawResponse {}
|
export interface IPayResponse extends IPayRawResponse {}
|
||||||
|
|
||||||
|
export interface IInvoicePaymentRawResponse {
|
||||||
|
id: number;
|
||||||
|
amount: string;
|
||||||
|
paymentMethod: string;
|
||||||
|
type: string;
|
||||||
|
bankAccountId: number;
|
||||||
|
payedAt: string;
|
||||||
|
description: null;
|
||||||
|
createdAt: string;
|
||||||
|
receipt: IReceiptInfo;
|
||||||
|
bankAccount: IBankAccountSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IInvoicePaymentResponse extends IInvoicePaymentRawResponse {}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import ISummary from '@/core/models/summary';
|
||||||
|
|
||||||
export interface IReceiptsOverview {
|
export interface IReceiptsOverview {
|
||||||
totalPayment: string;
|
totalPayment: string;
|
||||||
count: number;
|
count: number;
|
||||||
@@ -19,3 +21,17 @@ export interface ISupplierReceiptItemSummary {
|
|||||||
sku: string;
|
sku: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IReceiptInfo {
|
||||||
|
id: number;
|
||||||
|
code: string;
|
||||||
|
totalAmount: string;
|
||||||
|
paidAmount: string;
|
||||||
|
description: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
status: string;
|
||||||
|
supplierId: number;
|
||||||
|
inventoryId: number;
|
||||||
|
inventory: ISummary;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { Injectable } from '@angular/core';
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { SUPPLIERS_API_ROUTES } from '../constants';
|
import { SUPPLIERS_API_ROUTES } from '../constants';
|
||||||
import {
|
import {
|
||||||
|
IInvoicePaymentRawResponse,
|
||||||
|
IInvoicePaymentResponse,
|
||||||
IPayRawResponse,
|
IPayRawResponse,
|
||||||
IPayRequestPayload,
|
IPayRequestPayload,
|
||||||
IPayResponse,
|
IPayResponse,
|
||||||
@@ -36,4 +38,13 @@ export class SupplierInvoicesService {
|
|||||||
): Observable<IPayResponse> {
|
): Observable<IPayResponse> {
|
||||||
return this.http.post<IPayRawResponse>(this.apiRoutes.pay(supplierId, invoiceId), payload);
|
return this.http.post<IPayRawResponse>(this.apiRoutes.pay(supplierId, invoiceId), payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPayments(
|
||||||
|
supplierId: string,
|
||||||
|
invoiceId: string,
|
||||||
|
): Observable<IPaginatedResponse<IInvoicePaymentResponse>> {
|
||||||
|
return this.http.get<IPaginatedResponse<IInvoicePaymentRawResponse>>(
|
||||||
|
this.apiRoutes.invoicePayments(supplierId, invoiceId),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
</app-key-value>
|
</app-key-value>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<app-invoice-payments [supplierId]="supplierId" [invoiceId]="invoiceId" />
|
||||||
@if (invoice() && supplier()) {
|
@if (invoice() && supplier()) {
|
||||||
<app-supplier-invoice-pay-form
|
<app-supplier-invoice-pay-form
|
||||||
[(visible)]="showPayForm"
|
[(visible)]="showPayForm"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Component, computed, inject, signal } from '@angular/core';
|
|||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { SupplierInvoicePayFormComponent } from '../components/invoices/pay-form.component';
|
import { SupplierInvoicePayFormComponent } from '../components/invoices/pay-form.component';
|
||||||
|
import { InvoicePaymentsComponent } from '../components/invoices/payments.component';
|
||||||
import { SupplierInvoiceStore, SupplierStore } from '../store';
|
import { SupplierInvoiceStore, SupplierStore } from '../store';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -16,6 +17,7 @@ import { SupplierInvoiceStore, SupplierStore } from '../store';
|
|||||||
CatalogPurchaseReceiptStatusTagComponent,
|
CatalogPurchaseReceiptStatusTagComponent,
|
||||||
ButtonDirective,
|
ButtonDirective,
|
||||||
SupplierInvoicePayFormComponent,
|
SupplierInvoicePayFormComponent,
|
||||||
|
InvoicePaymentsComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SupplierInvoiceComponent {
|
export class SupplierInvoiceComponent {
|
||||||
@@ -27,6 +29,7 @@ export class SupplierInvoiceComponent {
|
|||||||
this.supplierStore.getSingle(this.supplierId);
|
this.supplierStore.getSingle(this.supplierId);
|
||||||
this.store.supplierId = this.supplierId;
|
this.store.supplierId = this.supplierId;
|
||||||
this.store.getSingle(this.invoiceId);
|
this.store.getSingle(this.invoiceId);
|
||||||
|
console.log(this.supplierId);
|
||||||
}
|
}
|
||||||
|
|
||||||
supplierId = this.route.snapshot.params['supplierId'];
|
supplierId = this.route.snapshot.params['supplierId'];
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<app-inner-pages-header [pageTitle]="pageTitle()" [backRoute]="['/suppliers', supplierId]" />
|
<app-inner-pages-header [pageTitle]="pageTitle()" [backRoute]="['/suppliers', supplierId]" />
|
||||||
<div class="inline-flex items-center gap-5">
|
<div class="inline-flex items-center gap-5">
|
||||||
|
@if (supplier()) {
|
||||||
<div class="">
|
<div class="">
|
||||||
<app-key-value label="شماره تماس" [value]="supplier()?.mobileNumber" />
|
<app-key-value label="شماره تماس" [value]="supplier().mobileNumber" />
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
<div class="grid grid-cols-4 gap-4">
|
<div class="grid grid-cols-4 gap-4">
|
||||||
@for (item of topBarCardDetails; track $index) {
|
@for (item of topBarCardDetails; track $index) {
|
||||||
<details-info-card [icon]="item.icon" [label]="item.label" [value]="item.value?.toString() || ''" />
|
<details-info-card [icon]="item.icon" [label]="item.label" [value]="item.value.toString() || ''" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
import { PriceMaskDirective } from '@/shared/directives';
|
|
||||||
import { UikitFieldComponent } from '@/uikit/uikit-field.component';
|
import { UikitFieldComponent } from '@/uikit/uikit-field.component';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
@@ -20,7 +19,6 @@ import { ToggleSwitch } from 'primeng/toggleswitch';
|
|||||||
InputGroupModule,
|
InputGroupModule,
|
||||||
UikitFieldComponent,
|
UikitFieldComponent,
|
||||||
ToggleSwitch,
|
ToggleSwitch,
|
||||||
PriceMaskDirective,
|
|
||||||
InputGroupAddon,
|
InputGroupAddon,
|
||||||
InputNumberModule,
|
InputNumberModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -41,7 +41,15 @@
|
|||||||
<ng-template #header let-columns>
|
<ng-template #header let-columns>
|
||||||
<tr>
|
<tr>
|
||||||
@for (col of columns; track col.header) {
|
@for (col of columns; track col.header) {
|
||||||
<th [style]="{ width: col.width, minWidth: col.minWidth }">{{ col.header }}</th>
|
<th
|
||||||
|
[style]="
|
||||||
|
col.type === 'index'
|
||||||
|
? { width: '3rem', minWidth: '3rem' }
|
||||||
|
: { width: col.width, minWidth: col.minWidth }
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ col.header }}
|
||||||
|
</th>
|
||||||
}
|
}
|
||||||
@if (actionsCount()) {
|
@if (actionsCount()) {
|
||||||
<th type="th" [style]="{ width: `${actionsCount() * 2 + (actionsCount() - 1) * 0.25}rem` }"></th>
|
<th type="th" [style]="{ width: `${actionsCount() * 2 + (actionsCount() - 1) * 0.25}rem` }"></th>
|
||||||
@@ -49,11 +57,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #body let-item>
|
<ng-template #body let-item let-i="rowIndex">
|
||||||
<tr>
|
<tr>
|
||||||
@for (col of columns; track col.field) {
|
@for (col of columns; track col.field) {
|
||||||
<td>
|
<td>
|
||||||
@if (getTemplate(col)) {
|
@if (col.type === "index") {
|
||||||
|
{{ i * (currentPage || 1) + 1 }}
|
||||||
|
} @else if (getTemplate(col)) {
|
||||||
<ng-container
|
<ng-container
|
||||||
[ngTemplateOutlet]="getTemplate(col)"
|
[ngTemplateOutlet]="getTemplate(col)"
|
||||||
[ngTemplateOutletContext]="{ $implicit: item }"
|
[ngTemplateOutletContext]="{ $implicit: item }"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export interface IColumn<T = any> {
|
|||||||
width?: string;
|
width?: string;
|
||||||
minWidth?: string;
|
minWidth?: string;
|
||||||
canCopy?: boolean;
|
canCopy?: boolean;
|
||||||
type?: 'text' | 'price' | 'boolean' | 'date' | 'nested';
|
type?: 'text' | 'price' | 'boolean' | 'date' | 'nested' | 'index';
|
||||||
nestedPath?: string;
|
nestedPath?: string;
|
||||||
customDataModel?: TemplateRef<any> | ((item: T) => string | number | boolean);
|
customDataModel?: TemplateRef<any> | ((item: T) => string | number | boolean);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user