feat(consumers): implement consumer and POS stores with breadcrumb management

- Added ConsumerStore and PosStore to manage state and data fetching for consumers and POS entities.
- Implemented breadcrumb functionality in both stores to enhance navigation.
- Created views for consumer accounts, business activities, complexes, and poses with respective components.
- Developed single view components for detailed display and editing of consumer and POS data.
- Introduced charge account management components in the super admin module, including forms and lists for charge transactions.
- Established API routes and services for handling charge account transactions.
This commit is contained in:
2026-04-23 20:59:48 +03:30
parent 57f333f5b8
commit e58bcbef57
119 changed files with 2917 additions and 52 deletions
@@ -8,7 +8,7 @@
>
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
<app-input label="عنوان" [control]="form.controls.name" name="name" />
<app-input label="کد مالیاتی" [control]="form.controls.tax_id" name="tax_id" />
<app-input label="کد شعبه" [control]="form.controls.branch_code" name="branch_code" />
<app-input label="آدرس" [control]="form.controls.address" name="address" />
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
</form>
@@ -25,7 +25,7 @@ export class ConsumerComplexFormComponent extends AbstractFormDialog<
initForm = () => {
return this.fb.group({
name: [this.initialValues?.name || '', [Validators.required]],
tax_id: [this.initialValues?.tax_id || '', [Validators.required]],
branch_code: [this.initialValues?.branch_code || ''],
address: [this.initialValues?.address || '', [Validators.required]],
});
};
@@ -33,7 +33,7 @@ export class ConsumerComplexFormComponent extends AbstractFormDialog<
form = this.initForm();
get preparedTitle() {
return `ویرایش فروشگاه ${this.initialValues?.name}`;
return `ویرایش شعبه ${this.initialValues?.name}`;
}
override ngOnChanges(): void {
@@ -1,7 +1,7 @@
<app-page-data-list
pageTitle="لیست فروشگاه‌ها"
pageTitle="لیست شعب"
[columns]="columns"
emptyPlaceholderTitle="فروشگاهی یافت نشد."
emptyPlaceholderTitle="شعبه‌ای یافت نشد."
[items]="items()"
[loading]="loading()"
[showDetails]="true"
@@ -12,7 +12,7 @@ export const consumerComplexesNamedRoutes: NamedRoutes<TComplexesRouteNames> = {
loadComponent: () =>
import('../../views/complexes/list.component').then((m) => m.ConsumerComplexesComponent),
meta: {
title: 'فروشگاه‌ها',
title: 'شعب',
pagePath: (businessId: string) => baseUrl(businessId),
},
},
@@ -21,7 +21,7 @@ export const consumerComplexesNamedRoutes: NamedRoutes<TComplexesRouteNames> = {
loadComponent: () =>
import('../../views/complexes/single.component').then((m) => m.ConsumerComplexComponent),
meta: {
title: 'فروشگاه',
title: 'شعبه',
pagePath: (businessId: string, complexId: string) => `${baseUrl(businessId)}/${complexId}`,
},
},
@@ -1,7 +1,7 @@
export interface IComplexRawResponse {
name: string;
address: string;
tax_id: string;
branch_code: string;
id: string;
}
export interface IComplexResponse extends IComplexRawResponse {}
@@ -9,5 +9,5 @@ export interface IComplexResponse extends IComplexRawResponse {}
export interface IComplexRequest {
name: string;
address: string;
tax_id: string;
branch_code: string;
}
@@ -3,10 +3,12 @@ import ISummary from '@/core/models/summary';
export interface IBusinessActivityRawResponse {
id: string;
name: string;
economic_code: string;
guild: ISummary;
}
export interface IBusinessActivityResponse extends IBusinessActivityRawResponse {}
export interface IBusinessActivityRequest {
economic_code: string;
name: string;
}
@@ -1,9 +1,8 @@
<div class="flex flex-col gap-6">
<app-card-data cardTitle="اطلاعات فروشگاه" [editable]="true" [(editMode)]="editMode">
<app-card-data cardTitle="اطلاعات شعبه" [editable]="true" [(editMode)]="editMode">
<div class="flex flex-col gap-4">
<div class="grid grid-cols-3 gap-4 items-center">
<app-key-value label="عنوان" [value]="complex()?.name" />
<app-key-value label="کد مالیاتی" [value]="complex()?.tax_id" />
<app-key-value label="آدرس" [value]="complex()?.address" />
</div>
</div>
@@ -4,6 +4,7 @@
<div class="flex flex-col gap-4">
<div class="grid grid-cols-3 gap-4 items-center">
<app-key-value label="عنوان" [value]="business()?.name" />
<app-key-value label="کد اقتصادی" [value]="business()?.economic_code" />
<app-key-value label="صنف" [value]="business()?.guild?.name" />
</div>
</div>
@@ -27,9 +27,9 @@ export class ConsumerCustomerSaleInvoiceListComponent extends AbstractList<ICust
},
{
field: 'pos',
header: 'فروشگاه',
header: 'شعبه',
customDataModel(item: ICustomerSaleInvoicesResponse) {
return `${item.pos.complex.business_activity.name}، فروشگاه ${item.pos.complex.name}، پایانه‌ی فروش ${item.pos.name}`;
return `${item.pos.complex.business_activity.name}، شعبه ${item.pos.complex.name}، پایانه‌ی فروش ${item.pos.name}`;
},
},
{
@@ -43,7 +43,7 @@ export class ConsumerPosListComponent extends AbstractList<IPosResponse> {
},
{
field: 'complex',
header: 'عنوان فروشگاه',
header: 'عنوان شعبه',
type: 'nested',
nestedPath: 'complex.name',
},
@@ -26,9 +26,9 @@ export class ConsumerSaleInvoiceListComponent extends AbstractList<IConsumerSale
},
{
field: 'pos',
header: 'فروشگاه',
header: 'شعبه',
customDataModel(item: IConsumerSaleInvoicesResponse) {
return `${item.pos.complex.business_activity.name}، فروشگاه ${item.pos.complex.name}، پایانه‌ی فروش ${item.pos.name}`;
return `${item.pos.complex.business_activity.name}، شعبه ${item.pos.complex.name}، پایانه‌ی فروش ${item.pos.name}`;
},
},
{