feat: refactor form components and improve invoice printing logic; enhance checkbox functionality and loading state management
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
import { brandingConfig } from '@/branding/branding.config';
|
||||
import { Component, computed, signal } from '@angular/core';
|
||||
import { ButtonDirective } from 'primeng/button';
|
||||
|
||||
@Component({
|
||||
selector: 'pos-about-page',
|
||||
templateUrl: './root.component.html',
|
||||
imports: [ButtonDirective],
|
||||
})
|
||||
export class PosAboutPageComponent {
|
||||
// private readonly swUpdate = inject(SwUpdate);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@if (!loading()) {
|
||||
<form [formGroup]="form" (submit)="submit()">
|
||||
<app-checkbox [control]="form.controls.business_name" name="business_name" label="نمایش عنوان کسبوکار" />
|
||||
<app-checkbox [control]="form.controls.complex_name" name="complex_name" label="نمایش عنوان شعبه" />
|
||||
@@ -26,5 +27,6 @@
|
||||
<app-checkbox [control]="form.controls.show_payment_info" name="show_payment_info" label="نمایش جزییات پرداخت" />
|
||||
<app-checkbox [control]="form.controls.show_items" name="show_items" label="نمایش کالاهای خریداری شده" />
|
||||
|
||||
<app-form-footer-actions (onSubmit)="submit()" (onCancel)="close()" />
|
||||
<app-form-footer-actions (onCancel)="close()" />
|
||||
</form>
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AbstractForm } from '@/shared/abstractClasses';
|
||||
import { AppCheckboxComponent } from '@/shared/components/checkbox/checkbox.component';
|
||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { IPosConfigPrintRequestPayload, IPosConfigPrintResponse } from './models';
|
||||
import { PosConfigPrintService } from './services/main.service';
|
||||
@@ -17,6 +17,8 @@ export class PosConfigPrintFormComponent extends AbstractForm<
|
||||
> {
|
||||
private readonly service = inject(PosConfigPrintService);
|
||||
|
||||
loading = signal(true);
|
||||
|
||||
initForm = () => {
|
||||
const form = this.fb.group({
|
||||
business_name: [true, []],
|
||||
@@ -40,8 +42,18 @@ export class PosConfigPrintFormComponent extends AbstractForm<
|
||||
|
||||
form = this.initForm();
|
||||
|
||||
submitForm() {
|
||||
override async ngOnInit() {
|
||||
this.loading.set(true);
|
||||
const initialValues = await this.service.get();
|
||||
console.log('initialValues', initialValues);
|
||||
|
||||
this.form.patchValue(initialValues);
|
||||
this.loading.set(false);
|
||||
}
|
||||
|
||||
override submitForm() {
|
||||
const formValue = this.form.value as IPosConfigPrintRequestPayload;
|
||||
this.toastService.success({ text: 'تغییرات با موفقیت اعمال شد.' });
|
||||
return this.service.submit(formValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export abstract class AbstractForm<
|
||||
@Output() onClose = new EventEmitter<void>();
|
||||
|
||||
protected readonly fb = inject(FormBuilder);
|
||||
private readonly toastService = inject(ToastService);
|
||||
protected readonly toastService = inject(ToastService);
|
||||
constructor() {}
|
||||
|
||||
abstract form: ReturnType<FormBuilder['group']>;
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-3">
|
||||
<p-checkBox [formControl]="control" [name]="name" [inputId]="name" binary class="shrink-0"> </p-checkBox>
|
||||
<input
|
||||
[id]="name"
|
||||
type="checkbox"
|
||||
[name]="name"
|
||||
[disabled]="disabled"
|
||||
[checked]="checked"
|
||||
(change)="onChange($any($event.target).checked)"
|
||||
class="h-5 w-5 shrink-0 cursor-pointer rounded border border-surface-300 accent-primary disabled:cursor-not-allowed disabled:opacity-60"
|
||||
/>
|
||||
<uikit-label [name]="name"> {{ label }} </uikit-label>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,12 +2,11 @@ import { Maybe } from '@/core';
|
||||
import { UikitLabelComponent } from '@/uikit';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { Checkbox } from 'primeng/checkbox';
|
||||
|
||||
@Component({
|
||||
selector: 'app-checkbox',
|
||||
templateUrl: 'checkbox.component.html',
|
||||
imports: [Checkbox, UikitLabelComponent],
|
||||
imports: [UikitLabelComponent],
|
||||
})
|
||||
export class AppCheckboxComponent {
|
||||
@Input({ required: true }) control!: FormControl<Maybe<any>>;
|
||||
@@ -17,4 +16,14 @@ export class AppCheckboxComponent {
|
||||
@Input() size?: 'small' | 'large';
|
||||
@Input() showErrors = true;
|
||||
@Input() hint?: string;
|
||||
|
||||
get checked() {
|
||||
return this.control.value === 'true' || this.control.value === true;
|
||||
}
|
||||
|
||||
onChange(checked: boolean) {
|
||||
this.control.setValue(checked ? 'true' : 'false');
|
||||
this.control.markAsDirty();
|
||||
this.control.markAsTouched();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,73 @@ export interface ISaleInvoiceFullResponse extends ISaleInvoiceFullRawResponse {}
|
||||
|
||||
interface Item {
|
||||
id: string;
|
||||
good: ISummary;
|
||||
good_id: string;
|
||||
service_id: null;
|
||||
quantity: string;
|
||||
measure_unit_code: string;
|
||||
measure_unit_text: string;
|
||||
sku_code: string;
|
||||
unit_price: string;
|
||||
discount: string;
|
||||
total_amount: string;
|
||||
notes?: string;
|
||||
payload: Payload;
|
||||
good_snapshot: Goodsnapshot;
|
||||
good: GoodSummary;
|
||||
}
|
||||
interface GoodSummary {
|
||||
name: string;
|
||||
barcode?: string;
|
||||
image_url?: string;
|
||||
category: Category;
|
||||
}
|
||||
|
||||
interface Category {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
image_url?: string;
|
||||
is_default_guild_good: boolean;
|
||||
guild_id: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
interface Goodsnapshot {
|
||||
good: Good;
|
||||
}
|
||||
|
||||
interface Good {
|
||||
id: string;
|
||||
sku: Sku;
|
||||
name: string;
|
||||
barcode?: string;
|
||||
category: ISummary;
|
||||
image_url: string;
|
||||
local_sku?: string;
|
||||
measure_unit: MeasureUnit;
|
||||
pricing_model: string;
|
||||
base_sale_price: string;
|
||||
}
|
||||
|
||||
interface MeasureUnit {
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Sku {
|
||||
id: string;
|
||||
VAT: string;
|
||||
code: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Payload {
|
||||
karat: string;
|
||||
wages: number;
|
||||
profit: number;
|
||||
commission: number;
|
||||
}
|
||||
|
||||
interface Payment {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<button
|
||||
pButton
|
||||
type="button"
|
||||
label="چاپ کن"
|
||||
label="چاپ"
|
||||
icon="pi pi-print"
|
||||
outlined
|
||||
size="small"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Maybe } from '@/core';
|
||||
import { NativeBridgeService } from '@/core/services';
|
||||
import { ToastService } from '@/core/services/toast.service';
|
||||
import { PosConfigPrintService } from '@/domains/pos/modules/configs/components/print/services/main.service';
|
||||
import { PosInfoStore } from '@/domains/pos/store';
|
||||
import { CatalogTaxProviderStatusTagComponent } from '@/shared/catalog';
|
||||
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||
import { PriceMaskDirective } from '@/shared/directives';
|
||||
import { UikitEmptyStateComponent } from '@/uikit';
|
||||
import { formatWithCurrency } from '@/utils';
|
||||
import {
|
||||
Component,
|
||||
computed,
|
||||
@@ -49,6 +51,8 @@ export class SharedSaleInvoiceSingleViewComponent {
|
||||
private readonly nativeBridge = inject(NativeBridgeService);
|
||||
private readonly posInfoStore = inject(PosInfoStore);
|
||||
private readonly toastService = inject(ToastService);
|
||||
//TODO: below service Must be transform from pos to shared.
|
||||
private readonly service = inject(PosConfigPrintService);
|
||||
|
||||
@Input({ required: true }) loading!: boolean;
|
||||
@Input() invoice!: Maybe<ISaleInvoiceFullResponse>;
|
||||
@@ -67,38 +71,45 @@ export class SharedSaleInvoiceSingleViewComponent {
|
||||
return '';
|
||||
});
|
||||
|
||||
printInvoice = () => {
|
||||
try {
|
||||
preparePrint = async () => {
|
||||
if (this.invoice) {
|
||||
this.nativeBridge.print([
|
||||
const mustPrintConfig = await this.service.get();
|
||||
|
||||
const defaultPrintItems = [
|
||||
{
|
||||
title: 'اطلاعات صورتحساب',
|
||||
items: [
|
||||
{
|
||||
label: 'شماره منحصر به فرد مالیاتی',
|
||||
value: 'this.invoice',
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
label: 'شماره صورتحساب',
|
||||
value: this.invoice.code,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
label: 'موضوع صورتحساب',
|
||||
value: 'this.invoice',
|
||||
show: mustPrintConfig.invoice_template ?? true,
|
||||
},
|
||||
{
|
||||
label: 'نوع صورتحساب',
|
||||
value: 'this.invoice',
|
||||
show: mustPrintConfig.invoice_template,
|
||||
},
|
||||
{
|
||||
label: 'تاریخ و ساعت',
|
||||
value: this.invoice.invoice_date,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
label: 'وضعیت صورتحساب مالیاتی',
|
||||
value: this.invoice.status.translate,
|
||||
show: mustPrintConfig.show_payment_info ?? true,
|
||||
},
|
||||
],
|
||||
].filter((item) => item.show),
|
||||
},
|
||||
{
|
||||
title: `اطلاعات فروشنده`,
|
||||
@@ -106,20 +117,24 @@ export class SharedSaleInvoiceSingleViewComponent {
|
||||
{
|
||||
label: 'عنوان فروشگاه',
|
||||
value: this.invoice.pos.complex.business_activity.name,
|
||||
show: mustPrintConfig.business_name,
|
||||
},
|
||||
{
|
||||
label: 'عنوان شعبه',
|
||||
value: this.invoice.pos.complex.name,
|
||||
show: mustPrintConfig.complex_name,
|
||||
},
|
||||
{
|
||||
label: 'عنوان پایانه فروش',
|
||||
value: this.invoice.pos.name,
|
||||
show: mustPrintConfig.pos_name,
|
||||
},
|
||||
{
|
||||
label: 'شماره اقتصادی',
|
||||
value: 'this.invoice.pos.complex.business_activity.economic_code',
|
||||
show: mustPrintConfig.economic_code,
|
||||
},
|
||||
],
|
||||
].filter((item) => item.show),
|
||||
},
|
||||
{
|
||||
title: `اطلاعات خریدار`,
|
||||
@@ -132,6 +147,7 @@ export class SharedSaleInvoiceSingleViewComponent {
|
||||
? this.invoice.customer.legal?.company_name
|
||||
: `${this.invoice.customer.individual?.first_name} ${this.invoice.customer.individual?.last_name}`
|
||||
: this.invoice.unknown_customer?.name) || '-',
|
||||
show: mustPrintConfig.customer_name,
|
||||
},
|
||||
{
|
||||
label: 'شماره اقتصادی',
|
||||
@@ -141,10 +157,85 @@ export class SharedSaleInvoiceSingleViewComponent {
|
||||
? this.invoice.customer.legal?.economic_code
|
||||
: this.invoice.customer.individual?.economic_code || '-'
|
||||
: '-') || '-',
|
||||
show: mustPrintConfig.customer_economic_code,
|
||||
},
|
||||
].filter((item) => item.show),
|
||||
},
|
||||
].filter((item) => item.items.length);
|
||||
|
||||
if (mustPrintConfig.show_items) {
|
||||
for (let item of this.invoice.items) {
|
||||
defaultPrintItems.push({
|
||||
title: 'جزییات صورتحساب',
|
||||
items: [
|
||||
{
|
||||
label: 'شرح',
|
||||
value: item.good.name,
|
||||
show: mustPrintConfig.items?.name,
|
||||
},
|
||||
{
|
||||
label: 'شناسه کالا / خدمت',
|
||||
value: item.sku_code,
|
||||
show: mustPrintConfig.items?.sku,
|
||||
},
|
||||
{
|
||||
label: 'تعداد / مقدار',
|
||||
value: `${item.quantity} ${item.measure_unit_text}`,
|
||||
show: mustPrintConfig.items?.quantity,
|
||||
},
|
||||
{
|
||||
label: 'قیمت واحد',
|
||||
value: formatWithCurrency(item.unit_price),
|
||||
show: mustPrintConfig.items?.base_amount,
|
||||
},
|
||||
{
|
||||
label: 'اجرت',
|
||||
value: formatWithCurrency(item.payload.wages),
|
||||
show:
|
||||
mustPrintConfig.items?.wage && item.good_snapshot.good.pricing_model === 'GOLD',
|
||||
},
|
||||
{
|
||||
label: 'سود',
|
||||
value: formatWithCurrency(item.payload.wages),
|
||||
show:
|
||||
mustPrintConfig.items?.profit && item.good_snapshot.good.pricing_model === 'GOLD',
|
||||
},
|
||||
{
|
||||
label: 'حقالعمل',
|
||||
value: formatWithCurrency(item.payload.commission),
|
||||
show:
|
||||
mustPrintConfig.items?.commission &&
|
||||
item.good_snapshot.good.pricing_model === 'GOLD',
|
||||
},
|
||||
{
|
||||
label: 'مالیات بر ارزش افزوده',
|
||||
value: 'item.good.tax',
|
||||
show: mustPrintConfig.items?.tax,
|
||||
},
|
||||
{
|
||||
label: 'تخفیف',
|
||||
value: formatWithCurrency(item.discount),
|
||||
show: mustPrintConfig.items?.discount,
|
||||
},
|
||||
{
|
||||
label: 'مبلغ کل',
|
||||
value: formatWithCurrency(item.total_amount),
|
||||
show: mustPrintConfig.items?.total_amount,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
return defaultPrintItems;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
printInvoice = async () => {
|
||||
try {
|
||||
const printItems = await this.preparePrint();
|
||||
if (printItems) {
|
||||
this.nativeBridge.print(printItems);
|
||||
}
|
||||
} catch (error) {
|
||||
return this.toastService.error({
|
||||
|
||||
Reference in New Issue
Block a user