refactor: replace economic code fields with individual and legal variants, add equal length validation
This commit is contained in:
@@ -68,6 +68,13 @@ export class FormErrorsService {
|
|||||||
const info = errors['invalidUsername'];
|
const info = errors['invalidUsername'];
|
||||||
out.push({ key: 'invalidUsername', message: info.message ?? `${label} معتبر نیست.` });
|
out.push({ key: 'invalidUsername', message: info.message ?? `${label} معتبر نیست.` });
|
||||||
}
|
}
|
||||||
|
if (errors['equalLength']) {
|
||||||
|
const info = errors['equalLength'];
|
||||||
|
out.push({
|
||||||
|
key: 'equalLength',
|
||||||
|
message: `تعداد کاراکترهای ${label} باید برابر با ${info.length} باشد.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (errors['invalidFiscalId']) {
|
if (errors['invalidFiscalId']) {
|
||||||
const info = errors['invalidFiscalId'];
|
const info = errors['invalidFiscalId'];
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
|
||||||
|
|
||||||
|
export function equalLengthValidator(length: number): ValidatorFn {
|
||||||
|
return (control: AbstractControl): ValidationErrors | null => {
|
||||||
|
const v = control.value;
|
||||||
|
if (v === null || v === undefined || v === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const normalized = String(v);
|
||||||
|
|
||||||
|
return normalized.length !== length
|
||||||
|
? {
|
||||||
|
equalLength: {
|
||||||
|
length,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from './equalLength.validator';
|
||||||
export * from './fiscal-id.validator';
|
export * from './fiscal-id.validator';
|
||||||
export * from './greater.validator';
|
export * from './greater.validator';
|
||||||
export * from './iban.validator';
|
export * from './iban.validator';
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
[modal]="true"
|
[modal]="true"
|
||||||
[style]="{ width: '500px' }"
|
[style]="{ width: '500px' }"
|
||||||
[closable]="true"
|
[closable]="true"
|
||||||
(onHide)="close()"
|
(onHide)="close()">
|
||||||
>
|
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<field-name [control]="form.controls.name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<field-economic-code [control]="form.controls.economic_code" />
|
<field-individual-economic-code [control]="form.controls.economic_code" />
|
||||||
<field-fiscal-id [control]="form.controls.fiscal_id" />
|
<field-fiscal-id [control]="form.controls.fiscal_id" />
|
||||||
<field-partner-token [control]="form.controls.partner_token" />
|
<field-partner-token [control]="form.controls.partner_token" />
|
||||||
<field-invoice-number-sequence [control]="form.controls.invoice_number_sequence" [min]="1" />
|
<field-invoice-number-sequence [control]="form.controls.invoice_number_sequence" [min]="1" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
||||||
import {
|
import {
|
||||||
EconomicCodeComponent,
|
|
||||||
FiscalIdComponent,
|
FiscalIdComponent,
|
||||||
|
IndividualEconomicCodeComponent,
|
||||||
NameComponent,
|
NameComponent,
|
||||||
PartnerTokenComponent,
|
PartnerTokenComponent,
|
||||||
} from '@/shared/components';
|
} from '@/shared/components';
|
||||||
@@ -22,7 +22,7 @@ import { BusinessActivitiesService } from '../services/main.service';
|
|||||||
SharedDialogComponent,
|
SharedDialogComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
NameComponent,
|
NameComponent,
|
||||||
EconomicCodeComponent,
|
IndividualEconomicCodeComponent,
|
||||||
PartnerTokenComponent,
|
PartnerTokenComponent,
|
||||||
InvoiceNumberSequenceComponent,
|
InvoiceNumberSequenceComponent,
|
||||||
FiscalIdComponent,
|
FiscalIdComponent,
|
||||||
@@ -37,11 +37,11 @@ export class ConsumerBusinessActivityFormComponent extends AbstractFormDialog<
|
|||||||
|
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
name: fieldControl.name(this.initialValues?.name || ''),
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
economic_code: fieldControl.economic_code(this.initialValues?.economic_code || ''),
|
economic_code: fieldControl.individual_economic_code(this.initialValues?.economic_code || ''),
|
||||||
fiscal_id: fieldControl.fiscal_id(this.initialValues?.fiscal_id || ''),
|
fiscal_id: fieldControl.fiscal_id(this.initialValues?.fiscal_id || ''),
|
||||||
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
||||||
invoice_number_sequence: fieldControl.invoice_number_sequence(
|
invoice_number_sequence: fieldControl.invoice_number_sequence(
|
||||||
this.initialValues?.invoice_number_sequence || 1,
|
this.initialValues?.invoice_number_sequence || 1
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<field-name [control]="form.controls.name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<field-economic-code [control]="form.controls.economic_code" />
|
<field-individual-economic-code [control]="form.controls.economic_code" />
|
||||||
<field-fiscal-id [control]="form.controls.fiscal_id" />
|
<field-fiscal-id [control]="form.controls.fiscal_id" />
|
||||||
<field-invoice-number-sequence [control]="form.controls.invoice_number_sequence" />
|
<field-invoice-number-sequence [control]="form.controls.invoice_number_sequence" />
|
||||||
<field-partner-token [control]="form.controls.partner_token" />
|
<field-partner-token [control]="form.controls.partner_token" />
|
||||||
|
|||||||
+5
-5
@@ -1,8 +1,8 @@
|
|||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import {
|
import {
|
||||||
EconomicCodeComponent,
|
|
||||||
FiscalIdComponent,
|
FiscalIdComponent,
|
||||||
GuildIdComponent,
|
GuildIdComponent,
|
||||||
|
IndividualEconomicCodeComponent,
|
||||||
LicenseStartsAtComponent,
|
LicenseStartsAtComponent,
|
||||||
NameComponent,
|
NameComponent,
|
||||||
PartnerTokenComponent,
|
PartnerTokenComponent,
|
||||||
@@ -22,7 +22,7 @@ import { PartnerConsumerBusinessActivitiesService } from '../../services/busines
|
|||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
NameComponent,
|
NameComponent,
|
||||||
EconomicCodeComponent,
|
IndividualEconomicCodeComponent,
|
||||||
FiscalIdComponent,
|
FiscalIdComponent,
|
||||||
PartnerTokenComponent,
|
PartnerTokenComponent,
|
||||||
GuildIdComponent,
|
GuildIdComponent,
|
||||||
@@ -44,10 +44,10 @@ export class ConsumerBusinessActivitiesFormComponent extends AbstractForm<
|
|||||||
initForm = () => {
|
initForm = () => {
|
||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
name: fieldControl.name(this.initialValues?.name || ''),
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
economic_code: fieldControl.economic_code(this.initialValues?.economic_code || ''),
|
economic_code: fieldControl.individual_economic_code(this.initialValues?.economic_code || ''),
|
||||||
fiscal_id: fieldControl.fiscal_id(this.initialValues?.fiscal_id || ''),
|
fiscal_id: fieldControl.fiscal_id(this.initialValues?.fiscal_id || ''),
|
||||||
invoice_number_sequence: fieldControl.invoice_number_sequence(
|
invoice_number_sequence: fieldControl.invoice_number_sequence(
|
||||||
parseInt(this.initialValues?.invoice_number_sequence || '1'),
|
parseInt(this.initialValues?.invoice_number_sequence || '1')
|
||||||
),
|
),
|
||||||
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
||||||
guild_id: fieldControl.guild_id(this.initialValues?.guild?.id || ''),
|
guild_id: fieldControl.guild_id(this.initialValues?.guild?.id || ''),
|
||||||
@@ -63,7 +63,7 @@ export class ConsumerBusinessActivitiesFormComponent extends AbstractForm<
|
|||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: fieldControl.license_starts_at('')[1],
|
validators: fieldControl.license_starts_at('')[1],
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,11 @@
|
|||||||
<ng-template #topbarCenter>
|
<ng-template #topbarCenter>
|
||||||
@if (posInfo()) {
|
@if (posInfo()) {
|
||||||
<a [routerLink]="homeRouteLink" class="flex flex-col items-center justify-center gap-2">
|
<a [routerLink]="homeRouteLink" class="flex flex-col items-center justify-center gap-2">
|
||||||
<div class="w-8 h-8">
|
<div class="h-8 w-8">
|
||||||
<img
|
<img
|
||||||
[src]="posInfo()?.partner?.logo_url ?? placeholderLogo"
|
[src]="posInfo()?.partner?.logo_url ?? placeholderLogo"
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
class="w-full h-full object-cover rounded-md bg-surface-card"
|
class="bg-surface-card h-full w-full rounded-md object-cover" />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<span class="text-base font-semibold">{{ posInfo()?.partner?.name }}</span>
|
<span class="text-base font-semibold">{{ posInfo()?.partner?.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
|
|
||||||
<ng-template #topbarEnd>
|
<ng-template #topbarEnd>
|
||||||
<div class="">
|
<div class="">
|
||||||
<p-menu #menu [model]="profileMenuItems" [popup]="true" />
|
<p-menu #menu [model]="profileMenuItems" [popup]="true" appendTo="body" />
|
||||||
<p-button (click)="menu.toggle($event)" icon="pi pi-user" outlined size="large" />
|
<p-button (click)="menu.toggle($event)" icon="pi pi-user" outlined size="large" />
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@@ -57,11 +56,11 @@
|
|||||||
<pos-choose-cards class="h-full" (onChoose)="onChoosePos()" />
|
<pos-choose-cards class="h-full" (onChoose)="onChoosePos()" />
|
||||||
}
|
}
|
||||||
@default {
|
@default {
|
||||||
<div class="h-full w-full flex items-center justify-center">
|
<div class="flex h-full w-full items-center justify-center">
|
||||||
<p-card class="border border-surface-border">
|
<p-card class="border-surface-border border">
|
||||||
<div class="flex flex-col gap-2 items-center justify-between shrink-0">
|
<div class="flex shrink-0 flex-col items-center justify-between gap-2">
|
||||||
<i class="pi pi-exclamation-triangle text-6xl! mb-3 text-error" aria-hidden="true"></i>
|
<i class="pi pi-exclamation-triangle text-error mb-3 text-6xl!" aria-hidden="true"></i>
|
||||||
<span class="text-xl font-semibold mb-2 text-error block"> عدم دسترسی </span>
|
<span class="text-error mb-2 block text-xl font-semibold"> عدم دسترسی </span>
|
||||||
<p class="inline-block text-base">متاسفانه امکان دسترسی برای کاربر شما فراهم نیست</p>
|
<p class="inline-block text-base">متاسفانه امکان دسترسی برای کاربر شما فراهم نیست</p>
|
||||||
<button pButton outlined severity="danger" class="mt-5 w-32" (click)="logout()">خروج</button>
|
<button pButton outlined severity="danger" class="mt-5 w-32" (click)="logout()">خروج</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+3
-2
@@ -1,9 +1,10 @@
|
|||||||
<form [formGroup]="form" (submit)="submit()">
|
<form [formGroup]="form" (submit)="submit()">
|
||||||
|
<p-message severity="info"> وارد کردن شماره اقتصادی و یا کد ملی به همراه کد پستی الزامی است. </p-message>
|
||||||
|
|
||||||
<field-first-name [control]="form.controls.first_name" />
|
<field-first-name [control]="form.controls.first_name" />
|
||||||
<field-last-name [control]="form.controls.last_name" />
|
<field-last-name [control]="form.controls.last_name" />
|
||||||
<field-mobile-number [control]="form.controls.mobile_number" />
|
<field-individual-economic-code [control]="form.controls.economic_code" />
|
||||||
<field-national-id [control]="form.controls.national_id" />
|
<field-national-id [control]="form.controls.national_id" />
|
||||||
<field-economic-code [control]="form.controls.economic_code" />
|
|
||||||
<field-postal-code [control]="form.controls.postal_code" />
|
<field-postal-code [control]="form.controls.postal_code" />
|
||||||
|
|
||||||
<app-form-footer-actions submitLabel="ثبت مشتری و ادامه" (onCancel)="close()" (onSubmit)="submit()" />
|
<app-form-footer-actions submitLabel="ثبت مشتری و ادامه" (onCancel)="close()" (onSubmit)="submit()" />
|
||||||
|
|||||||
+60
-15
@@ -1,9 +1,8 @@
|
|||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import {
|
import {
|
||||||
EconomicCodeComponent,
|
|
||||||
FirstNameComponent,
|
FirstNameComponent,
|
||||||
|
IndividualEconomicCodeComponent,
|
||||||
LastNameComponent,
|
LastNameComponent,
|
||||||
MobileNumberComponent,
|
|
||||||
NationalIdComponent,
|
NationalIdComponent,
|
||||||
PostalCodeComponent,
|
PostalCodeComponent,
|
||||||
} from '@/shared/components';
|
} from '@/shared/components';
|
||||||
@@ -11,7 +10,8 @@ import { FormFooterActionsComponent } from '@/shared/components/formFooterAction
|
|||||||
import { fieldControl } from '@/shared/constants';
|
import { fieldControl } from '@/shared/constants';
|
||||||
import { CustomerType } from '@/shared/localEnum/constants/customerTypes';
|
import { CustomerType } from '@/shared/localEnum/constants/customerTypes';
|
||||||
import { Component, computed, inject } from '@angular/core';
|
import { Component, computed, inject } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { AbstractControl, ReactiveFormsModule, ValidationErrors } from '@angular/forms';
|
||||||
|
import { Message } from 'primeng/message';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { IIndividualCustomer } from '../../../models/customer';
|
import { IIndividualCustomer } from '../../../models/customer';
|
||||||
import { PosLandingStore } from '../../../store/main.store';
|
import { PosLandingStore } from '../../../store/main.store';
|
||||||
@@ -24,10 +24,10 @@ import { PosLandingStore } from '../../../store/main.store';
|
|||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
FirstNameComponent,
|
FirstNameComponent,
|
||||||
LastNameComponent,
|
LastNameComponent,
|
||||||
NationalIdComponent,
|
IndividualEconomicCodeComponent,
|
||||||
EconomicCodeComponent,
|
|
||||||
MobileNumberComponent,
|
|
||||||
PostalCodeComponent,
|
PostalCodeComponent,
|
||||||
|
Message,
|
||||||
|
NationalIdComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CustomerIndividualFormComponent extends AbstractForm<
|
export class CustomerIndividualFormComponent extends AbstractForm<
|
||||||
@@ -38,14 +38,56 @@ export class CustomerIndividualFormComponent extends AbstractForm<
|
|||||||
costumerInfo = computed(() => this.store.customer().info?.customer_individual);
|
costumerInfo = computed(() => this.store.customer().info?.customer_individual);
|
||||||
|
|
||||||
override showSuccessMessage = false;
|
override showSuccessMessage = false;
|
||||||
form = this.fb.group({
|
private readonly identityOrEconomicCodeValidator = (
|
||||||
first_name: fieldControl.first_name(this.costumerInfo()?.first_name || ''),
|
control: AbstractControl
|
||||||
last_name: fieldControl.last_name(this.costumerInfo()?.last_name || ''),
|
): ValidationErrors | null => {
|
||||||
national_id: fieldControl.national_id(this.costumerInfo()?.national_id || ''),
|
const economicCode = control.get('economic_code')?.value;
|
||||||
postal_code: fieldControl.postal_code(this.costumerInfo()?.postal_code || ''),
|
const nationalId = control.get('national_id')?.value;
|
||||||
economic_code: fieldControl.economic_code(this.costumerInfo()?.economic_code || ''),
|
const postalCode = control.get('postal_code')?.value;
|
||||||
mobile_number: fieldControl.mobile_number(this.costumerInfo()?.mobile_number || ''),
|
|
||||||
});
|
const hasEconomicCode = !!String(economicCode ?? '').trim();
|
||||||
|
const hasNationalId = !!String(nationalId ?? '').trim();
|
||||||
|
const hasPostalCode = !!String(postalCode ?? '').trim();
|
||||||
|
|
||||||
|
const isValid = hasEconomicCode || (hasNationalId && hasPostalCode);
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
return { identityOrEconomicCodeRequired: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
form = this.fb.group(
|
||||||
|
{
|
||||||
|
first_name: fieldControl.first_name(this.costumerInfo()?.first_name || '', false),
|
||||||
|
last_name: fieldControl.last_name(this.costumerInfo()?.last_name || '', false),
|
||||||
|
economic_code: fieldControl.individual_economic_code(
|
||||||
|
this.costumerInfo()?.economic_code || '',
|
||||||
|
false
|
||||||
|
),
|
||||||
|
national_id: fieldControl.national_id(this.costumerInfo()?.national_id || '', false),
|
||||||
|
postal_code: fieldControl.postal_code(this.costumerInfo()?.postal_code || '', false),
|
||||||
|
},
|
||||||
|
{ validators: this.identityOrEconomicCodeValidator }
|
||||||
|
);
|
||||||
|
|
||||||
|
override submit() {
|
||||||
|
this.form.markAllAsTouched();
|
||||||
|
this.form.updateValueAndValidity({ onlySelf: false, emitEvent: false });
|
||||||
|
|
||||||
|
if (this.form.hasError('identityOrEconomicCodeRequired')) {
|
||||||
|
this.toastService.warn({
|
||||||
|
text: 'وارد کردن شماره اقتصادی و یا کد ملی به همراه کد پستی الزامی است.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.form.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.submit();
|
||||||
|
}
|
||||||
|
|
||||||
override submitForm() {
|
override submitForm() {
|
||||||
return new Observable<IIndividualCustomer>((observer) => {
|
return new Observable<IIndividualCustomer>((observer) => {
|
||||||
@@ -54,7 +96,10 @@ export class CustomerIndividualFormComponent extends AbstractForm<
|
|||||||
customer_id: '',
|
customer_id: '',
|
||||||
type: CustomerType.INDIVIDUAL,
|
type: CustomerType.INDIVIDUAL,
|
||||||
info: {
|
info: {
|
||||||
customer_individual: info,
|
customer_individual: {
|
||||||
|
...info,
|
||||||
|
economic_code: info.economic_code ? info.economic_code.toString() : undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return observer.next(info);
|
return observer.next(info);
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<form [formGroup]="form" (submit)="submit()">
|
<form [formGroup]="form" (submit)="submit()">
|
||||||
<app-input [control]="form.controls.company_name" name="company_name" label="نام مجموعه" />
|
<p-message severity="info" icon="pi pi-info-circle">
|
||||||
<app-input [control]="form.controls.registration_number" name="registration_number" label="شماره ثبت" />
|
وارد کردن شماره اقتصادی و یا شناسه ملی به همراه کد پستی الزامی است.
|
||||||
<app-input [control]="form.controls.economic_code" name="economic_code" label="کد اقتصادی" maxlength="11" />
|
</p-message>
|
||||||
<app-input [control]="form.controls.postal_code" name="postal_code" label="کد پستی" type="postalCode" />
|
<field-name [control]="form.controls.name" name="name" label="نام مجموعه" />
|
||||||
|
<field-legal-economic-code [control]="form.controls.economic_code" />
|
||||||
|
<field-registration-number [control]="form.controls.registration_number" />
|
||||||
|
<field-postal-code [control]="form.controls.postal_code" />
|
||||||
|
|
||||||
<app-form-footer-actions submitLabel="ثبت مشتری و ادامه" (onCancel)="close()" (onSubmit)="submit()" />
|
<app-form-footer-actions submitLabel="ثبت مشتری و ادامه" (onCancel)="close()" (onSubmit)="submit()" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import { postalCodeValidator } from '@/core/validators';
|
|
||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import { InputComponent } from '@/shared/components';
|
import {
|
||||||
|
LegalEconomicCodeComponent,
|
||||||
|
NameComponent,
|
||||||
|
PostalCodeComponent,
|
||||||
|
RegistrationNumberComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
|
import { fieldControl } from '@/shared/constants';
|
||||||
import { CustomerType } from '@/shared/localEnum/constants/customerTypes';
|
import { CustomerType } from '@/shared/localEnum/constants/customerTypes';
|
||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { AbstractControl, ReactiveFormsModule, ValidationErrors } from '@angular/forms';
|
||||||
|
import { Message } from 'primeng/message';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ILegalCustomer } from '../../../models/customer';
|
import { ILegalCustomer } from '../../../models/customer';
|
||||||
import { PosLandingStore } from '../../../store/main.store';
|
import { PosLandingStore } from '../../../store/main.store';
|
||||||
@@ -12,31 +18,76 @@ import { PosLandingStore } from '../../../store/main.store';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'pos-customer-legal-form',
|
selector: 'pos-customer-legal-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, InputComponent, FormFooterActionsComponent],
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
FormFooterActionsComponent,
|
||||||
|
LegalEconomicCodeComponent,
|
||||||
|
NameComponent,
|
||||||
|
RegistrationNumberComponent,
|
||||||
|
PostalCodeComponent,
|
||||||
|
Message,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class CustomerLegalFormComponent extends AbstractForm<ILegalCustomer, ILegalCustomer> {
|
export class CustomerLegalFormComponent extends AbstractForm<ILegalCustomer, ILegalCustomer> {
|
||||||
private readonly store = inject(PosLandingStore);
|
private readonly store = inject(PosLandingStore);
|
||||||
|
|
||||||
override showSuccessMessage = false;
|
override showSuccessMessage = false;
|
||||||
|
|
||||||
form = this.fb.group({
|
private readonly registrationOrEconomicCodeValidator = (
|
||||||
company_name: [
|
control: AbstractControl
|
||||||
this.store.customer().info?.customer_legal?.company_name || '',
|
): ValidationErrors | null => {
|
||||||
[Validators.required],
|
const economicCode = control.get('economic_code')?.value;
|
||||||
],
|
const registrationNumber = control.get('registration_number')?.value;
|
||||||
registration_number: [
|
const postalCode = control.get('postal_code')?.value;
|
||||||
this.store.customer().info?.customer_legal?.registration_number || '',
|
|
||||||
[Validators.required],
|
const hasEconomicCode = !!String(economicCode ?? '').trim();
|
||||||
],
|
const hasRegistrationNumber = !!String(registrationNumber ?? '').trim();
|
||||||
economic_code: [
|
const hasPostalCode = !!String(postalCode ?? '').trim();
|
||||||
this.store.customer().info?.customer_legal?.economic_code || '',
|
|
||||||
[Validators.required],
|
const isValid = hasEconomicCode || (hasRegistrationNumber && hasPostalCode);
|
||||||
],
|
|
||||||
postal_code: [
|
if (!isValid) {
|
||||||
this.store.customer().info?.customer_legal?.postal_code || '',
|
return { registrationOrEconomicCodeRequired: true };
|
||||||
[postalCodeValidator()],
|
}
|
||||||
],
|
|
||||||
});
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
form = this.fb.group(
|
||||||
|
{
|
||||||
|
name: fieldControl.name(this.store.customer().info?.customer_legal?.name || ''),
|
||||||
|
economic_code: fieldControl.legal_economic_code(
|
||||||
|
this.store.customer().info?.customer_legal?.economic_code || '',
|
||||||
|
false
|
||||||
|
),
|
||||||
|
registration_number: fieldControl.registration_number(
|
||||||
|
this.store.customer().info?.customer_legal?.registration_number || '',
|
||||||
|
false
|
||||||
|
),
|
||||||
|
postal_code: fieldControl.postal_code(
|
||||||
|
this.store.customer().info?.customer_legal?.postal_code || '',
|
||||||
|
false
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ validators: this.registrationOrEconomicCodeValidator }
|
||||||
|
);
|
||||||
|
|
||||||
|
override submit() {
|
||||||
|
this.form.markAllAsTouched();
|
||||||
|
this.form.updateValueAndValidity({ onlySelf: false, emitEvent: false });
|
||||||
|
|
||||||
|
if (this.form.hasError('registrationOrEconomicCodeRequired')) {
|
||||||
|
this.toastService.warn({
|
||||||
|
text: 'وارد کردن شماره اقتصادی و یا شناسه ملی به همراه کد پستی الزامی است.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.form.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.submit();
|
||||||
|
}
|
||||||
|
|
||||||
override submitForm() {
|
override submitForm() {
|
||||||
return new Observable<ILegalCustomer>((observer) => {
|
return new Observable<ILegalCustomer>((observer) => {
|
||||||
@@ -45,7 +96,10 @@ export class CustomerLegalFormComponent extends AbstractForm<ILegalCustomer, ILe
|
|||||||
customer_id: '',
|
customer_id: '',
|
||||||
type: CustomerType.LEGAL,
|
type: CustomerType.LEGAL,
|
||||||
info: {
|
info: {
|
||||||
customer_legal: info,
|
customer_legal: {
|
||||||
|
...info,
|
||||||
|
economic_code: info.economic_code ? info.economic_code.toString() : undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return observer.next(info);
|
return observer.next(info);
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import { PosOrderSectionComponent } from './order-section.component';
|
|||||||
imports: [SharedLightBottomsheetComponent, PosOrderSectionComponent],
|
imports: [SharedLightBottomsheetComponent, PosOrderSectionComponent],
|
||||||
})
|
})
|
||||||
export class PosOrderSectionDialogComponent extends AbstractDialog {
|
export class PosOrderSectionDialogComponent extends AbstractDialog {
|
||||||
@Output() onCloseInvoiceBottomSheet = new EventEmitter();
|
@Output() onAddMoreGoods = new EventEmitter();
|
||||||
@Output() onSubmitOrder = new EventEmitter();
|
@Output() onSubmit = new EventEmitter();
|
||||||
|
|
||||||
closeInvoiceBottomSheet = () => {
|
closeInvoiceBottomSheet = () => {
|
||||||
this.onCloseInvoiceBottomSheet.emit();
|
this.onAddMoreGoods.emit();
|
||||||
};
|
};
|
||||||
submitOrder = () => {
|
submitOrder = () => {
|
||||||
this.onSubmitOrder.emit();
|
this.onSubmit.emit();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export class PosOrderSectionComponent {
|
|||||||
customerNameToShow = `${info?.customer_individual ? info?.customer_individual.first_name + ' ' + info?.customer_individual.last_name : '-----'} (نوع اول)`;
|
customerNameToShow = `${info?.customer_individual ? info?.customer_individual.first_name + ' ' + info?.customer_individual.last_name : '-----'} (نوع اول)`;
|
||||||
break;
|
break;
|
||||||
case 'LEGAL':
|
case 'LEGAL':
|
||||||
customerNameToShow = `${info?.customer_legal?.company_name || '-----'} (نوع اول)`;
|
customerNameToShow = `${info?.customer_legal?.name || '-----'} (نوع اول)`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +85,8 @@ export class PosOrderSectionComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submitAndPay() {
|
submitAndPay() {
|
||||||
|
console.log('submitAndPay');
|
||||||
|
|
||||||
this.onSubmit.emit();
|
this.onSubmit.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
export interface IIndividualCustomer {
|
export interface IIndividualCustomer {
|
||||||
first_name: string;
|
first_name?: string;
|
||||||
last_name: string;
|
last_name?: string;
|
||||||
national_id: string;
|
national_id?: string;
|
||||||
postal_code: string;
|
postal_code?: string;
|
||||||
mobile_number: string;
|
economic_code?: string;
|
||||||
economic_code: string;
|
|
||||||
is_favorite?: boolean;
|
is_favorite?: boolean;
|
||||||
}
|
}
|
||||||
export interface ILegalCustomer {
|
export interface ILegalCustomer {
|
||||||
company_name: string;
|
name?: string;
|
||||||
economic_code: string;
|
economic_code?: string;
|
||||||
registration_number: string;
|
registration_number?: string;
|
||||||
postal_code: string;
|
postal_code?: string;
|
||||||
is_favorite?: boolean;
|
is_favorite?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -4,11 +4,10 @@
|
|||||||
[modal]="true"
|
[modal]="true"
|
||||||
[style]="{ width: '500px' }"
|
[style]="{ width: '500px' }"
|
||||||
[closable]="true"
|
[closable]="true"
|
||||||
(onHide)="close()"
|
(onHide)="close()">
|
||||||
>
|
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<field-name [control]="form.controls.name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<field-economic-code [control]="form.controls.economic_code" />
|
<field-individual-economic-code [control]="form.controls.economic_code" />
|
||||||
<field-fiscal-id [control]="form.controls.fiscal_id" />
|
<field-fiscal-id [control]="form.controls.fiscal_id" />
|
||||||
<field-partner-token [control]="form.controls.partner_token" />
|
<field-partner-token [control]="form.controls.partner_token" />
|
||||||
<field-guild-id [control]="form.controls.guild_id" />
|
<field-guild-id [control]="form.controls.guild_id" />
|
||||||
|
|||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
||||||
import {
|
import {
|
||||||
EconomicCodeComponent,
|
|
||||||
FiscalIdComponent,
|
FiscalIdComponent,
|
||||||
GuildIdComponent,
|
GuildIdComponent,
|
||||||
|
IndividualEconomicCodeComponent,
|
||||||
NameComponent,
|
NameComponent,
|
||||||
PartnerTokenComponent,
|
PartnerTokenComponent,
|
||||||
} from '@/shared/components';
|
} from '@/shared/components';
|
||||||
@@ -22,7 +22,7 @@ import { AdminConsumerBusinessActivitiesService } from '../../services/businessA
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
SharedDialogComponent,
|
SharedDialogComponent,
|
||||||
NameComponent,
|
NameComponent,
|
||||||
EconomicCodeComponent,
|
IndividualEconomicCodeComponent,
|
||||||
FiscalIdComponent,
|
FiscalIdComponent,
|
||||||
PartnerTokenComponent,
|
PartnerTokenComponent,
|
||||||
GuildIdComponent,
|
GuildIdComponent,
|
||||||
@@ -41,7 +41,7 @@ export class ConsumerBusinessActivitiesFormComponent extends AbstractFormDialog<
|
|||||||
initForm = () => {
|
initForm = () => {
|
||||||
return this.fb.group({
|
return this.fb.group({
|
||||||
name: fieldControl.name(this.initialValues?.name || ''),
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
economic_code: fieldControl.economic_code(this.initialValues?.economic_code || ''),
|
economic_code: fieldControl.individual_economic_code(this.initialValues?.economic_code || ''),
|
||||||
fiscal_id: fieldControl.fiscal_id(this.initialValues?.fiscal_id || ''),
|
fiscal_id: fieldControl.fiscal_id(this.initialValues?.fiscal_id || ''),
|
||||||
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ export * from './code.component';
|
|||||||
export * from './company_name.component';
|
export * from './company_name.component';
|
||||||
export * from './description.component';
|
export * from './description.component';
|
||||||
export * from './device_id.component';
|
export * from './device_id.component';
|
||||||
export * from './economic_code.component';
|
|
||||||
export * from './email.component';
|
export * from './email.component';
|
||||||
export * from './first_name.component';
|
export * from './first_name.component';
|
||||||
export * from './fiscal_id.component';
|
export * from './fiscal_id.component';
|
||||||
export * from './guild_id.component';
|
export * from './guild_id.component';
|
||||||
|
export * from './individual_economic_code.component';
|
||||||
export * from './invoice_templates.component';
|
export * from './invoice_templates.component';
|
||||||
export * from './last_name.component';
|
export * from './last_name.component';
|
||||||
|
export * from './legal_economic_code.component';
|
||||||
export * from './legal_name.component';
|
export * from './legal_name.component';
|
||||||
export * from './license_starts_at.component';
|
export * from './license_starts_at.component';
|
||||||
export * from './mobile.component';
|
export * from './mobile.component';
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { InputComponent } from '../input/input.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'field-individual-economic-code',
|
||||||
|
template: `<app-input
|
||||||
|
label="شماره اقتصادی"
|
||||||
|
[control]="control"
|
||||||
|
[name]="name"
|
||||||
|
type="number"
|
||||||
|
[length]="14"
|
||||||
|
/>`,
|
||||||
|
imports: [ReactiveFormsModule, InputComponent],
|
||||||
|
})
|
||||||
|
export class IndividualEconomicCodeComponent {
|
||||||
|
@Input({ required: true }) control = new FormControl<string>('');
|
||||||
|
@Input() name = 'individual_economic_code';
|
||||||
|
}
|
||||||
+10
-4
@@ -3,11 +3,17 @@ import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|||||||
import { InputComponent } from '../input/input.component';
|
import { InputComponent } from '../input/input.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'field-economic-code',
|
selector: 'field-legal-economic-code',
|
||||||
template: `<app-input label="کد اقتصادی" [control]="control" [name]="name" type="number" />`,
|
template: `<app-input
|
||||||
|
label="شماره اقتصادی"
|
||||||
|
[control]="control"
|
||||||
|
[name]="name"
|
||||||
|
type="number"
|
||||||
|
[length]="11"
|
||||||
|
/>`,
|
||||||
imports: [ReactiveFormsModule, InputComponent],
|
imports: [ReactiveFormsModule, InputComponent],
|
||||||
})
|
})
|
||||||
export class EconomicCodeComponent {
|
export class LegalEconomicCodeComponent {
|
||||||
@Input({ required: true }) control = new FormControl<string>('');
|
@Input({ required: true }) control = new FormControl<string>('');
|
||||||
@Input() name = 'economic_code';
|
@Input() name = 'legal_economic_code';
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import { PosInfoStore } from '@/domains/pos/store';
|
|||||||
import {
|
import {
|
||||||
CatalogInvoiceTypeTagComponent,
|
CatalogInvoiceTypeTagComponent,
|
||||||
CatalogTaxProviderStatusTagComponent,
|
CatalogTaxProviderStatusTagComponent,
|
||||||
|
TspProviderResponseStatus,
|
||||||
} from '@/shared/catalog';
|
} from '@/shared/catalog';
|
||||||
import { CatalogInvoiceSettlementTypeTagComponent } from '@/shared/catalog/invoiceSettlementType';
|
import { CatalogInvoiceSettlementTypeTagComponent } from '@/shared/catalog/invoiceSettlementType';
|
||||||
import {
|
import {
|
||||||
@@ -87,6 +88,7 @@ export class SharedSaleInvoiceSingleViewComponent {
|
|||||||
|
|
||||||
@Output() onRefresh = new EventEmitter<void>();
|
@Output() onRefresh = new EventEmitter<void>();
|
||||||
@Output() onSendToTsp = new EventEmitter<Observable<any>>();
|
@Output() onSendToTsp = new EventEmitter<Observable<any>>();
|
||||||
|
@Output() onResendToTsp = new EventEmitter<Observable<any>>();
|
||||||
@Output() onInquiry = new EventEmitter<Observable<any>>();
|
@Output() onInquiry = new EventEmitter<Observable<any>>();
|
||||||
|
|
||||||
@ViewChild('totalAmount', { static: false }) totalAmount!: TemplateRef<any>;
|
@ViewChild('totalAmount', { static: false }) totalAmount!: TemplateRef<any>;
|
||||||
@@ -102,6 +104,7 @@ export class SharedSaleInvoiceSingleViewComponent {
|
|||||||
this.showBackFromSale = this.showBackFromSale.bind(this);
|
this.showBackFromSale = this.showBackFromSale.bind(this);
|
||||||
this.printInvoice = this.printInvoice.bind(this);
|
this.printInvoice = this.printInvoice.bind(this);
|
||||||
this.send = this.send.bind(this);
|
this.send = this.send.bind(this);
|
||||||
|
this.resend = this.resend.bind(this);
|
||||||
this.inquiry = this.inquiry.bind(this);
|
this.inquiry = this.inquiry.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +119,9 @@ export class SharedSaleInvoiceSingleViewComponent {
|
|||||||
send() {
|
send() {
|
||||||
this.onSendToTsp.emit();
|
this.onSendToTsp.emit();
|
||||||
}
|
}
|
||||||
|
resend() {
|
||||||
|
this.onResendToTsp.emit();
|
||||||
|
}
|
||||||
async showRevokeConfirmation() {
|
async showRevokeConfirmation() {
|
||||||
await this.confirmationService.ask({
|
await this.confirmationService.ask({
|
||||||
header: `ابطال صورتحساب شماره ${this.invoice!.invoice_number}`,
|
header: `ابطال صورتحساب شماره ${this.invoice!.invoice_number}`,
|
||||||
@@ -146,40 +152,46 @@ export class SharedSaleInvoiceSingleViewComponent {
|
|||||||
if (changes['invoice'] && this.invoice) {
|
if (changes['invoice'] && this.invoice) {
|
||||||
const invoiceStatus = this.invoice.status.value;
|
const invoiceStatus = this.invoice.status.value;
|
||||||
const actions: MenuItem[] = [
|
const actions: MenuItem[] = [
|
||||||
|
{
|
||||||
|
label: 'ارسال مجدد صورتحساب',
|
||||||
|
icon: 'pi pi-send',
|
||||||
|
neededStatus: TspProviderResponseStatus.SEND_FAILURE,
|
||||||
|
command: this.resend,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'ارسال صورتحساب',
|
label: 'ارسال صورتحساب',
|
||||||
icon: 'pi pi-send',
|
icon: 'pi pi-send',
|
||||||
neededStatus: 'NOT_SEND',
|
neededStatus: TspProviderResponseStatus.NOT_SEND,
|
||||||
command: this.send,
|
command: this.send,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'استعلام وضعیت',
|
label: 'استعلام وضعیت',
|
||||||
icon: 'pi pi-info',
|
icon: 'pi pi-info',
|
||||||
neededStatus: 'FISCAL_QUEUED',
|
neededStatus: TspProviderResponseStatus.FISCAL_QUEUED,
|
||||||
command: this.inquiry,
|
command: this.inquiry,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'دلایل خطا',
|
label: 'دلایل خطا',
|
||||||
icon: 'pi pi-question',
|
icon: 'pi pi-question',
|
||||||
neededStatus: 'FAILURE',
|
neededStatus: TspProviderResponseStatus.FAILURE,
|
||||||
command: this.showErrors,
|
command: this.showErrors,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'ابطال',
|
label: 'ابطال',
|
||||||
icon: 'pi pi-eraser',
|
icon: 'pi pi-eraser',
|
||||||
neededStatus: 'SUCCESS',
|
neededStatus: TspProviderResponseStatus.SUCCESS,
|
||||||
command: this.showRevokeConfirmation,
|
command: this.showRevokeConfirmation,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'اصلاح',
|
label: 'اصلاح',
|
||||||
icon: 'pi pi-file-edit',
|
icon: 'pi pi-file-edit',
|
||||||
neededStatus: 'SUCCESS',
|
neededStatus: TspProviderResponseStatus.SUCCESS,
|
||||||
command: this.showCorrection,
|
command: this.showCorrection,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'برگشت از فروش',
|
label: 'برگشت از فروش',
|
||||||
icon: 'pi pi-cart-minus',
|
icon: 'pi pi-cart-minus',
|
||||||
neededStatus: 'SUCCESS',
|
neededStatus: TspProviderResponseStatus.SUCCESS,
|
||||||
command: this.showBackFromSale,
|
command: this.showBackFromSale,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
equalLengthValidator,
|
||||||
fiscalIdValidator,
|
fiscalIdValidator,
|
||||||
mobileValidator,
|
mobileValidator,
|
||||||
password,
|
password,
|
||||||
@@ -70,9 +71,13 @@ export const fieldControl = {
|
|||||||
value,
|
value,
|
||||||
isRequired ? [...required(), usernameValidator()] : [usernameValidator()],
|
isRequired ? [...required(), usernameValidator()] : [usernameValidator()],
|
||||||
],
|
],
|
||||||
economic_code: (value = '', isRequired = true): ControlConfig => [
|
legal_economic_code: (value = '', isRequired = true): ControlConfig => [
|
||||||
value,
|
value,
|
||||||
isRequired ? required() : [],
|
isRequired ? [...required(), equalLengthValidator(11)] : [equalLengthValidator(11)],
|
||||||
|
],
|
||||||
|
individual_economic_code: (value = '', isRequired = true): ControlConfig => [
|
||||||
|
value,
|
||||||
|
isRequired ? [...required(), equalLengthValidator(14)] : [equalLengthValidator(14)],
|
||||||
],
|
],
|
||||||
fiscal_id: (value = '', isRequired = true): ControlConfig => [
|
fiscal_id: (value = '', isRequired = true): ControlConfig => [
|
||||||
value,
|
value,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'bg-surface-ground font-bold': day.isCurrentDay,
|
'bg-surface-ground font-bold': day.isCurrentDay,
|
||||||
'bg-primary! text-primary-contrast!': isSelected(day),
|
'bg-primary! text-primary-contrast!': isSelected(day),
|
||||||
'text-muted-color! font-normal': day.isDisabled,
|
'text-muted-color! font-light': day.isDisabled,
|
||||||
}"
|
}"
|
||||||
(click)="selectDate(day)">
|
(click)="selectDate(day)">
|
||||||
{{ day.day }}
|
{{ day.day }}
|
||||||
|
|||||||
Reference in New Issue
Block a user