diff --git a/lib/constants.dart b/lib/constants.dart index f7febf69a..0d0e39273 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -171,6 +171,7 @@ const String kCurrencyEuro = '3'; const String kCountryUnitedStates = '840'; const String kCountryCanada = '124'; +const String kCountrySwitzerland = '756'; const String kInvoiceStatusViewed = '-3'; const String kInvoiceStatusUnpaid = '-2'; diff --git a/lib/data/models/company_model.dart b/lib/data/models/company_model.dart index 792084d73..047b993e1 100644 --- a/lib/data/models/company_model.dart +++ b/lib/data/models/company_model.dart @@ -619,6 +619,8 @@ abstract class CompanyEntity extends Object String get currencyId => settings.currencyId ?? kDefaultCurrencyId; + bool get supportsQrIban => settings.countryId == kCountrySwitzerland; + // ignore: unused_element static void _initializeBuilder(CompanyEntityBuilder builder) => builder ..calculateExpenseTaxByAmount = false diff --git a/lib/data/models/settings_model.dart b/lib/data/models/settings_model.dart index 6b8918cf3..446b7147f 100644 --- a/lib/data/models/settings_model.dart +++ b/lib/data/models/settings_model.dart @@ -885,6 +885,14 @@ abstract class SettingsEntity @BuiltValueField(wireName: 'purchase_order_number_counter') int get purchaseOrderNumberCounter; + @nullable + @BuiltValueField(wireName: 'qr_iban') + String get qrIban; + + @nullable + @BuiltValueField(wireName: 'besr_id') + String get besrId; + bool get hasAddress => address1 != null && address1.isNotEmpty; bool get hasLogo => companyLogo != null && companyLogo.isNotEmpty; diff --git a/lib/data/models/settings_model.g.dart b/lib/data/models/settings_model.g.dart index 0129231a4..88d84a336 100644 --- a/lib/data/models/settings_model.g.dart +++ b/lib/data/models/settings_model.g.dart @@ -1364,6 +1364,20 @@ class _$SettingsEntitySerializer ..add('purchase_order_number_counter') ..add(serializers.serialize(value, specifiedType: const FullType(int))); } + value = object.qrIban; + if (value != null) { + result + ..add('qr_iban') + ..add(serializers.serialize(value, + specifiedType: const FullType(String))); + } + value = object.besrId; + if (value != null) { + result + ..add('besr_id') + ..add(serializers.serialize(value, + specifiedType: const FullType(String))); + } return result; } @@ -2160,6 +2174,14 @@ class _$SettingsEntitySerializer result.purchaseOrderNumberCounter = serializers.deserialize(value, specifiedType: const FullType(int)) as int; break; + case 'qr_iban': + result.qrIban = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; + case 'besr_id': + result.besrId = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; } } @@ -2556,6 +2578,10 @@ class _$SettingsEntity extends SettingsEntity { final String purchaseOrderNumberPattern; @override final int purchaseOrderNumberCounter; + @override + final String qrIban; + @override + final String besrId; factory _$SettingsEntity([void Function(SettingsEntityBuilder) updates]) => (new SettingsEntityBuilder()..update(updates)).build(); @@ -2754,7 +2780,9 @@ class _$SettingsEntity extends SettingsEntity { this.defaultPurchaseOrderDesignId, this.defaultPurchaseOrderFooter, this.purchaseOrderNumberPattern, - this.purchaseOrderNumberCounter}) + this.purchaseOrderNumberCounter, + this.qrIban, + this.besrId}) : super._(); @override @@ -2965,7 +2993,9 @@ class _$SettingsEntity extends SettingsEntity { defaultPurchaseOrderDesignId == other.defaultPurchaseOrderDesignId && defaultPurchaseOrderFooter == other.defaultPurchaseOrderFooter && purchaseOrderNumberPattern == other.purchaseOrderNumberPattern && - purchaseOrderNumberCounter == other.purchaseOrderNumberCounter; + purchaseOrderNumberCounter == other.purchaseOrderNumberCounter && + qrIban == other.qrIban && + besrId == other.besrId; } int __hashCode; @@ -2989,26 +3019,26 @@ class _$SettingsEntity extends SettingsEntity { $jc( $jc( $jc( - $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, timezoneId.hashCode), dateFormatId.hashCode), enableMilitaryTime.hashCode), languageId.hashCode), showCurrencyCode.hashCode), currencyId.hashCode), customValue1.hashCode), customValue2.hashCode), customValue3.hashCode), customValue4.hashCode), defaultPaymentTerms.hashCode), defaultValidUntil.hashCode), companyGatewayIds.hashCode), defaultTaskRate.hashCode), sendReminders.hashCode), enablePortal.hashCode), enablePortalDashboard.hashCode), enablePortalTasks.hashCode), enablePortalUploads.hashCode), emailStyle.hashCode), replyToEmail.hashCode), replyToName.hashCode), emailFromName.hashCode), bccEmail.hashCode), pdfEmailAttachment.hashCode), ublEmailAttachment.hashCode), documentEmailAttachment.hashCode), emailStyleCustom.hashCode), customMessageDashboard.hashCode), customMessageUnpaidInvoice.hashCode), customMessagePaidInvoice.hashCode), customMessageUnapprovedQuote.hashCode), autoArchiveInvoice.hashCode), autoArchiveInvoiceCancelled.hashCode), autoArchiveQuote.hashCode), autoEmailInvoice.hashCode), autoConvertQuote.hashCode), enableInclusiveTaxes.hashCode), translations.hashCode), taskNumberPattern.hashCode), taskNumberCounter.hashCode), expenseNumberPattern.hashCode), expenseNumberCounter.hashCode), recurringExpenseNumberPattern.hashCode), recurringExpenseNumberCounter.hashCode), vendorNumberPattern.hashCode), vendorNumberCounter.hashCode), ticketNumberPattern.hashCode), ticketNumberCounter.hashCode), paymentNumberPattern.hashCode), paymentNumberCounter.hashCode), projectNumberPattern.hashCode), projectNumberCounter.hashCode), invoiceNumberPattern.hashCode), invoiceNumberCounter.hashCode), recurringInvoiceNumberPattern.hashCode), recurringInvoiceNumberCounter.hashCode), quoteNumberPattern.hashCode), quoteNumberCounter.hashCode), clientNumberPattern.hashCode), clientNumberCounter.hashCode), creditNumberPattern.hashCode), creditNumberCounter.hashCode), recurringNumberPrefix.hashCode), resetCounterFrequencyId.hashCode), resetCounterDate.hashCode), counterPadding.hashCode), sharedInvoiceQuoteCounter.hashCode), sharedInvoiceCreditCounter.hashCode), defaultInvoiceTerms.hashCode), defaultQuoteTerms.hashCode), defaultQuoteFooter.hashCode), defaultCreditTerms.hashCode), defaultCreditFooter.hashCode), defaultInvoiceDesignId.hashCode), defaultQuoteDesignId.hashCode), defaultCreditDesignId.hashCode), defaultInvoiceFooter.hashCode), defaultTaxName1.hashCode), defaultTaxRate1.hashCode), defaultTaxName2.hashCode), defaultTaxRate2.hashCode), defaultTaxName3.hashCode), defaultTaxRate3.hashCode), defaultPaymentTypeId.hashCode), pdfVariables.hashCode), emailSignature.hashCode), emailSubjectInvoice.hashCode), emailSubjectQuote.hashCode), emailSubjectCredit.hashCode), emailSubjectPayment.hashCode), emailSubjectPaymentPartial.hashCode), emailBodyInvoice.hashCode), emailBodyQuote.hashCode), emailBodyCredit.hashCode), emailBodyPayment.hashCode), emailBodyPaymentPartial.hashCode), emailSubjectReminder1.hashCode), emailSubjectReminder2.hashCode), emailSubjectReminder3.hashCode), emailBodyReminder1.hashCode), emailBodyReminder2.hashCode), emailBodyReminder3.hashCode), emailSubjectCustom1.hashCode), emailBodyCustom1.hashCode), emailSubjectCustom2.hashCode), emailBodyCustom2.hashCode), emailSubjectCustom3.hashCode), emailBodyCustom3.hashCode), emailSubjectStatement.hashCode), emailBodyStatement.hashCode), emailSubjectPurchaseOrder.hashCode), emailBodyPurchaseOrder.hashCode), enablePortalPassword.hashCode), signatureOnPdf.hashCode), enableEmailMarkup.hashCode), showAcceptInvoiceTerms.hashCode), showAcceptQuoteTerms.hashCode), requireInvoiceSignature.hashCode), requireQuoteSignature.hashCode), name.hashCode), companyLogo.hashCode), website.hashCode), address1.hashCode), address2.hashCode), city.hashCode), state.hashCode), postalCode.hashCode), phone.hashCode), email.hashCode), countryId.hashCode), vatNumber.hashCode), idNumber.hashCode), pageSize.hashCode), pageLayout.hashCode), fontSize.hashCode), primaryColor.hashCode), secondaryColor.hashCode), primaryFont.hashCode), secondaryFont.hashCode), hidePaidToDate.hashCode), embedDocuments.hashCode), allPagesHeader.hashCode), allPagesFooter.hashCode), enableReminder1.hashCode), enableReminder2.hashCode), enableReminder3.hashCode), enableReminderEndless.hashCode), numDaysReminder1.hashCode), numDaysReminder2.hashCode), numDaysReminder3.hashCode), scheduleReminder1.hashCode), scheduleReminder2.hashCode), scheduleReminder3.hashCode), endlessReminderFrequencyId.hashCode), lateFeeAmount1.hashCode), lateFeeAmount2.hashCode), lateFeeAmount3.hashCode), lateFeeAmountEndless.hashCode), lateFeePercent1.hashCode), lateFeePercent2.hashCode), lateFeePercent3.hashCode), lateFeePercentEndless.hashCode), emailSubjectReminderEndless.hashCode), emailBodyReminderEndless.hashCode), clientOnlinePaymentNotification.hashCode), clientManualPaymentNotification.hashCode), counterNumberApplied.hashCode), emailSendingMethod.hashCode), gmailSendingUserId.hashCode), clientPortalTerms.hashCode), clientPortalPrivacy.hashCode), lockInvoices.hashCode), autoBill.hashCode), clientPortalAllowUnderPayment.hashCode), - clientPortalAllowOverPayment.hashCode), - autoBillDate.hashCode), - clientPortalUnderPaymentMinimum.hashCode), - useCreditsPayment.hashCode), - clientPortalCustomHeader.hashCode), - clientPortalCustomCss.hashCode), - clientPortalCustomFooter.hashCode), - clientPortalCustomJs.hashCode), - hideEmptyColumnsOnPdf.hashCode), - entitySendTime.hashCode), - clientPortalTasks.hashCode), - pageNumbering.hashCode), - pageNumberingAlignment.hashCode), - requirePurchaseOrderSignature.hashCode), - defaultPurchaseOrderTerms.hashCode), - defaultPurchaseOrderDesignId.hashCode), - defaultPurchaseOrderFooter.hashCode), - purchaseOrderNumberPattern.hashCode), - purchaseOrderNumberCounter.hashCode)); + $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, timezoneId.hashCode), dateFormatId.hashCode), enableMilitaryTime.hashCode), languageId.hashCode), showCurrencyCode.hashCode), currencyId.hashCode), customValue1.hashCode), customValue2.hashCode), customValue3.hashCode), customValue4.hashCode), defaultPaymentTerms.hashCode), defaultValidUntil.hashCode), companyGatewayIds.hashCode), defaultTaskRate.hashCode), sendReminders.hashCode), enablePortal.hashCode), enablePortalDashboard.hashCode), enablePortalTasks.hashCode), enablePortalUploads.hashCode), emailStyle.hashCode), replyToEmail.hashCode), replyToName.hashCode), emailFromName.hashCode), bccEmail.hashCode), pdfEmailAttachment.hashCode), ublEmailAttachment.hashCode), documentEmailAttachment.hashCode), emailStyleCustom.hashCode), customMessageDashboard.hashCode), customMessageUnpaidInvoice.hashCode), customMessagePaidInvoice.hashCode), customMessageUnapprovedQuote.hashCode), autoArchiveInvoice.hashCode), autoArchiveInvoiceCancelled.hashCode), autoArchiveQuote.hashCode), autoEmailInvoice.hashCode), autoConvertQuote.hashCode), enableInclusiveTaxes.hashCode), translations.hashCode), taskNumberPattern.hashCode), taskNumberCounter.hashCode), expenseNumberPattern.hashCode), expenseNumberCounter.hashCode), recurringExpenseNumberPattern.hashCode), recurringExpenseNumberCounter.hashCode), vendorNumberPattern.hashCode), vendorNumberCounter.hashCode), ticketNumberPattern.hashCode), ticketNumberCounter.hashCode), paymentNumberPattern.hashCode), paymentNumberCounter.hashCode), projectNumberPattern.hashCode), projectNumberCounter.hashCode), invoiceNumberPattern.hashCode), invoiceNumberCounter.hashCode), recurringInvoiceNumberPattern.hashCode), recurringInvoiceNumberCounter.hashCode), quoteNumberPattern.hashCode), quoteNumberCounter.hashCode), clientNumberPattern.hashCode), clientNumberCounter.hashCode), creditNumberPattern.hashCode), creditNumberCounter.hashCode), recurringNumberPrefix.hashCode), resetCounterFrequencyId.hashCode), resetCounterDate.hashCode), counterPadding.hashCode), sharedInvoiceQuoteCounter.hashCode), sharedInvoiceCreditCounter.hashCode), defaultInvoiceTerms.hashCode), defaultQuoteTerms.hashCode), defaultQuoteFooter.hashCode), defaultCreditTerms.hashCode), defaultCreditFooter.hashCode), defaultInvoiceDesignId.hashCode), defaultQuoteDesignId.hashCode), defaultCreditDesignId.hashCode), defaultInvoiceFooter.hashCode), defaultTaxName1.hashCode), defaultTaxRate1.hashCode), defaultTaxName2.hashCode), defaultTaxRate2.hashCode), defaultTaxName3.hashCode), defaultTaxRate3.hashCode), defaultPaymentTypeId.hashCode), pdfVariables.hashCode), emailSignature.hashCode), emailSubjectInvoice.hashCode), emailSubjectQuote.hashCode), emailSubjectCredit.hashCode), emailSubjectPayment.hashCode), emailSubjectPaymentPartial.hashCode), emailBodyInvoice.hashCode), emailBodyQuote.hashCode), emailBodyCredit.hashCode), emailBodyPayment.hashCode), emailBodyPaymentPartial.hashCode), emailSubjectReminder1.hashCode), emailSubjectReminder2.hashCode), emailSubjectReminder3.hashCode), emailBodyReminder1.hashCode), emailBodyReminder2.hashCode), emailBodyReminder3.hashCode), emailSubjectCustom1.hashCode), emailBodyCustom1.hashCode), emailSubjectCustom2.hashCode), emailBodyCustom2.hashCode), emailSubjectCustom3.hashCode), emailBodyCustom3.hashCode), emailSubjectStatement.hashCode), emailBodyStatement.hashCode), emailSubjectPurchaseOrder.hashCode), emailBodyPurchaseOrder.hashCode), enablePortalPassword.hashCode), signatureOnPdf.hashCode), enableEmailMarkup.hashCode), showAcceptInvoiceTerms.hashCode), showAcceptQuoteTerms.hashCode), requireInvoiceSignature.hashCode), requireQuoteSignature.hashCode), name.hashCode), companyLogo.hashCode), website.hashCode), address1.hashCode), address2.hashCode), city.hashCode), state.hashCode), postalCode.hashCode), phone.hashCode), email.hashCode), countryId.hashCode), vatNumber.hashCode), idNumber.hashCode), pageSize.hashCode), pageLayout.hashCode), fontSize.hashCode), primaryColor.hashCode), secondaryColor.hashCode), primaryFont.hashCode), secondaryFont.hashCode), hidePaidToDate.hashCode), embedDocuments.hashCode), allPagesHeader.hashCode), allPagesFooter.hashCode), enableReminder1.hashCode), enableReminder2.hashCode), enableReminder3.hashCode), enableReminderEndless.hashCode), numDaysReminder1.hashCode), numDaysReminder2.hashCode), numDaysReminder3.hashCode), scheduleReminder1.hashCode), scheduleReminder2.hashCode), scheduleReminder3.hashCode), endlessReminderFrequencyId.hashCode), lateFeeAmount1.hashCode), lateFeeAmount2.hashCode), lateFeeAmount3.hashCode), lateFeeAmountEndless.hashCode), lateFeePercent1.hashCode), lateFeePercent2.hashCode), lateFeePercent3.hashCode), lateFeePercentEndless.hashCode), emailSubjectReminderEndless.hashCode), emailBodyReminderEndless.hashCode), clientOnlinePaymentNotification.hashCode), clientManualPaymentNotification.hashCode), counterNumberApplied.hashCode), emailSendingMethod.hashCode), gmailSendingUserId.hashCode), clientPortalTerms.hashCode), clientPortalPrivacy.hashCode), lockInvoices.hashCode), autoBill.hashCode), clientPortalAllowUnderPayment.hashCode), clientPortalAllowOverPayment.hashCode), autoBillDate.hashCode), + clientPortalUnderPaymentMinimum.hashCode), + useCreditsPayment.hashCode), + clientPortalCustomHeader.hashCode), + clientPortalCustomCss.hashCode), + clientPortalCustomFooter.hashCode), + clientPortalCustomJs.hashCode), + hideEmptyColumnsOnPdf.hashCode), + entitySendTime.hashCode), + clientPortalTasks.hashCode), + pageNumbering.hashCode), + pageNumberingAlignment.hashCode), + requirePurchaseOrderSignature.hashCode), + defaultPurchaseOrderTerms.hashCode), + defaultPurchaseOrderDesignId.hashCode), + defaultPurchaseOrderFooter.hashCode), + purchaseOrderNumberPattern.hashCode), + purchaseOrderNumberCounter.hashCode), + qrIban.hashCode), + besrId.hashCode)); } @override @@ -3210,7 +3240,9 @@ class _$SettingsEntity extends SettingsEntity { ..add('defaultPurchaseOrderDesignId', defaultPurchaseOrderDesignId) ..add('defaultPurchaseOrderFooter', defaultPurchaseOrderFooter) ..add('purchaseOrderNumberPattern', purchaseOrderNumberPattern) - ..add('purchaseOrderNumberCounter', purchaseOrderNumberCounter)) + ..add('purchaseOrderNumberCounter', purchaseOrderNumberCounter) + ..add('qrIban', qrIban) + ..add('besrId', besrId)) .toString(); } } @@ -4168,6 +4200,14 @@ class SettingsEntityBuilder set purchaseOrderNumberCounter(int purchaseOrderNumberCounter) => _$this._purchaseOrderNumberCounter = purchaseOrderNumberCounter; + String _qrIban; + String get qrIban => _$this._qrIban; + set qrIban(String qrIban) => _$this._qrIban = qrIban; + + String _besrId; + String get besrId => _$this._besrId; + set besrId(String besrId) => _$this._besrId = besrId; + SettingsEntityBuilder(); SettingsEntityBuilder get _$this { @@ -4367,6 +4407,8 @@ class SettingsEntityBuilder _defaultPurchaseOrderFooter = $v.defaultPurchaseOrderFooter; _purchaseOrderNumberPattern = $v.purchaseOrderNumberPattern; _purchaseOrderNumberCounter = $v.purchaseOrderNumberCounter; + _qrIban = $v.qrIban; + _besrId = $v.besrId; _$v = null; } return this; @@ -4582,7 +4624,9 @@ class SettingsEntityBuilder defaultPurchaseOrderDesignId: defaultPurchaseOrderDesignId, defaultPurchaseOrderFooter: defaultPurchaseOrderFooter, purchaseOrderNumberPattern: purchaseOrderNumberPattern, - purchaseOrderNumberCounter: purchaseOrderNumberCounter); + purchaseOrderNumberCounter: purchaseOrderNumberCounter, + qrIban: qrIban, + besrId: besrId); } catch (_) { String _$failedField; try { diff --git a/lib/ui/settings/company_details.dart b/lib/ui/settings/company_details.dart index acebabbe6..f4738f3e1 100644 --- a/lib/ui/settings/company_details.dart +++ b/lib/ui/settings/company_details.dart @@ -78,6 +78,8 @@ class _CompanyDetailsState extends State final _creditFooterController = TextEditingController(); final _purchaseOrderTermsController = TextEditingController(); final _purchaseOrderFooterController = TextEditingController(); + final _qrIbanController = TextEditingController(); + final _besrIdController = TextEditingController(); List _controllers = []; @@ -126,6 +128,8 @@ class _CompanyDetailsState extends State _creditTermsController, _purchaseOrderFooterController, _purchaseOrderTermsController, + _qrIbanController, + _besrIdController, ]; _controllers.forEach( @@ -157,6 +161,8 @@ class _CompanyDetailsState extends State _creditTermsController.text = settings.defaultCreditTerms; _purchaseOrderFooterController.text = settings.defaultPurchaseOrderFooter; _purchaseOrderTermsController.text = settings.defaultPurchaseOrderTerms; + _qrIbanController.text = settings.qrIban; + _besrIdController.text = settings.besrId; _controllers.forEach( (dynamic controller) => controller.addListener(_onSettingsChanged)); @@ -200,7 +206,9 @@ class _CompanyDetailsState extends State ..defaultCreditFooter = _creditFooterController.text.trim() ..defaultCreditTerms = _creditTermsController.text.trim() ..defaultPurchaseOrderFooter = _purchaseOrderFooterController.text.trim() - ..defaultPurchaseOrderTerms = _purchaseOrderTermsController.text.trim()); + ..defaultPurchaseOrderTerms = _purchaseOrderTermsController.text.trim() + ..qrIban = _qrIbanController.text.trim() + ..besrId = _besrIdController.text.trim()); if (settings != widget.viewModel.settings) { _debouncer.run(() { widget.viewModel.onSettingsChanged(settings); @@ -323,6 +331,23 @@ class _CompanyDetailsState extends State ), ], ), + if (company.supportsQrIban) + FormCard( + children: [ + DecoratedFormField( + label: localization.qrIban, + controller: _qrIbanController, + onSavePressed: viewModel.onSavePressed, + keyboardType: TextInputType.text, + ), + DecoratedFormField( + label: localization.besrId, + controller: _besrIdController, + onSavePressed: viewModel.onSavePressed, + keyboardType: TextInputType.text, + ), + ], + ), if (!state.settingsUIState.isFiltered) FormCard( isLast: true, diff --git a/lib/ui/settings/invoice_design.dart b/lib/ui/settings/invoice_design.dart index 8b999122e..edadd7874 100644 --- a/lib/ui/settings/invoice_design.dart +++ b/lib/ui/settings/invoice_design.dart @@ -62,10 +62,25 @@ class _InvoiceDesignState extends State @override void initState() { super.initState(); - final settingsUIState = widget.viewModel.state.settingsUIState; + final state = widget.viewModel.state; + final settingsUIState = state.settingsUIState; _focusNode = FocusScopeNode(); + + int tabs = 6; + + [ + EntityType.invoice, + EntityType.quote, + EntityType.credit, + EntityType.task, + ].forEach((entityType) { + if (state.company.isModuleEnabled(entityType)) { + tabs++; + } + }); + _controller = TabController( - vsync: this, length: 10, initialIndex: settingsUIState.tabIndex); + vsync: this, length: tabs, initialIndex: settingsUIState.tabIndex); _controller.addListener(_onTabChanged); } @@ -110,11 +125,15 @@ class _InvoiceDesignState extends State Tab(text: localization.clientDetails), Tab(text: localization.companyDetails), Tab(text: localization.companyAddress), - Tab(text: localization.invoiceDetails), - Tab(text: localization.quoteDetails), - Tab(text: localization.creditDetails), + if (company.isModuleEnabled(EntityType.invoice)) + Tab(text: localization.invoiceDetails), + if (company.isModuleEnabled(EntityType.quote)) + Tab(text: localization.quoteDetails), + if (company.isModuleEnabled(EntityType.credit)) + Tab(text: localization.creditDetails), Tab(text: localization.productColumns), - Tab(text: localization.taskColumns), + if (company.isModuleEnabled(EntityType.task)) + Tab(text: localization.taskColumns), Tab(text: localization.totalFields), ], ), @@ -579,119 +598,123 @@ class _InvoiceDesignState extends State prefix: 'company', ), ), - FormCard( - isLast: true, - child: MultiSelectList( - options: [ - ...[ + if (company.isModuleEnabled(EntityType.invoice)) + FormCard( + isLast: true, + child: MultiSelectList( + options: [ + ...[ + InvoiceFields.number, + InvoiceFields.poNumber, + InvoiceFields.date, + InvoiceFields.dueDate, + InvoiceFields.amount, + InvoiceFields.balance, + InvoiceFields.balanceDue, + InvoiceFields.customValue1, + InvoiceFields.customValue2, + InvoiceFields.customValue3, + InvoiceFields.customValue4, + InvoiceFields.project, + InvoiceFields.vendor, + ].map((field) => '\$invoice.$field'), + ...[ + ClientFields.balance, + ].map((field) => '\$client.$field') + ], + defaultSelected: [ InvoiceFields.number, InvoiceFields.poNumber, InvoiceFields.date, InvoiceFields.dueDate, - InvoiceFields.amount, - InvoiceFields.balance, + InvoiceFields.total, InvoiceFields.balanceDue, - InvoiceFields.customValue1, - InvoiceFields.customValue2, - InvoiceFields.customValue3, - InvoiceFields.customValue4, - InvoiceFields.project, - InvoiceFields.vendor, - ].map((field) => '\$invoice.$field'), - ...[ - ClientFields.balance, - ].map((field) => '\$client.$field') - ], - defaultSelected: [ - InvoiceFields.number, - InvoiceFields.poNumber, - InvoiceFields.date, - InvoiceFields.dueDate, - InvoiceFields.total, - InvoiceFields.balanceDue, - ].map((field) => '\$invoice.$field').toList(), - selected: settings.getFieldsForSection(kPdfFieldsInvoiceDetails), - onSelected: (values) { - viewModel.onSettingsChanged(settings.setFieldsForSection( - kPdfFieldsInvoiceDetails, values)); - }, - addTitle: localization.addField, - liveChanges: true, - prefix: 'invoice', + ].map((field) => '\$invoice.$field').toList(), + selected: + settings.getFieldsForSection(kPdfFieldsInvoiceDetails), + onSelected: (values) { + viewModel.onSettingsChanged(settings.setFieldsForSection( + kPdfFieldsInvoiceDetails, values)); + }, + addTitle: localization.addField, + liveChanges: true, + prefix: 'invoice', + ), ), - ), - FormCard( - isLast: true, - child: MultiSelectList( - options: [ - ...[ + if (company.isModuleEnabled(EntityType.quote)) + FormCard( + isLast: true, + child: MultiSelectList( + options: [ + ...[ + QuoteFields.number, + QuoteFields.poNumber, + QuoteFields.date, + QuoteFields.validUntil, + QuoteFields.total, + QuoteFields.customValue1, + QuoteFields.customValue2, + QuoteFields.customValue3, + QuoteFields.customValue4, + ].map((field) => '\$quote.$field'), + ...[ + ClientFields.balance, + ].map((field) => '\$client.$field') + ], + defaultSelected: [ QuoteFields.number, QuoteFields.poNumber, QuoteFields.date, QuoteFields.validUntil, QuoteFields.total, - QuoteFields.customValue1, - QuoteFields.customValue2, - QuoteFields.customValue3, - QuoteFields.customValue4, - ].map((field) => '\$quote.$field'), - ...[ - ClientFields.balance, - ].map((field) => '\$client.$field') - ], - defaultSelected: [ - QuoteFields.number, - QuoteFields.poNumber, - QuoteFields.date, - QuoteFields.validUntil, - QuoteFields.total, - ].map((field) => '\$quote.$field').toList(), - selected: settings.getFieldsForSection(kPdfFieldsQuoteDetails), - onSelected: (values) { - viewModel.onSettingsChanged(settings.setFieldsForSection( - kPdfFieldsQuoteDetails, values)); - }, - addTitle: localization.addField, - liveChanges: true, - prefix: 'quote', + ].map((field) => '\$quote.$field').toList(), + selected: settings.getFieldsForSection(kPdfFieldsQuoteDetails), + onSelected: (values) { + viewModel.onSettingsChanged(settings.setFieldsForSection( + kPdfFieldsQuoteDetails, values)); + }, + addTitle: localization.addField, + liveChanges: true, + prefix: 'quote', + ), ), - ), - FormCard( - isLast: true, - child: MultiSelectList( - options: [ - ...[ + if (company.isModuleEnabled(EntityType.credit)) + FormCard( + isLast: true, + child: MultiSelectList( + options: [ + ...[ + CreditFields.number, + CreditFields.poNumber, + CreditFields.date, + CreditFields.total, + CreditFields.balance, + CreditFields.customValue1, + CreditFields.customValue2, + CreditFields.customValue3, + CreditFields.customValue4, + ].map((field) => '\$credit.$field'), + ...[ + ClientFields.balance, + ].map((field) => '\$client.$field') + ], + defaultSelected: [ CreditFields.number, CreditFields.poNumber, CreditFields.date, - CreditFields.total, CreditFields.balance, - CreditFields.customValue1, - CreditFields.customValue2, - CreditFields.customValue3, - CreditFields.customValue4, - ].map((field) => '\$credit.$field'), - ...[ - ClientFields.balance, - ].map((field) => '\$client.$field') - ], - defaultSelected: [ - CreditFields.number, - CreditFields.poNumber, - CreditFields.date, - CreditFields.balance, - CreditFields.total, - ].map((field) => '\$credit.$field').toList(), - selected: settings.getFieldsForSection(kPdfFieldsCreditDetails), - onSelected: (values) { - viewModel.onSettingsChanged(settings.setFieldsForSection( - kPdfFieldsCreditDetails, values)); - }, - addTitle: localization.addField, - liveChanges: true, - prefix: 'credit', + CreditFields.total, + ].map((field) => '\$credit.$field').toList(), + selected: settings.getFieldsForSection(kPdfFieldsCreditDetails), + onSelected: (values) { + viewModel.onSettingsChanged(settings.setFieldsForSection( + kPdfFieldsCreditDetails, values)); + }, + addTitle: localization.addField, + liveChanges: true, + prefix: 'credit', + ), ), - ), FormCard( isLast: true, child: MultiSelectList( @@ -728,42 +751,43 @@ class _InvoiceDesignState extends State prefix: 'product', ), ), - FormCard( - isLast: true, - child: MultiSelectList( - options: [ - TaskItemFields.service, - TaskItemFields.description, - TaskItemFields.hours, - TaskItemFields.rate, - if (company.hasItemTaxes) TaskItemFields.tax, - if (company.enableProductDiscount) TaskItemFields.discount, - TaskItemFields.lineTotal, - TaskItemFields.custom1, - TaskItemFields.custom2, - TaskItemFields.custom3, - TaskItemFields.custom4, - TaskItemFields.grossLineTotal, - ].map((field) => '\$task.$field').toList(), - defaultSelected: [ - TaskItemFields.service, - TaskItemFields.description, - TaskItemFields.rate, - TaskItemFields.hours, - if (company.enableProductDiscount) TaskItemFields.discount, - if (company.hasItemTaxes) TaskItemFields.tax, - TaskItemFields.lineTotal, - ].map((field) => '\$task.$field').toList(), - selected: settings.getFieldsForSection(kPdfFieldsTaskColumns), - onSelected: (values) { - viewModel.onSettingsChanged(settings.setFieldsForSection( - kPdfFieldsTaskColumns, values)); - }, - addTitle: localization.addField, - liveChanges: true, - prefix: 'task', + if (company.isModuleEnabled(EntityType.task)) + FormCard( + isLast: true, + child: MultiSelectList( + options: [ + TaskItemFields.service, + TaskItemFields.description, + TaskItemFields.hours, + TaskItemFields.rate, + if (company.hasItemTaxes) TaskItemFields.tax, + if (company.enableProductDiscount) TaskItemFields.discount, + TaskItemFields.lineTotal, + TaskItemFields.custom1, + TaskItemFields.custom2, + TaskItemFields.custom3, + TaskItemFields.custom4, + TaskItemFields.grossLineTotal, + ].map((field) => '\$task.$field').toList(), + defaultSelected: [ + TaskItemFields.service, + TaskItemFields.description, + TaskItemFields.rate, + TaskItemFields.hours, + if (company.enableProductDiscount) TaskItemFields.discount, + if (company.hasItemTaxes) TaskItemFields.tax, + TaskItemFields.lineTotal, + ].map((field) => '\$task.$field').toList(), + selected: settings.getFieldsForSection(kPdfFieldsTaskColumns), + onSelected: (values) { + viewModel.onSettingsChanged(settings.setFieldsForSection( + kPdfFieldsTaskColumns, values)); + }, + addTitle: localization.addField, + liveChanges: true, + prefix: 'task', + ), ), - ), FormCard( isLast: true, child: MultiSelectList( diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 5ff8c070d..ae24baa4f 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -16,6 +16,8 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'qr_iban': 'QR IBAN', + 'besr_id': 'BESR ID', 'accept': 'Accept', 'clone_to_purchase_order': 'Clone to PO', 'vendor_email_not_set': 'Vendor does not have an email address set', @@ -70820,6 +70822,15 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['accept'] ?? _localizedValues['en']['accept']; + String get qrIban => + _localizedValues[localeCode]['qr_iban'] ?? + _localizedValues['en']['qr_iban']; + + String get besrId => + _localizedValues[localeCode]['besr_id'] ?? + _localizedValues['en']['besr_id']; + + // STARTER: lang field - do not remove comment String lookup(String key) {