diff --git a/src/app/modules/bankAccounts/views/list.component.html b/src/app/modules/bankAccounts/views/list.component.html
index a93a2fc..75693da 100644
--- a/src/app/modules/bankAccounts/views/list.component.html
+++ b/src/app/modules/bankAccounts/views/list.component.html
@@ -9,6 +9,7 @@
[loading]="loading()"
[showDetails]="true"
(onAdd)="openAddForm()"
+ (onDetails)="toDetails($event)"
/>
diff --git a/src/app/modules/bankAccounts/views/list.component.ts b/src/app/modules/bankAccounts/views/list.component.ts
index b316d2e..6f015fa 100644
--- a/src/app/modules/bankAccounts/views/list.component.ts
+++ b/src/app/modules/bankAccounts/views/list.component.ts
@@ -3,6 +3,7 @@ import {
PageDataListComponent,
} from '@/shared/components/pageDataList/page-data-list.component';
import { Component, signal } from '@angular/core';
+import { Router } from '@angular/router';
import { BankAccountFormComponent } from '../components/form.component';
import { IBankAccountsResponse } from '../models';
import { BankAccountsService } from '../services/main.service';
@@ -13,7 +14,10 @@ import { BankAccountsService } from '../services/main.service';
imports: [PageDataListComponent, BankAccountFormComponent],
})
export class BankAccountsComponent {
- constructor(private service: BankAccountsService) {
+ constructor(
+ private service: BankAccountsService,
+ private router: Router,
+ ) {
this.getData();
}
@@ -78,4 +82,8 @@ export class BankAccountsComponent {
openAddForm() {
this.visibleForm.set(true);
}
+
+ toDetails(item: IBankAccountsResponse) {
+ this.router.navigate(['/bankAccounts', item.id]);
+ }
}
diff --git a/src/app/modules/inventories/views/single.component.html b/src/app/modules/inventories/views/single.component.html
index fb19f79..fa3ab8b 100644
--- a/src/app/modules/inventories/views/single.component.html
+++ b/src/app/modules/inventories/views/single.component.html
@@ -11,21 +11,21 @@
pButton
type="button"
label="نقاط فروش"
- icon="pi pi-plus"
+ icon="pi pi-shop"
[routerLink]="['/inventories', inventoryId, 'pos-accounts']"
>
diff --git a/src/app/modules/pos/components/order/held-order-item.component.html b/src/app/modules/pos/components/order/held-order-item.component.html
new file mode 100644
index 0000000..d8ca28f
--- /dev/null
+++ b/src/app/modules/pos/components/order/held-order-item.component.html
@@ -0,0 +1,28 @@
+
+
+ سفارش #{{ heldOrder.orderNumber }}
+
+ {{ heldOrder.orderItems.length }} کالا -
+
+
+
+
+
+
+
+
diff --git a/src/app/modules/pos/components/order/held-order-item.component.ts b/src/app/modules/pos/components/order/held-order-item.component.ts
new file mode 100644
index 0000000..0e92c53
--- /dev/null
+++ b/src/app/modules/pos/components/order/held-order-item.component.ts
@@ -0,0 +1,57 @@
+import { ToastService } from '@/core/services/toast.service';
+import { ConfirmationDialogService } from '@/shared/components/confirmationDialog/confirmation-dialog.service';
+import { PriceMaskDirective } from '@/shared/directives';
+import { Component, EventEmitter, Input, Output, signal } from '@angular/core';
+import { ButtonDirective } from 'primeng/button';
+import { IPosHeldOrderResponse } from '../../models';
+import { PosService } from '../../services/main.service';
+
+@Component({
+ selector: 'app-held-order-item',
+ templateUrl: './held-order-item.component.html',
+ imports: [PriceMaskDirective, ButtonDirective],
+})
+export class HeldOrderItemComponent {
+ @Input() heldOrder!: IPosHeldOrderResponse;
+ @Input() posId!: number;
+
+ @Output() onCancel = new EventEmitter();
+ @Output() onLoad = new EventEmitter();
+
+ constructor(
+ private readonly posService: PosService,
+ private readonly confirmationService: ConfirmationDialogService,
+ private readonly toastService: ToastService,
+ ) {}
+
+ actionLoading = signal(false);
+
+ cancelHeldOrder(heldOrderId: number) {
+ this.confirmationService.confirm({
+ message: `آیا از لغو سفارش شمارهی #${this.heldOrder.orderNumber} اطمینان دارید؟`,
+ header: 'لغو سفارش موقت',
+ acceptLabel: 'بله',
+ rejectLabel: 'خیر',
+ accept: () => {
+ this.actionLoading.set(true);
+ this.posService.cancelOrder(this.posId, heldOrderId).subscribe({
+ next: () => {
+ this.onCancel.emit(heldOrderId);
+ this.actionLoading.set(false);
+ this.toastService.success({
+ text: `سفارش شمارهی #${this.heldOrder.orderNumber} با موفقیت لغو شد.`,
+ });
+ },
+ error: () => {
+ this.actionLoading.set(false);
+ },
+ });
+ },
+ reject: () => {},
+ });
+ }
+
+ loadHeldOrder(heldOrderId: number) {
+ this.onLoad.emit(heldOrderId);
+ }
+}
diff --git a/src/app/modules/pos/components/order/held-orders.component.html b/src/app/modules/pos/components/order/held-orders.component.html
new file mode 100644
index 0000000..f92faf7
--- /dev/null
+++ b/src/app/modules/pos/components/order/held-orders.component.html
@@ -0,0 +1,19 @@
+
+
+
+
+ سفارشهای نگهداشته شده
+
+
+ @if (!heldOrders()?.length) {
+
+ هیچ سفارش نگهداشته شدهای وجود ندارد.
+
+ } @else {
+
+ @for (heldOrder of heldOrders(); track heldOrder.id) {
+
+ }
+
+ }
+
diff --git a/src/app/modules/pos/components/order/held-orders.component.ts b/src/app/modules/pos/components/order/held-orders.component.ts
new file mode 100644
index 0000000..02d6014
--- /dev/null
+++ b/src/app/modules/pos/components/order/held-orders.component.ts
@@ -0,0 +1,41 @@
+import { Maybe } from '@/core';
+import { Component, Input, signal } from '@angular/core';
+import { IPosHeldOrderResponse } from '../../models';
+import { PosService } from '../../services/main.service';
+import { HeldOrderItemComponent } from './held-order-item.component';
+
+@Component({
+ selector: 'app-held-orders',
+ templateUrl: './held-orders.component.html',
+ imports: [HeldOrderItemComponent],
+})
+export class HeldOrdersComponent {
+ @Input() posId!: number;
+
+ constructor(private readonly posService: PosService) {}
+
+ heldOrders = signal>(null);
+ loading = signal(false);
+
+ ngOnInit() {
+ this.getHeldOrders();
+ }
+
+ getHeldOrders() {
+ this.loading.set(true);
+ this.posService.getHeldOrders(this.posId).subscribe({
+ next: (res) => {
+ this.heldOrders.set(res.data);
+ this.loading.set(false);
+ },
+ error: () => {
+ this.loading.set(false);
+ },
+ });
+ }
+
+ removeHeldOrder(orderId: number) {
+ const currentOrders = this.heldOrders() || [];
+ this.heldOrders.set(currentOrders.filter((order) => order.id !== orderId));
+ }
+}
diff --git a/src/app/modules/pos/components/order/order-card.component.html b/src/app/modules/pos/components/order/order-card.component.html
index 9ba6f10..a88abfa 100644
--- a/src/app/modules/pos/components/order/order-card.component.html
+++ b/src/app/modules/pos/components/order/order-card.component.html
@@ -1,4 +1,8 @@
+
+
diff --git a/src/app/modules/pos/components/order/order-card.component.ts b/src/app/modules/pos/components/order/order-card.component.ts
index c4e62ee..afb1ffa 100644
--- a/src/app/modules/pos/components/order/order-card.component.ts
+++ b/src/app/modules/pos/components/order/order-card.component.ts
@@ -3,13 +3,14 @@ import { CustomersSelectComponent } from '@/modules/customers/components/select/
import { ICustomerResponse } from '@/modules/customers/models';
import { PriceMaskDirective } from '@/shared/directives';
import { UikitCounterComponent } from '@/uikit';
-import { Component, computed, signal } from '@angular/core';
+import { Component, computed, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ButtonDirective } from 'primeng/button';
import { InplaceModule } from 'primeng/inplace';
import { InputNumber } from 'primeng/inputnumber';
import images from 'src/assets/images';
import { POSStore } from '../../store';
+import { HeldOrdersComponent } from './held-orders.component';
import { POSOrderPriceInfoCardComponent } from './price-info-card.component';
@Component({
@@ -24,13 +25,18 @@ import { POSOrderPriceInfoCardComponent } from './price-info-card.component';
FormsModule,
InplaceModule,
InputNumber,
+ HeldOrdersComponent,
],
})
export class PosOrderCardComponent {
- constructor(private store: POSStore) {
+ private store = inject(POSStore);
+
+ constructor() {
this.selectedCustomer.set(this.store.selectedCustomer());
}
+ posId = this.store.posId;
+
placeholderImage = images.placeholders.default;
inOrderProducts = computed(() => this.store.inOrderProducts());
@@ -64,4 +70,8 @@ export class PosOrderCardComponent {
submit() {
this.store.submitOrder();
}
+
+ submitAndPay() {
+ this.store.submitOrder();
+ }
}
diff --git a/src/app/modules/pos/constants/apiRoutes/index.ts b/src/app/modules/pos/constants/apiRoutes/index.ts
index 475439c..32080c9 100644
--- a/src/app/modules/pos/constants/apiRoutes/index.ts
+++ b/src/app/modules/pos/constants/apiRoutes/index.ts
@@ -4,5 +4,10 @@ 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`,
+ submitOrder: (posId: number) => `${baseUrl}/${posId}/orders`,
+ heldOrders: (posId: number) => `${baseUrl}/${posId}/orders/held`,
+ order: (posId: number, orderId: number) => `${baseUrl}/${posId}/orders/${orderId}`,
+ cancelOrder: (posId: number, orderId: number) => `${baseUrl}/${posId}/orders/${orderId}/cancel`,
+ rejectOrder: (posId: number, orderId: number) => `${baseUrl}/${posId}/orders/${orderId}/reject`,
+ confirmOrder: (posId: number, orderId: number) => `${baseUrl}/${posId}/orders/${orderId}/confirm`,
};
diff --git a/src/app/modules/pos/models/io.ts b/src/app/modules/pos/models/io.ts
index ff265ec..52eafd8 100644
--- a/src/app/modules/pos/models/io.ts
+++ b/src/app/modules/pos/models/io.ts
@@ -36,3 +36,39 @@ export interface IPosOrderRequest {
customerId?: number;
items: IPosOrderItem[];
}
+
+export interface IPosOrderRawResponse {
+ id: number;
+ orderNumber: string;
+ totalAmount: number;
+ paidAmount: number;
+ status: string;
+ description?: string;
+ createdAt: string;
+ updatedAt: string;
+ deletedAt?: string;
+ customer?: {
+ id: number;
+ firstName: string;
+ lastName: string;
+ };
+ orderItems: {
+ product: IPosProductSummary;
+ count: number;
+ unitPrice: number;
+ totalPrice: number;
+ }[];
+}
+
+export interface IPosOrderResponse extends Omit {
+ customer?: {
+ id: number;
+ name: string;
+ };
+}
+export interface IPosHeldOrderRawResponse extends IPosOrderResponse {}
+export interface IPosHeldOrderResponse extends IPosHeldOrderRawResponse {}
+
+export interface IPosOrderConfirmedResponse {
+ invoiceId: number;
+}
diff --git a/src/app/modules/pos/models/types.ts b/src/app/modules/pos/models/types.ts
index 580ab92..b6cda48 100644
--- a/src/app/modules/pos/models/types.ts
+++ b/src/app/modules/pos/models/types.ts
@@ -5,7 +5,7 @@ export interface IPosProductSummary {
name: string;
sku: string;
salePrice: string;
- category: ICategorySummary;
+ categoryId: number;
}
interface ICategorySummary {
diff --git a/src/app/modules/pos/services/main.service.ts b/src/app/modules/pos/services/main.service.ts
index 06d464b..72716fc 100644
--- a/src/app/modules/pos/services/main.service.ts
+++ b/src/app/modules/pos/services/main.service.ts
@@ -43,4 +43,24 @@ export class PosService {
submitOrder(posId: number, payload: IPosOrderRequest): Observable {
return this.http.post(this.apiRoutes.submitOrder(posId), payload);
}
+
+ getHeldOrders(posId: number): Observable> {
+ return this.http.get>(this.apiRoutes.heldOrders(posId));
+ }
+
+ getOrder(posId: number, orderId: number): Observable {
+ return this.http.get(this.apiRoutes.order(posId, orderId));
+ }
+
+ cancelOrder(posId: number, orderId: number): Observable {
+ return this.http.post(this.apiRoutes.cancelOrder(posId, orderId), {});
+ }
+
+ rejectOrder(posId: number, orderId: number): Observable {
+ return this.http.post(this.apiRoutes.rejectOrder(posId, orderId), {});
+ }
+
+ confirmOrder(posId: number, orderId: number): Observable {
+ return this.http.post(this.apiRoutes.confirmOrder(posId, orderId), {});
+ }
}
diff --git a/src/app/modules/pos/store/index.ts b/src/app/modules/pos/store/index.ts
index 140a37a..39b2395 100644
--- a/src/app/modules/pos/store/index.ts
+++ b/src/app/modules/pos/store/index.ts
@@ -1,7 +1,7 @@
import { Maybe } from '@/core';
import { ICustomerResponse } from '@/modules/customers/models';
import { computed, Inject, Injectable, InjectionToken, signal } from '@angular/core';
-import { map } from 'rxjs';
+import { map, of } from 'rxjs';
import { IPosInfoResponse, IPosProductCategoriesResponse, IPosStockResponse } from '../models';
import { IPosInOrderProduct } from '../models/types';
import { PosService } from '../services/main.service';
@@ -66,7 +66,7 @@ export class POSStore {
return this.state$().stock;
}
return this.state$().stock?.filter(
- (s) => s.product.category.id === this.state$().activeProductCategory,
+ (s) => s.product.categoryId === this.state$().activeProductCategory,
);
});
@@ -258,6 +258,15 @@ export class POSStore {
unitPrice: item.unitPrice,
})),
};
- this.service.submitOrder(this.posId, orderPayload).subscribe();
+ return this.service.submitOrder(this.posId, orderPayload).subscribe({
+ next: (res) => {
+ this.resetInOrderProducts();
+ this.setSelectedCustomer(null);
+ return of(res);
+ },
+ error: (err) => {
+ return of(err);
+ },
+ });
}
}
diff --git a/src/app/modules/suppliers/views/invoice.component.ts b/src/app/modules/suppliers/views/invoice.component.ts
index 7678465..f53fd84 100644
--- a/src/app/modules/suppliers/views/invoice.component.ts
+++ b/src/app/modules/suppliers/views/invoice.component.ts
@@ -1,7 +1,6 @@
import { CatalogPurchaseReceiptStatusTagComponent } from '@/shared/catalog';
import { KeyValueComponent } from '@/shared/components';
import { InnerPagesHeaderComponent } from '@/shared/components/innerPagesHeader/inner-pages-header.component';
-import { PurchaseReceiptPaymentWrapperComponent } from '@/shared/components/purchaseReceiptPayment/wrapper.component';
import { PriceMaskDirective } from '@/shared/directives';
import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@@ -21,7 +20,6 @@ import { SupplierInvoiceStore, SupplierStore } from '../store';
SupplierInvoicePayFormComponent,
InvoicePaymentsComponent,
PriceMaskDirective,
- PurchaseReceiptPaymentWrapperComponent,
],
})
export class SupplierInvoiceComponent {