Add QR IBAN
This commit is contained in:
parent
3cf9cbdfac
commit
a222e93d0d
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -78,6 +78,8 @@ class _CompanyDetailsState extends State<CompanyDetails>
|
|||
final _creditFooterController = TextEditingController();
|
||||
final _purchaseOrderTermsController = TextEditingController();
|
||||
final _purchaseOrderFooterController = TextEditingController();
|
||||
final _qrIbanController = TextEditingController();
|
||||
final _besrIdController = TextEditingController();
|
||||
|
||||
List<TextEditingController> _controllers = [];
|
||||
|
||||
|
|
@ -126,6 +128,8 @@ class _CompanyDetailsState extends State<CompanyDetails>
|
|||
_creditTermsController,
|
||||
_purchaseOrderFooterController,
|
||||
_purchaseOrderTermsController,
|
||||
_qrIbanController,
|
||||
_besrIdController,
|
||||
];
|
||||
|
||||
_controllers.forEach(
|
||||
|
|
@ -157,6 +161,8 @@ class _CompanyDetailsState extends State<CompanyDetails>
|
|||
_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<CompanyDetails>
|
|||
..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<CompanyDetails>
|
|||
),
|
||||
],
|
||||
),
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -62,10 +62,25 @@ class _InvoiceDesignState extends State<InvoiceDesign>
|
|||
@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<InvoiceDesign>
|
|||
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<InvoiceDesign>
|
|||
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<InvoiceDesign>
|
|||
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(
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
static final Map<String, Map<String, String>> _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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue