ui update, init to consumer statistics and manage pos user types
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
<div class="flex flex-col gap-6">
|
||||
<app-card-data cardTitle="اطلاعات فاکتور" [editable]="false" [(editMode)]="editMode">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="grid grid-cols-3 gap-4 items-center">
|
||||
<app-key-value label="کد رهگیری" [value]="invoice()?.code" />
|
||||
<app-key-value label="تاریخ فاکتور" [value]="invoice()?.invoice_date" type="dateTime" />
|
||||
<app-key-value label="تاریخ ایجاد فاکتور" [value]="invoice()?.created_at" type="dateTime" />
|
||||
<app-key-value label="وضعیت صدور به سامانهی مودیان">
|
||||
<p-badge value="ارسال نشده" severity="danger" />
|
||||
</app-key-value>
|
||||
<div class="col-span-3">
|
||||
<app-key-value label="توضیحات" [value]="invoice()?.notes" />
|
||||
</div>
|
||||
</div>
|
||||
<p-divider align="center"> اطلاعات پرداخت </p-divider>
|
||||
<div class="grid grid-cols-3 gap-4 items-center">
|
||||
<app-key-value label="مجموع قابل پرداخت" [value]="invoice()?.total_amount" type="price" />
|
||||
@for (payment of invoice()?.payments; track $index) {
|
||||
<app-key-value
|
||||
[label]="
|
||||
`${payment.payment_method === 'SET_OF' ? 'تهاتر' : payment.payment_method === 'TERMINAL' ? 'پایانه' : 'نقدی'}`
|
||||
"
|
||||
[value]="payment.amount"
|
||||
type="price"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
<p-divider align="center"> اطلاعات صادر کننده </p-divider>
|
||||
<div class="grid grid-cols-3 gap-4 items-center">
|
||||
<app-key-value label="کسب و کار" [value]="invoice()?.pos!.complex.business_activity.name" />
|
||||
<app-key-value label="مجموعه" [value]="invoice()?.pos!.complex.name" />
|
||||
<app-key-value label="پایانهی فروش" [value]="invoice()?.pos!.name" />
|
||||
<app-key-value label="ایجاد کننده" [value]="invoice()?.account?.account?.username" />
|
||||
</div>
|
||||
|
||||
@if (variant !== "customer") {
|
||||
<p-divider align="center"> اطلاعات مشتری </p-divider>
|
||||
<div class="grid grid-cols-3 gap-4 items-center">
|
||||
@if (invoice()?.customer) {}
|
||||
<!-- <app-key-value label="کسب و کار" [value]="invoice()?.pos!.complex.business_activity.name" />
|
||||
<app-key-value label="مجموعه" [value]="invoice()?.pos!.complex.name" />
|
||||
<app-key-value label="پایانهی فروش" [value]="invoice()?.pos!.name" />
|
||||
<app-key-value label="ایجاد کننده" [value]="invoice()?.account?.account?.username" /> -->
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</app-card-data>
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
||||
import { Component, Input, signal } from '@angular/core';
|
||||
import { Badge } from 'primeng/badge';
|
||||
import { Divider } from 'primeng/divider';
|
||||
|
||||
export type TConsumerSaleInvoice = 'full' | 'customer' | 'pos';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-saleInvoice-shared',
|
||||
templateUrl: './single.component.html',
|
||||
imports: [AppCardComponent, KeyValueComponent, Badge, Divider],
|
||||
})
|
||||
export class ConsumerSaleInvoiceSharedComponent {
|
||||
@Input({ required: true }) loading!: boolean;
|
||||
@Input({ required: true }) invoice!: any;
|
||||
@Input() editable = false;
|
||||
@Input() variant: TConsumerSaleInvoice = 'full';
|
||||
|
||||
editMode = signal<boolean>(false);
|
||||
}
|
||||
@@ -31,6 +31,8 @@ export class LayoutComponent {
|
||||
});
|
||||
|
||||
ngOnInit() {
|
||||
console.log('first');
|
||||
|
||||
this.layoutService.setMenuItems(CONSUMER_MENU_ITEMS);
|
||||
this.store.getData();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerAccountsNamedRoutes } from '../constants';
|
||||
import { IAccountResponse } from '../models';
|
||||
import { AccountsService } from '../services/main.service';
|
||||
@@ -51,11 +51,9 @@ export class AccountStore extends EntityStore<IAccountResponse, AccountState> {
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerBusinessActivityNamedRoutes } from '../constants';
|
||||
import { IBusinessActivityResponse } from '../models';
|
||||
import { BusinessActivitiesService } from '../services/main.service';
|
||||
@@ -55,11 +55,9 @@ export class BusinessActivityStore extends EntityStore<
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerComplexesNamedRoutes } from '../constants/routes/complexes';
|
||||
import { IComplexResponse } from '../models';
|
||||
import { ConsumerComplexesService } from '../services/complexes.service';
|
||||
@@ -50,11 +50,9 @@ export class ConsumerComplexStore extends EntityStore<IComplexResponse, ComplexS
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerPosesNamedRoutes } from '../constants/routes/poses';
|
||||
import { IPosResponse } from '../models';
|
||||
import { ConsumerPosesService } from '../services/poses.service';
|
||||
@@ -51,11 +51,9 @@ export class PosStore extends EntityStore<IPosResponse, PosState> {
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Component, computed, effect, inject, signal } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
import { Button } from 'primeng/button';
|
||||
import { COOKIE_KEYS } from 'src/assets/constants';
|
||||
import { ConsumerPosFormComponent } from '../../components/poses/form.component';
|
||||
import { ConsumerSalesInvoicesComponent } from '../../components/salesInvoices/list.component';
|
||||
import { BusinessActivityStore } from '../../store/businessActivity.store';
|
||||
@@ -53,8 +54,8 @@ export class SuperAdminUserPosComponent {
|
||||
}
|
||||
|
||||
toPosLanding() {
|
||||
// this.cookieService.delete('posId', '/', 'localhost', false, 'Lax');
|
||||
this.cookieService.set('posId', this.posId(), {
|
||||
this.cookieService.set(COOKIE_KEYS.POS_ID, '', new Date());
|
||||
this.cookieService.set(COOKIE_KEYS.POS_ID, this.posId(), {
|
||||
sameSite: 'Lax', // or 'Strict' for same-site requests only
|
||||
secure: false,
|
||||
path: '/',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerCustomersNamedRoutes } from '../constants';
|
||||
import { ICustomerResponse } from '../models';
|
||||
import { CustomersService } from '../services/main.service';
|
||||
@@ -54,11 +54,9 @@ export class ConsumerCustomerStore extends EntityStore<ICustomerResponse, Consum
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerCustomerSaleInvoicesNamedRoutes } from '../constants/routes/saleInvoices';
|
||||
import { ICustomerSaleInvoicesResponse } from '../models';
|
||||
import { CustomerSaleInvoicesService } from '../services/saleInvoices.service';
|
||||
@@ -58,11 +58,9 @@ export class ConsumerCustomerSaleInvoiceStore extends EntityStore<
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<app-page-data-list
|
||||
pageTitle="آخرین فاکتورهای صادر شدهی امروز"
|
||||
[columns]="columns"
|
||||
emptyPlaceholderTitle="تا به این لحظه فاکتوری صادر نشده است."
|
||||
[items]="items()"
|
||||
[showDetails]="true"
|
||||
[loading]="loading()"
|
||||
(onDetails)="toSinglePage($event)"
|
||||
>
|
||||
<ng-template #moreActions>
|
||||
<a routerLink pButton [routerLink]="invoicesPageRoute" outlined>تمامی فاکتورها</a>
|
||||
</ng-template>
|
||||
</app-page-data-list>
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { consumerSaleInvoicesNamedRoutes } from '@/domains/consumer/modules/saleInvoices/constants';
|
||||
import { AbstractList } from '@/shared/abstractClasses';
|
||||
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
import { IStatisticsSaleInvoicesResponse } from '../../../models';
|
||||
import { CustomerStatisticsService } from '../../../services/main.service';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-statistics-latest-Invoices',
|
||||
templateUrl: './latest-Invoices.component.html',
|
||||
imports: [PageDataListComponent, ButtonDirective, RouterLink],
|
||||
})
|
||||
export class ConsumerStatisticsLatestInvoicesComponent extends AbstractList<IStatisticsSaleInvoicesResponse> {
|
||||
private readonly service = inject(CustomerStatisticsService);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
readonly invoicesPageRoute = consumerSaleInvoicesNamedRoutes.saleInvoices.meta.pagePath!();
|
||||
|
||||
override setColumns(): void {
|
||||
this.columns = [
|
||||
{ field: 'code', header: 'کد پیگیری' },
|
||||
{ field: 'total_amount', header: 'مجموع قیمت', type: 'price' },
|
||||
{
|
||||
field: 'created_at',
|
||||
header: 'تاریخ ایجاد',
|
||||
type: 'date',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
override getDataRequest() {
|
||||
return this.service.getInvoices();
|
||||
}
|
||||
|
||||
toSinglePage(invoice: IStatisticsSaleInvoicesResponse) {
|
||||
this.router.navigateByUrl(
|
||||
consumerSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(invoice.id),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
const baseUrl = '/api/v1/consumer/statistics';
|
||||
|
||||
export const CONSUMER_STATISTICS_API_ROUTES = {
|
||||
invoices: () => `${baseUrl}/invoices`,
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './apiRoutes';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './saleInvoices.io';
|
||||
@@ -0,0 +1,27 @@
|
||||
import ISummary from '@/core/models/summary';
|
||||
|
||||
export interface IStatisticsSaleInvoicesRawResponse {
|
||||
id: string;
|
||||
code: string;
|
||||
created_date: string;
|
||||
total_amount: string;
|
||||
pos: Pos;
|
||||
consumer_account: ConsumerAccount;
|
||||
created_at: string;
|
||||
}
|
||||
export interface IStatisticsSaleInvoicesResponse extends IStatisticsSaleInvoicesRawResponse {}
|
||||
|
||||
interface ConsumerAccount {
|
||||
role: string;
|
||||
account: {
|
||||
username: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface Pos extends ISummary {
|
||||
complex: Complex;
|
||||
}
|
||||
|
||||
interface Complex extends ISummary {
|
||||
business_activity: ISummary;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { IListingResponse } from '@/core/models/service.model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { CONSUMER_STATISTICS_API_ROUTES } from '../constants';
|
||||
import { IStatisticsSaleInvoicesRawResponse, IStatisticsSaleInvoicesResponse } from '../models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CustomerStatisticsService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private apiRoutes = CONSUMER_STATISTICS_API_ROUTES;
|
||||
|
||||
getInvoices(): Observable<IListingResponse<IStatisticsSaleInvoicesResponse>> {
|
||||
return this.http.get<IListingResponse<IStatisticsSaleInvoicesRawResponse>>(
|
||||
this.apiRoutes.invoices(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
<div class="flex items-center justify-center h-[100cqmin]">
|
||||
<span class="text-center"> به پنل کسب و کار خوش آمدید </span>
|
||||
<div class="grid grid-cols-2 gap-10">
|
||||
<div class="h-[300px] flex">
|
||||
<consumer-statistics-latest-Invoices class="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ConsumerStatisticsLatestInvoicesComponent } from '../components/statistics/latestInvoices/latest-Invoices.component';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-dashboard',
|
||||
templateUrl: './index.component.html',
|
||||
imports: [ConsumerStatisticsLatestInvoicesComponent],
|
||||
})
|
||||
export class DashboardComponent {
|
||||
constructor() {}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
@if (loading()) {
|
||||
<shared-page-loading />
|
||||
} @else {
|
||||
<router-outlet></router-outlet>
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
||||
import { Component, computed, inject, signal } from '@angular/core';
|
||||
import { ActivatedRoute, RouterOutlet } from '@angular/router';
|
||||
import { ConsumerSaleInvoiceStore } from '../store/main.store';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-customer-layout',
|
||||
templateUrl: './layout.component.html',
|
||||
imports: [PageLoadingComponent, RouterOutlet],
|
||||
})
|
||||
export class ConsumerCustomerLayoutComponent {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly store = inject(ConsumerSaleInvoiceStore);
|
||||
|
||||
readonly invoiceId = signal<string>(this.route.snapshot.paramMap.get('invoiceId')!);
|
||||
|
||||
readonly loading = computed(() => this.store.loading());
|
||||
|
||||
getData() {
|
||||
this.store.getData(this.invoiceId());
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<app-page-data-list
|
||||
[pageTitle]="'لیست فاکتورهای ایجاد شده'"
|
||||
[columns]="columns"
|
||||
emptyPlaceholderTitle="فاکتوری یافت نشد"
|
||||
[items]="items()"
|
||||
[loading]="loading()"
|
||||
[showDetails]="true"
|
||||
(onDetails)="toSinglePage($event)"
|
||||
/>
|
||||
@@ -0,0 +1,66 @@
|
||||
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
||||
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
||||
import {
|
||||
IColumn,
|
||||
PageDataListComponent,
|
||||
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||
import { Component, inject, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { consumerSaleInvoicesNamedRoutes } from '../constants/routes';
|
||||
import { IConsumerSaleInvoicesResponse } from '../models';
|
||||
import { ConsumerSaleInvoicesService } from '../services/main.service';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-saleInvoice-list',
|
||||
templateUrl: './list.component.html',
|
||||
imports: [PageDataListComponent],
|
||||
})
|
||||
export class ConsumerSaleInvoiceListComponent extends AbstractList<IConsumerSaleInvoicesResponse> {
|
||||
@Input() fullHeight?: boolean;
|
||||
@Input() header: IColumn[] = [
|
||||
{ field: 'code', header: 'کد رهگیری' },
|
||||
{
|
||||
field: 'total_amount',
|
||||
header: 'قیمت نهایی',
|
||||
type: 'price',
|
||||
},
|
||||
{
|
||||
field: 'pos',
|
||||
header: 'فروشگاه',
|
||||
customDataModel(item: IConsumerSaleInvoicesResponse) {
|
||||
return `${item.pos.complex.business_activity.name}، فروشگاه ${item.pos.complex.name}، پایانهی فروش ${item.pos.name}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'account',
|
||||
header: 'ایجاد شده توسط',
|
||||
type: 'nested',
|
||||
nestedPath: 'account.account.username',
|
||||
},
|
||||
{
|
||||
field: 'invoice_date',
|
||||
header: 'تاریخ فاکتور',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
field: 'created_at',
|
||||
header: 'تاریخ ایجاد',
|
||||
type: 'date',
|
||||
},
|
||||
];
|
||||
|
||||
private readonly service = inject(ConsumerSaleInvoicesService);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
override setColumns(): void {
|
||||
this.columns = this.header;
|
||||
}
|
||||
|
||||
override getDataRequest() {
|
||||
return this.service.getAll();
|
||||
}
|
||||
|
||||
toSinglePage(item: IConsumerSaleInvoicesResponse) {
|
||||
this.router.navigateByUrl(consumerSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(item.id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
const baseUrl = () => `/api/v1/consumer/sale-invoices`;
|
||||
|
||||
export const CONSUMER_SALE_INVOICES_API_ROUTES = {
|
||||
list: () => baseUrl(),
|
||||
single: (id: string) => `${baseUrl()}/${id}`,
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './apiRoutes';
|
||||
export * from './routes';
|
||||
@@ -0,0 +1,30 @@
|
||||
import { NamedRoutes } from '@/core';
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
export type TConsumerSaleInvoicesRouteNames = 'saleInvoices' | 'saleInvoice';
|
||||
|
||||
export const consumerSaleInvoicesNamedRoutes: NamedRoutes<TConsumerSaleInvoicesRouteNames> = {
|
||||
saleInvoices: {
|
||||
path: 'saleInvoices',
|
||||
loadComponent: () =>
|
||||
import('../../views/list.component').then((m) => m.ConsumerSaleInvoicesComponent),
|
||||
meta: {
|
||||
title: 'فاکتورهای صادر شده',
|
||||
pagePath: () => `/consumer/saleInvoices`,
|
||||
},
|
||||
},
|
||||
saleInvoice: {
|
||||
path: 'saleInvoices/:invoiceId',
|
||||
loadComponent: () =>
|
||||
import('../../views/single.component').then((m) => m.ConsumerSaleInvoiceComponent),
|
||||
meta: {
|
||||
title: 'فاکتور صادر شده',
|
||||
pagePath: (saleInvoiceId: string) => `/consumer/saleInvoices/${saleInvoiceId}`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const CONSUMER_SALE_INVOICES_ROUTES: Routes = [
|
||||
consumerSaleInvoicesNamedRoutes.saleInvoices,
|
||||
consumerSaleInvoicesNamedRoutes.saleInvoice,
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
export * from './io';
|
||||
@@ -0,0 +1,44 @@
|
||||
import ISummary from '@/core/models/summary';
|
||||
|
||||
export interface IConsumerSaleInvoicesRawResponse {
|
||||
id: string;
|
||||
code: string;
|
||||
invoice_date: string;
|
||||
notes?: string;
|
||||
total_amount: string;
|
||||
pos: Pos;
|
||||
account: ConsumerAccount;
|
||||
created_at: string;
|
||||
items_count: number;
|
||||
payments: Payments[];
|
||||
}
|
||||
export interface IConsumerSaleInvoicesResponse extends IConsumerSaleInvoicesRawResponse {}
|
||||
|
||||
interface ConsumerAccount {
|
||||
role: string;
|
||||
user: User;
|
||||
account: Account;
|
||||
}
|
||||
|
||||
interface Account {
|
||||
username: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
}
|
||||
|
||||
interface Pos extends ISummary {
|
||||
complex: Complex;
|
||||
}
|
||||
|
||||
interface Complex extends ISummary {
|
||||
business_activity: ISummary;
|
||||
}
|
||||
|
||||
interface Payments {
|
||||
amount: string;
|
||||
paid_at: string;
|
||||
payment_method: string;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { IPaginatedResponse } from '@/core/models/service.model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { CONSUMER_SALE_INVOICES_API_ROUTES } from '../constants';
|
||||
import { IConsumerSaleInvoicesRawResponse, IConsumerSaleInvoicesResponse } from '../models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ConsumerSaleInvoicesService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
private apiRoutes = CONSUMER_SALE_INVOICES_API_ROUTES;
|
||||
|
||||
getAll(): Observable<IPaginatedResponse<IConsumerSaleInvoicesResponse>> {
|
||||
return this.http.get<IPaginatedResponse<IConsumerSaleInvoicesRawResponse>>(
|
||||
this.apiRoutes.list(),
|
||||
);
|
||||
}
|
||||
getSingle(invoiceId: string): Observable<IConsumerSaleInvoicesResponse> {
|
||||
return this.http.get<IConsumerSaleInvoicesRawResponse>(this.apiRoutes.single(invoiceId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { computed, inject, Injectable } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { consumerSaleInvoicesNamedRoutes } from '../constants';
|
||||
import { IConsumerSaleInvoicesResponse } from '../models';
|
||||
import { ConsumerSaleInvoicesService } from '../services/main.service';
|
||||
|
||||
interface ConsumerSaleInvoiceState extends EntityState<IConsumerSaleInvoicesResponse> {
|
||||
breadcrumbItems: MenuItem[];
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ConsumerSaleInvoiceStore extends EntityStore<
|
||||
IConsumerSaleInvoicesResponse,
|
||||
ConsumerSaleInvoiceState
|
||||
> {
|
||||
private readonly service = inject(ConsumerSaleInvoicesService);
|
||||
constructor() {
|
||||
super({
|
||||
loading: false,
|
||||
error: null,
|
||||
entity: null,
|
||||
initialized: false,
|
||||
isRefreshing: false,
|
||||
breadcrumbItems: [],
|
||||
});
|
||||
}
|
||||
|
||||
breadcrumbItems = computed(() => this._state().breadcrumbItems);
|
||||
|
||||
private setBreadcrumb(invoiceId: string) {
|
||||
this.patchState({
|
||||
breadcrumbItems: [
|
||||
{
|
||||
...consumerSaleInvoicesNamedRoutes.saleInvoices.meta,
|
||||
routerLink: consumerSaleInvoicesNamedRoutes.saleInvoices.meta.pagePath!(),
|
||||
},
|
||||
{
|
||||
title: this.entity()?.code,
|
||||
routerLink: consumerSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(invoiceId),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
getData(invoiceId: string) {
|
||||
this.patchState({ loading: true });
|
||||
this.service
|
||||
.getSingle(invoiceId)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
this.patchState({ entity });
|
||||
this.setBreadcrumb(invoiceId);
|
||||
});
|
||||
}
|
||||
|
||||
override reset(): void {
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: null,
|
||||
entity: null,
|
||||
initialized: false,
|
||||
isRefreshing: false,
|
||||
breadcrumbItems: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './list.component';
|
||||
export * from './single.component';
|
||||
@@ -0,0 +1 @@
|
||||
<consumer-saleInvoice-list />
|
||||
@@ -0,0 +1,10 @@
|
||||
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
||||
import { Component } from '@angular/core';
|
||||
import { ConsumerSaleInvoiceListComponent } from '../components/list.component';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-saleInvoices',
|
||||
templateUrl: './list.component.html',
|
||||
imports: [ConsumerSaleInvoiceListComponent],
|
||||
})
|
||||
export class ConsumerSaleInvoicesComponent {}
|
||||
@@ -0,0 +1 @@
|
||||
<consumer-saleInvoice-shared [loading]="loading()" [invoice]="invoice" />
|
||||
@@ -0,0 +1,44 @@
|
||||
import { BreadcrumbService } from '@/core/services';
|
||||
import { ConsumerSaleInvoiceSharedComponent } from '@/domains/consumer/components/invoices/single.component';
|
||||
import pageParamsUtils from '@/utils/page-params.utils';
|
||||
import { Component, computed, effect, inject, signal } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ConsumerSaleInvoiceStore } from '../store/main.store';
|
||||
|
||||
@Component({
|
||||
selector: 'consumer-saleInvoice',
|
||||
templateUrl: './single.component.html',
|
||||
imports: [ConsumerSaleInvoiceSharedComponent],
|
||||
})
|
||||
export class ConsumerSaleInvoiceComponent {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly breadcrumbService = inject(BreadcrumbService);
|
||||
private readonly store = inject(ConsumerSaleInvoiceStore);
|
||||
|
||||
pageParams = computed(() => pageParamsUtils(this.route));
|
||||
invoiceId = signal<string>(this.pageParams()['invoiceId']);
|
||||
editMode = signal<boolean>(false);
|
||||
|
||||
readonly invoice = computed(() => this.store.entity());
|
||||
readonly loading = computed(() => this.store.loading());
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
if (this.invoice()?.id) {
|
||||
this.setBreadcrumb();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.getData();
|
||||
}
|
||||
|
||||
getData() {
|
||||
this.store.getData(this.invoiceId());
|
||||
}
|
||||
|
||||
setBreadcrumb() {
|
||||
this.breadcrumbService.setItems([...this.store.breadcrumbItems()]);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { Route } from '@angular/router';
|
||||
import { CONSUMER_ACCOUNTS_ROUTES } from './modules/accounts/constants';
|
||||
import { CONSUMER_BUSINESS_ACTIVITIES_ROUTES } from './modules/businessActivities/constants';
|
||||
import { CONSUMER_CUSTOMERS_ROUTES } from './modules/customers/constants';
|
||||
import { CONSUMER_SALE_INVOICES_ROUTES } from './modules/saleInvoices/constants';
|
||||
|
||||
export const CONSUMER_ROUTES = {
|
||||
path: 'consumer',
|
||||
@@ -15,5 +16,6 @@ export const CONSUMER_ROUTES = {
|
||||
...CONSUMER_ACCOUNTS_ROUTES,
|
||||
...CONSUMER_BUSINESS_ACTIVITIES_ROUTES,
|
||||
...CONSUMER_CUSTOMERS_ROUTES,
|
||||
...CONSUMER_SALE_INVOICES_ROUTES,
|
||||
],
|
||||
} as Route;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EntityState, EntityStore } from '@/core/state';
|
||||
import { LayoutService } from '@/layout/service/layout.service';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { catchError, finalize, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs';
|
||||
import { IConsumerInfoResponse } from '../models';
|
||||
import { ConsumerService } from '../services/main.service';
|
||||
|
||||
@@ -32,11 +32,9 @@ export class ConsumerStore extends EntityStore<IConsumerInfoResponse, ConsumerSt
|
||||
finalize(() => {
|
||||
this.patchState({ loading: false });
|
||||
}),
|
||||
catchError(() => {
|
||||
this.patchState({
|
||||
error: '',
|
||||
});
|
||||
return throwError('');
|
||||
catchError((error) => {
|
||||
this.setError(error);
|
||||
throw error;
|
||||
}),
|
||||
)
|
||||
.subscribe((entity) => {
|
||||
|
||||
Reference in New Issue
Block a user