diff --git a/src/app/core/models/payment-method/hosted-payment-page-parameters.mapper.ts b/src/app/core/models/payment-method/hosted-payment-page-parameters.mapper.ts
new file mode 100644
index 0000000000..715f714126
--- /dev/null
+++ b/src/app/core/models/payment-method/hosted-payment-page-parameters.mapper.ts
@@ -0,0 +1,20 @@
+export class HostedPaymentPageParametersMapper {
+ static fromData(body: { name: string; value: string }[]): { name: string; value: string }[] {
+ const hostedPaymentPageParameters: { name: string; value: string }[] = new Array();
+
+ if (body !== undefined) {
+ for (const entry of body) {
+ if (typeof entry.value !== 'string') {
+ const sepaMandateArray = entry.value as { name: string; value: string }[];
+ hostedPaymentPageParameters.push({ name: 'mandateId', value: sepaMandateArray['mandateId'] });
+ hostedPaymentPageParameters.push({ name: 'mandateText', value: sepaMandateArray['mandateText'] });
+ hostedPaymentPageParameters.push({ name: 'directDebitType', value: sepaMandateArray['directDebitType'] });
+ } else {
+ hostedPaymentPageParameters.push(entry);
+ }
+ }
+ }
+
+ return hostedPaymentPageParameters;
+ }
+}
diff --git a/src/app/core/models/payment-method/payment-method.mapper.ts b/src/app/core/models/payment-method/payment-method.mapper.ts
index 457c25e7a7..a4dc382a61 100644
--- a/src/app/core/models/payment-method/payment-method.mapper.ts
+++ b/src/app/core/models/payment-method/payment-method.mapper.ts
@@ -3,6 +3,7 @@ import { FormlyFieldConfig } from '@ngx-formly/core';
import { PaymentInstrumentData } from 'ish-core/models/payment-instrument/payment-instrument.interface';
import { PriceMapper } from 'ish-core/models/price/price.mapper';
+import { HostedPaymentPageParametersMapper } from './hosted-payment-page-parameters.mapper';
import {
PaymentMethodBaseData,
PaymentMethodData,
@@ -41,7 +42,7 @@ export class PaymentMethodMapper {
? data.paymentInstruments.map(id => included.paymentInstruments[id])
: undefined,
parameters: data.parameterDefinitions ? PaymentMethodMapper.mapParameter(data.parameterDefinitions) : undefined,
- hostedPaymentPageParameters: data.hostedPaymentPageParameters,
+ hostedPaymentPageParameters: HostedPaymentPageParametersMapper.fromData(data.hostedPaymentPageParameters),
}));
}
diff --git a/src/app/pages/checkout-payment/checkout-payment-page.module.ts b/src/app/pages/checkout-payment/checkout-payment-page.module.ts
index c1f5a3a719..18fc60bc71 100644
--- a/src/app/pages/checkout-payment/checkout-payment-page.module.ts
+++ b/src/app/pages/checkout-payment/checkout-payment-page.module.ts
@@ -5,10 +5,16 @@ import { SharedModule } from 'ish-shared/shared.module';
import { CheckoutPaymentPageComponent } from './checkout-payment-page.component';
import { CheckoutPaymentComponent } from './checkout-payment/checkout-payment.component';
import { PaymentConcardisCreditcardComponent } from './payment-concardis-creditcard/payment-concardis-creditcard.component';
+import { PaymentConcardisDirectdebitComponent } from './payment-concardis-directdebit/payment-concardis-directdebit.component';
@NgModule({
imports: [SharedModule],
- declarations: [CheckoutPaymentComponent, CheckoutPaymentPageComponent, PaymentConcardisCreditcardComponent],
+ declarations: [
+ CheckoutPaymentComponent,
+ CheckoutPaymentPageComponent,
+ PaymentConcardisCreditcardComponent,
+ PaymentConcardisDirectdebitComponent,
+ ],
})
export class CheckoutPaymentPageModule {
static component = CheckoutPaymentPageComponent;
diff --git a/src/app/pages/checkout-payment/checkout-payment/checkout-payment.component.html b/src/app/pages/checkout-payment/checkout-payment/checkout-payment.component.html
index 4bba3639d3..a740525bba 100644
--- a/src/app/pages/checkout-payment/checkout-payment/checkout-payment.component.html
+++ b/src/app/pages/checkout-payment/checkout-payment/checkout-payment.component.html
@@ -107,39 +107,52 @@
{{ 'checkout.payment.method.select.heading' | translate }}
*{{ 'account.required_field.message' | translate }}
-
-
-
-
+
+
diff --git a/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.html b/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.html
new file mode 100644
index 0000000000..9c04e4a61a
--- /dev/null
+++ b/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.spec.ts b/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.spec.ts
new file mode 100644
index 0000000000..7139d6aabd
--- /dev/null
+++ b/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.spec.ts
@@ -0,0 +1,49 @@
+import { ComponentFixture, TestBed, async } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { FaIconComponent } from '@fortawesome/angular-fontawesome';
+import { NgbPopover } from '@ng-bootstrap/ng-bootstrap';
+import { FormlyForm } from '@ngx-formly/core';
+import { TranslateModule } from '@ngx-translate/core';
+import { MockComponent } from 'ng-mocks';
+
+import { PaymentMethod } from 'ish-core/models/payment-method/payment-method.model';
+import { CheckboxComponent } from 'ish-shared/forms/components/checkbox/checkbox.component';
+
+import { PaymentConcardisDirectdebitComponent } from './payment-concardis-directdebit.component';
+
+describe('Payment Concardis Directdebit Component', () => {
+ let component: PaymentConcardisDirectdebitComponent;
+ let fixture: ComponentFixture;
+ let element: HTMLElement;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ MockComponent(CheckboxComponent),
+ MockComponent(FaIconComponent),
+ MockComponent(FormlyForm),
+ MockComponent(NgbPopover),
+ PaymentConcardisDirectdebitComponent,
+ ],
+ imports: [ReactiveFormsModule, TranslateModule.forRoot()],
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PaymentConcardisDirectdebitComponent);
+ component = fixture.componentInstance;
+ element = fixture.nativeElement;
+
+ component.paymentMethod = {
+ id: 'Concardis_DirectDebit',
+ saveAllowed: false,
+ parameters: [{ key: 'key1', name: 'name', templateOptions: { label: 'input' } }],
+ } as PaymentMethod;
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ expect(element).toBeTruthy();
+ expect(() => fixture.detectChanges()).not.toThrow();
+ });
+});
diff --git a/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.ts b/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.ts
new file mode 100644
index 0000000000..240bf0109a
--- /dev/null
+++ b/src/app/pages/checkout-payment/payment-concardis-directdebit/payment-concardis-directdebit.component.ts
@@ -0,0 +1,365 @@
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ OnDestroy,
+ OnInit,
+ Output,
+} from '@angular/core';
+import { FormGroup, Validators } from '@angular/forms';
+import { FormlyFieldConfig, FormlyFormOptions } from '@ngx-formly/core';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
+
+import { Attribute } from 'ish-core/models/attribute/attribute.model';
+import { PaymentMethod } from 'ish-core/models/payment-method/payment-method.model';
+import { ScriptLoaderService } from 'ish-core/utils/script-loader/script-loader.service';
+import { markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils';
+
+// allows access to concardis js functionality
+// tslint:disable-next-line:no-any
+declare var PayEngine: any;
+
+/**
+ * The Payment Concardis Directdebit Component renders a form on which the user can enter his concardis direct debit data. Some entry fields are provided by an external host and embedded as iframes. Therefore an external javascript is loaded. See also {@link CheckoutPaymentPageComponent}
+ *
+ * @example
+ *
+ */
+@Component({
+ selector: 'ish-payment-concardis-directdebit',
+ templateUrl: './payment-concardis-directdebit.component.html',
+ changeDetection: ChangeDetectionStrategy.Default,
+})
+// tslint:disable-next-line:ccp-no-intelligence-in-components
+export class PaymentConcardisDirectdebitComponent implements OnInit, OnChanges, OnDestroy {
+ /**
+ * concardis payment method, needed to get configuration parameters
+ */
+ @Input() paymentMethod: PaymentMethod;
+
+ /**
+ * should be set to true by the parent, if component is visible
+ */
+ @Input() activated = false;
+
+ @Output() cancel = new EventEmitter();
+ @Output() submit = new EventEmitter<{ parameters: Attribute[]; saveAllowed: boolean }>();
+
+ parameterForm: FormGroup; // form for parameters which doesnt come form payment host
+ model = {};
+ options: FormlyFormOptions = {};
+
+ scriptLoaded = false; // flag to make sure that the init script is executed only once
+ formSubmitted = false; // flag for displaying error messages after form submit
+
+ // error messages from host
+ errorMessage = {
+ general: { message: '' },
+ iban: { messageKey: '', message: '', code: 0 },
+ bic: { messageKey: '', message: '', code: 0 },
+ accountholder: { messageKey: '', message: '', code: 0 },
+ };
+
+ private destroy$ = new Subject();
+
+ constructor(private scriptLoader: ScriptLoaderService, private cd: ChangeDetectorRef) {}
+
+ /**
+ * initialize parameter form on init
+ */
+ ngOnInit() {
+ this.parameterForm = new FormGroup({});
+ }
+
+ /* ---------------------------------------- load concardis script if component is visible ------------------------------------------- */
+
+ /**
+ * load concardis script if component is shown
+ */
+ ngOnChanges() {
+ if (this.paymentMethod) {
+ this.loadScript();
+ }
+ }
+
+ ngOnDestroy() {
+ this.destroy$.next();
+ }
+
+ handleErrors(controlName: string, message: string) {
+ this.parameterForm.controls[controlName].markAsDirty();
+ this.parameterForm.controls[controlName].markAsTouched();
+ this.parameterForm.controls[controlName].setErrors({ customError: message });
+ }
+
+ loadScript() {
+ // load script only once if component becomes visible
+ if (this.activated && !this.scriptLoaded) {
+ const merchantId = this.getParamValue(
+ 'ConcardisPaymentService.MerchantID',
+ 'checkout.credit_card.merchantId.error.notFound'
+ );
+
+ const url =
+ this.getParamValue('ConcardisPaymentService.Environment', '') === 'LIVE'
+ ? 'https://pp.payengine.de/bridge/1.0/payengine.min.js'
+ : 'https://pptest.payengine.de/bridge/1.0/payengine.min.js';
+
+ this.scriptLoaded = true;
+ this.scriptLoader
+ .load(url)
+ .pipe(takeUntil(this.destroy$))
+ .subscribe(() => {
+ PayEngine.setPublishableKey(merchantId);
+ });
+ }
+ }
+
+ /**
+ * gets a parameter value from payment method
+ * sets the general error message (key) if the parameter is not available
+ */
+ private getParamValue(name: string, errorMessage: string): string {
+ const parameter = this.paymentMethod.hostedPaymentPageParameters.find(param => param.name === name);
+ if (!parameter || !parameter.value) {
+ this.errorMessage.general.message = errorMessage;
+ return;
+ }
+ return parameter.value;
+ }
+
+ /**
+ * hide fields without labels and enrich mandate reference and mandate text with corresponding values from hosted payment page parameters
+ */
+ getFieldConfig(): FormlyFieldConfig[] {
+ const fields: FormlyFieldConfig[] = [];
+ for (const param of this.paymentMethod.parameters) {
+ if (!param.templateOptions.label) {
+ if (param.key === 'mandateReference') {
+ param.defaultValue = this.getParamValue('mandateId', '');
+ }
+ param.hide = true;
+ if (param.key === 'mandateText') {
+ param.type = 'checkbox';
+ param.fieldGroupClassName = 'offset-md-4 col-md-8';
+ param.templateOptions.label = this.getParamValue('mandateText', '');
+ param.defaultValue = false;
+ param.hide = false;
+ param.validators = [Validators.pattern('false')];
+ }
+ }
+ fields.push(param);
+ }
+ return fields;
+ }
+
+ /* ---------------------------------------- concardis callback functions ------------------------------------------- */
+
+ /**
+ * call back function to submit data, get a response token from provider and send data in case of success
+ */
+ submitCallback(
+ error: { message: { properties: { key: string; code: number; message: string; messageKey: string }[] } | string },
+ result: {
+ paymentInstrumentId: string;
+ attributes: {
+ accountHolder: string;
+ iban: string;
+ mandateReference: string;
+ mandate: {
+ mandateReference: string;
+ createdDateTime: string;
+ mandateText: string;
+ directDebitType: string;
+ };
+ createdAt: string;
+ };
+ }
+ ) {
+ if (this.parameterForm.invalid) {
+ this.formSubmitted = true;
+ markAsDirtyRecursive(this.parameterForm);
+ }
+
+ this.resetErrors();
+ if (error) {
+ // map error messages
+ if (typeof error.message !== 'string' && error.message.properties) {
+ this.errorMessage.iban = error.message.properties && error.message.properties.find(prop => prop.key === 'iban');
+ if (this.errorMessage.iban && this.errorMessage.iban.code) {
+ this.errorMessage.iban.messageKey = this.getErrorMessage(
+ this.errorMessage.iban.code,
+ 'iban',
+ this.errorMessage.iban.message
+ );
+ this.handleErrors('IBAN', this.errorMessage.iban.messageKey);
+ }
+
+ this.errorMessage.bic = error.message.properties && error.message.properties.find(prop => prop.key === 'bic');
+ if (this.errorMessage.bic && this.errorMessage.bic.code) {
+ this.errorMessage.bic.messageKey = this.getErrorMessage(
+ this.errorMessage.bic.code,
+ 'bic',
+ this.errorMessage.bic.message
+ );
+ this.handleErrors('BIC', this.errorMessage.bic.messageKey);
+ }
+
+ this.errorMessage.accountholder =
+ error.message.properties && error.message.properties.find(prop => prop.key === 'accountholder');
+ if (this.errorMessage.accountholder && this.errorMessage.accountholder.code) {
+ this.errorMessage.accountholder.messageKey = this.getErrorMessage(
+ this.errorMessage.accountholder.code,
+ 'bic',
+ this.errorMessage.accountholder.message
+ );
+ this.handleErrors('accountHolder', this.errorMessage.accountholder.messageKey);
+ }
+ } else if (typeof error.message === 'string') {
+ this.errorMessage.general.message = error.message;
+ }
+ } else if (!this.parameterForm.invalid) {
+ this.submit.emit({
+ parameters: [
+ { name: 'paymentInstrumentId', value: result.paymentInstrumentId },
+ { name: 'accountHolder', value: result.attributes.accountHolder },
+ { name: 'IBAN', value: result.attributes.iban },
+ { name: 'mandateReference', value: result.attributes.mandate.mandateReference },
+ { name: 'mandateText', value: result.attributes.mandate.mandateText },
+ { name: 'mandateCreatedDateTime', value: result.attributes.mandate.createdDateTime },
+ ],
+ saveAllowed: this.paymentMethod.saveAllowed && this.parameterForm.get('saveForLater').value,
+ });
+ }
+ this.cd.detectChanges();
+ }
+
+ /* ---------------------------------------- error message handling ------------------------------------------- */
+
+ /**
+ * reset errorMessages
+ */
+ resetErrors() {
+ this.errorMessage.general.message = undefined;
+ if (this.errorMessage.accountholder) {
+ this.errorMessage.accountholder.message = undefined;
+ this.errorMessage.accountholder.messageKey = undefined;
+ this.errorMessage.accountholder.code = undefined;
+ }
+ if (this.errorMessage.iban) {
+ this.errorMessage.iban.message = undefined;
+ this.errorMessage.iban.messageKey = undefined;
+ this.errorMessage.iban.code = undefined;
+ }
+ if (this.errorMessage.bic) {
+ this.errorMessage.bic.message = undefined;
+ this.errorMessage.bic.messageKey = undefined;
+ this.errorMessage.bic.code = undefined;
+ }
+ }
+
+ /**
+ * determine errorMessages on the basis of the error code
+ */
+ getErrorMessage(code: number, fieldType: string, defaultMessage: string): string {
+ let messageKey: string;
+
+ switch (code) {
+ case 4121: {
+ messageKey = `checkout.sepa.${fieldType}.error.default`;
+ break;
+ }
+ case 4122: {
+ messageKey = `checkout.sepa.${fieldType}.error.default`;
+ break;
+ }
+ case 4124: {
+ messageKey = `checkout.sepa.${fieldType}.error.notAlphanumeric`;
+ break;
+ }
+ case 41213: {
+ messageKey = `checkout.sepa.${fieldType}.error.countryNotSupported`;
+ break;
+ }
+ case 41214: {
+ messageKey = `checkout.sepa.${fieldType}.error.length`;
+ break;
+ }
+
+ case 41215: {
+ messageKey = `checkout.sepa.${fieldType}.error.invalid`;
+ break;
+ }
+
+ case 41216: {
+ messageKey = `checkout.sepa.${fieldType}.error.length`;
+ break;
+ }
+
+ case 41217: {
+ messageKey = `checkout.sepa.${fieldType}.error.countryNotSupported`;
+ break;
+ }
+ default: {
+ messageKey = defaultMessage;
+ break;
+ }
+ }
+
+ return messageKey;
+ }
+
+ /* ---------------------------------------- cancel and submit form ------------------------------------------- */
+
+ /**
+ * cancel new payment instrument, hides and resets the parameter form
+ */
+ cancelNewPaymentInstrument() {
+ this.parameterForm.reset();
+ this.resetErrors();
+ this.cancel.emit();
+ }
+
+ /**
+ * submit concardis payment form
+ */
+ submitNewPaymentInstrument() {
+ const parameters = Object.entries(this.parameterForm.controls)
+ .filter(([, control]) => control.enabled && control.value)
+ .map(([key, control]) => ({ name: key, value: control.value }));
+
+ let paymentData: {
+ accountHolder: string;
+ bic?: string;
+ iban: string;
+ mandate: { mandateId: string; mandateText: string; directDebitType: string };
+ } = {
+ accountHolder: parameters.find(p => p.name === 'accountHolder')
+ ? parameters.find(p => p.name === 'accountHolder').value
+ : undefined,
+ iban: parameters.find(p => p.name === 'IBAN') ? parameters.find(p => p.name === 'IBAN').value : undefined,
+ mandate: {
+ mandateId: parameters.find(p => p.name === 'mandateReference')
+ ? parameters.find(p => p.name === 'mandateReference').value
+ : undefined,
+ mandateText: this.getParamValue('mandateText', ''),
+ directDebitType: this.getParamValue('directDebitType', ''),
+ },
+ };
+
+ if (parameters.find(p => p.name === 'BIC')) {
+ paymentData = { ...paymentData, bic: parameters.find(p => p.name === 'BIC').value };
+ }
+ // tslint:disable-next-line:no-null-keyword
+ PayEngine.createPaymentInstrument('sepa', paymentData, null, (err, val) => this.submitCallback(err, val));
+ }
+}
diff --git a/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.html b/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.html
new file mode 100644
index 0000000000..034fc0a933
--- /dev/null
+++ b/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.html
@@ -0,0 +1,9 @@
+
+
+
diff --git a/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.spec.ts b/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.spec.ts
new file mode 100644
index 0000000000..b66bd8c1fa
--- /dev/null
+++ b/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.spec.ts
@@ -0,0 +1,51 @@
+import { ComponentFixture, TestBed, async } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+
+import { CheckboxComponent } from 'ish-shared/forms/components/checkbox/checkbox.component';
+
+import { CheckboxDynamicComponent } from './checkbox-dynamic.component';
+
+describe('Checkbox Dynamic Component', () => {
+ let component: CheckboxDynamicComponent;
+ let fixture: ComponentFixture;
+ let element: HTMLElement;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [CheckboxDynamicComponent, MockComponent(CheckboxComponent)],
+ })
+ .compileComponents()
+ .then(() => {
+ fixture = TestBed.createComponent(CheckboxDynamicComponent);
+ component = fixture.componentInstance;
+ element = fixture.nativeElement;
+
+ component.field = {
+ key: 'test',
+ templateOptions: {},
+ fieldGroupClassName: 'offset',
+ };
+ });
+ }));
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ expect(element).toBeTruthy();
+ expect(() => fixture.detectChanges()).not.toThrow();
+ });
+
+ it('should render a checkbox form component if field is provided', () => {
+ fixture.detectChanges();
+ expect(element.querySelector('ish-checkbox')).toBeTruthy();
+ });
+
+ it('should not render an checkbox form component if field is missing', () => {
+ component.field = {
+ key: 'test',
+ templateOptions: {},
+ fieldGroupClassName: undefined,
+ };
+ fixture.detectChanges();
+ expect(element.querySelector('ish-checkbox')).toBeFalsy();
+ });
+});
diff --git a/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.ts b/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.ts
new file mode 100644
index 0000000000..c9b6fa2f38
--- /dev/null
+++ b/src/app/shared/forms-dynamic/components/checkbox-dynamic/checkbox-dynamic.component.ts
@@ -0,0 +1,9 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { FieldType } from '@ngx-formly/core';
+
+@Component({
+ selector: 'ish-checkbox-dynamic',
+ templateUrl: './checkbox-dynamic.component.html',
+ changeDetection: ChangeDetectionStrategy.Default,
+})
+export class CheckboxDynamicComponent extends FieldType {}
diff --git a/src/app/shared/forms-dynamic/forms-dynamic.module.ts b/src/app/shared/forms-dynamic/forms-dynamic.module.ts
index d9c17c0c5c..9a0f13fb68 100644
--- a/src/app/shared/forms-dynamic/forms-dynamic.module.ts
+++ b/src/app/shared/forms-dynamic/forms-dynamic.module.ts
@@ -5,6 +5,7 @@ import { FormlyModule } from '@ngx-formly/core';
import { FormsSharedModule } from 'ish-shared/forms/forms.module';
+import { CheckboxDynamicComponent } from './components/checkbox-dynamic/checkbox-dynamic.component';
import { InputDynamicComponent } from './components/input-dynamic/input-dynamic.component';
import { SelectDynamicComponent } from './components/select-dynamic/select-dynamic.component';
@@ -15,12 +16,13 @@ import { SelectDynamicComponent } from './components/select-dynamic/select-dynam
types: [
{ name: 'input', component: InputDynamicComponent },
{ name: 'select', component: SelectDynamicComponent },
+ { name: 'checkbox', component: CheckboxDynamicComponent },
],
}),
FormsSharedModule,
ReactiveFormsModule,
],
- declarations: [InputDynamicComponent, SelectDynamicComponent],
- exports: [InputDynamicComponent, SelectDynamicComponent],
+ declarations: [CheckboxDynamicComponent, InputDynamicComponent, SelectDynamicComponent],
+ exports: [CheckboxDynamicComponent, InputDynamicComponent, SelectDynamicComponent],
})
export class FormsDynamicModule {}
diff --git a/src/assets/i18n/en_US.json b/src/assets/i18n/en_US.json
index 5c55eb3942..f2f0e43dfd 100644
--- a/src/assets/i18n/en_US.json
+++ b/src/assets/i18n/en_US.json
@@ -2679,5 +2679,17 @@
"quote.already_in_basket.error": "The quote is already in the cart.",
"quote.not_found.error": "The quote could not be found.",
"basket.add_quote.error": "The quote could not be added to the cart.",
- "quoterequest.not_editable.error": "You have already submitted the quote request. Please reload this page to view the changes."
+ "quoterequest.not_editable.error": "You have already submitted the quote request. Please reload this page to view the changes.",
+ "checkout.sepa.iban.error.default": "Field is required and should not be empty!",
+ "checkout.sepa.iban.error.length": "The length of the iban value is invalid!",
+ "checkout.sepa.iban.error.countryNotSupported": "Country not supported!",
+ "checkout.sepa.iban.error.notAlphanumeric": "IBAN value should be alphanumeric!",
+ "checkout.sepa.iban.error.invalid": "The IBAN value is invalid!",
+ "checkout.sepa.accountholder.error.default": "Field is required and should not be empty!",
+ "checkout.sepa.accountholder.error.notAlphanumeric": "Account holder value should be alphanumeric!",
+ "checkout.sepa.bic.error.notAlphanumeric": "BIC value should be alphanumeric!",
+ "checkout.sepa.bic.error.countryNotSupported": "BIC country not supported!",
+ "checkout.sepa.bic.error.length": "The length of the BIC value is invalid!",
+ "checkout.sepa.bic.error.invalid": "The BIC value is invalid!",
+ "checkout.sepa.mandate.error.required": "No consent has been given for authorisation."
}