feat: Add Cardex module with filters and invoices components
- Implemented Cardex routes and integrated with the main application routing. - Created filters component for Cardex to filter inventory and product data. - Developed invoices component to display supplier invoices with detailed views. - Enhanced Products module with pagination and state management using a store. - Updated Suppliers module to include invoice management and detailed supplier views. - Refactored state management in Products and Suppliers to utilize signals for reactive updates. - Added new models and services to support the Cardex functionality. - Improved UI components for better user experience in displaying data.
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<form [formGroup]="form" class="flex items-end gap-4">
|
||||
<div class="grow grid grid-cols-4 gap-2">
|
||||
<inventories-select-field [control]="form.controls.inventoryId" />
|
||||
<products-select-field [control]="form.controls.productId" />
|
||||
<uikit-datepicker [control]="form.controls.startDate" />
|
||||
<uikit-datepicker [control]="form.controls.endDate" />
|
||||
</div>
|
||||
<div class="shrink-0">
|
||||
<button pButton>جستجو</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,31 @@
|
||||
import { InventoriesSelectComponent } from '@/modules/inventories/components';
|
||||
import { ProductsSelectComponent } from '@/modules/products/components/select/select.component';
|
||||
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
|
||||
@Component({
|
||||
selector: 'cardex-filters',
|
||||
templateUrl: './filters.component.html',
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
InventoriesSelectComponent,
|
||||
ProductsSelectComponent,
|
||||
UikitFlatpickrJalaliComponent,
|
||||
ButtonDirective,
|
||||
],
|
||||
})
|
||||
export class CardexFiltersComponent {
|
||||
private route = inject(ActivatedRoute);
|
||||
private fb = inject(FormBuilder);
|
||||
constructor() {}
|
||||
|
||||
form = this.fb.group({
|
||||
inventoryId: [Number(this.route.snapshot.queryParams['inventoryId']) || 0],
|
||||
productId: [Number(this.route.snapshot.queryParams['productId']) || 0],
|
||||
startDate: [this.route.snapshot.queryParams['startDate'] || ''],
|
||||
endDate: [this.route.snapshot.queryParams['endDate'] || ''],
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './filters/filters.component';
|
||||
@@ -0,0 +1,5 @@
|
||||
const baseUrl = '/api/v1/cardex';
|
||||
|
||||
export const CARDEX_API_ROUTES = {
|
||||
cardex: () => `${baseUrl}`,
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './apiRoutes';
|
||||
export * from './routes';
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NamedRoutes } from '@/core';
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
export type TCARDEXRouteNames = 'CARDEX';
|
||||
|
||||
export const cardexNamedRoutes: NamedRoutes<TCARDEXRouteNames> = {
|
||||
CARDEX: {
|
||||
path: 'cardex',
|
||||
loadComponent: () => import('../../views/cardex.component').then((m) => m.CardexPageComponent),
|
||||
meta: {
|
||||
title: 'کاردکس',
|
||||
pagePath: () => '/cardex',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const CARDEX_ROUTES: Routes = Object.values(cardexNamedRoutes);
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './io';
|
||||
export * from './types';
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
IInventoryInfo,
|
||||
IInventoryMovement,
|
||||
IInventoryStockProduct,
|
||||
IInventoryTransferRequestItem,
|
||||
} from './types';
|
||||
|
||||
export interface IInventorySummaryRawResponse {
|
||||
id: number;
|
||||
name: string;
|
||||
location: string;
|
||||
isActive: boolean;
|
||||
isPointOfSale: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface IInventorySummaryResponse extends IInventorySummaryRawResponse {}
|
||||
|
||||
export interface IInventoryDetailRawResponse extends IInventorySummaryRawResponse {
|
||||
availableProductTypes: number;
|
||||
availableProductCount: number;
|
||||
availableProductsCost: number;
|
||||
}
|
||||
|
||||
export interface IInventoryDetailResponse extends IInventoryDetailRawResponse {}
|
||||
|
||||
export interface IInventoryRequest {
|
||||
name: string;
|
||||
location: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export interface IInventoryStockMovementRawResponse {
|
||||
receiptId: string;
|
||||
count: number;
|
||||
info: IInventoryInfo;
|
||||
movements: IInventoryMovement[];
|
||||
}
|
||||
|
||||
export interface IInventoryStockMovementResponse extends IInventoryStockMovementRawResponse {}
|
||||
|
||||
export interface IInventoryTransferRequest {
|
||||
code: string;
|
||||
description: string;
|
||||
fromInventoryId: number;
|
||||
toInventoryId: number;
|
||||
items: IInventoryTransferRequestItem[];
|
||||
}
|
||||
|
||||
export interface IInventoryStockRawResponse {
|
||||
quantity: number;
|
||||
avgCost: number;
|
||||
product: IInventoryStockProduct;
|
||||
}
|
||||
|
||||
export interface IInventoryStockResponse extends IInventoryStockRawResponse {}
|
||||
|
||||
export interface IInventoryStockQuery {
|
||||
isAvailable?: boolean;
|
||||
}
|
||||
|
||||
export interface IInventoryProductCardexRawResponse extends IInventoryStockMovementRawResponse {}
|
||||
|
||||
export interface IInventoryProductCardexResponse extends IInventoryProductCardexRawResponse {}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { IProductRawResponse } from '@/modules/products/models';
|
||||
|
||||
export interface IInventoryMovement {
|
||||
id: number;
|
||||
quantity: number;
|
||||
fee: number;
|
||||
totalCost: number;
|
||||
avgCost: number;
|
||||
product: IInventoryProduct;
|
||||
remainedInStock: number;
|
||||
}
|
||||
|
||||
export interface IInventoryProduct {
|
||||
id: number;
|
||||
name: string;
|
||||
description: null;
|
||||
sku: string;
|
||||
barcode: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: null;
|
||||
brandId: number;
|
||||
categoryId: number;
|
||||
}
|
||||
|
||||
export interface IInventoryInfo {
|
||||
date: string;
|
||||
type: string;
|
||||
quantity: number;
|
||||
fee: number;
|
||||
totalCost: number;
|
||||
referenceType: string;
|
||||
referenceId: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface IInventoryTransferRequestItem {
|
||||
productId: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface IInventoryStockProduct extends IProductRawResponse {}
|
||||
@@ -0,0 +1,8 @@
|
||||
<div class="flex flex-col gap-4">
|
||||
<p-card>
|
||||
<cardex-filters />
|
||||
</p-card>
|
||||
<p-card>
|
||||
<uikit-empty-state title="برای مشاهدهی کاردکس اطلاعات بالا را تکمیل کنید"> </uikit-empty-state>
|
||||
</p-card>
|
||||
</div>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { UikitEmptyStateComponent } from '@/uikit';
|
||||
import { Component } from '@angular/core';
|
||||
import { Card } from 'primeng/card';
|
||||
import { CardexFiltersComponent } from '../components';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cardex',
|
||||
templateUrl: './cardex.component.html',
|
||||
imports: [Card, CardexFiltersComponent, UikitEmptyStateComponent],
|
||||
})
|
||||
export class CardexPageComponent {
|
||||
constructor() {}
|
||||
}
|
||||
Reference in New Issue
Block a user