Settings
This commit is contained in:
parent
3f33299575
commit
1e111c1eef
|
|
@ -497,7 +497,7 @@ abstract class InvoiceItemEntity extends Object
|
|||
productKey: '',
|
||||
notes: '',
|
||||
cost: 0.0,
|
||||
qty: 0.0,
|
||||
quantity: 0.0,
|
||||
taxName1: '',
|
||||
taxRate1: 0.0,
|
||||
taxName2: '',
|
||||
|
|
@ -526,7 +526,7 @@ abstract class InvoiceItemEntity extends Object
|
|||
|
||||
double get cost;
|
||||
|
||||
double get qty;
|
||||
double get quantity;
|
||||
|
||||
@BuiltValueField(wireName: 'tax_name1')
|
||||
String get taxName1;
|
||||
|
|
@ -559,7 +559,7 @@ abstract class InvoiceItemEntity extends Object
|
|||
@BuiltValueField(wireName: 'expense_public_id')
|
||||
String get expenseId;
|
||||
|
||||
double get total => round(qty * cost, 2);
|
||||
double get total => round(quantity * cost, 2);
|
||||
|
||||
bool get isTask => taskId != null && taskId.isNotEmpty;
|
||||
|
||||
|
|
|
|||
|
|
@ -512,8 +512,9 @@ class _$InvoiceItemEntitySerializer
|
|||
specifiedType: const FullType(String)),
|
||||
'cost',
|
||||
serializers.serialize(object.cost, specifiedType: const FullType(double)),
|
||||
'qty',
|
||||
serializers.serialize(object.qty, specifiedType: const FullType(double)),
|
||||
'quantity',
|
||||
serializers.serialize(object.quantity,
|
||||
specifiedType: const FullType(double)),
|
||||
'tax_name1',
|
||||
serializers.serialize(object.taxName1,
|
||||
specifiedType: const FullType(String)),
|
||||
|
|
@ -620,8 +621,8 @@ class _$InvoiceItemEntitySerializer
|
|||
result.cost = serializers.deserialize(value,
|
||||
specifiedType: const FullType(double)) as double;
|
||||
break;
|
||||
case 'qty':
|
||||
result.qty = serializers.deserialize(value,
|
||||
case 'quantity':
|
||||
result.quantity = serializers.deserialize(value,
|
||||
specifiedType: const FullType(double)) as double;
|
||||
break;
|
||||
case 'tax_name1':
|
||||
|
|
@ -1761,7 +1762,7 @@ class _$InvoiceItemEntity extends InvoiceItemEntity {
|
|||
@override
|
||||
final double cost;
|
||||
@override
|
||||
final double qty;
|
||||
final double quantity;
|
||||
@override
|
||||
final String taxName1;
|
||||
@override
|
||||
|
|
@ -1805,7 +1806,7 @@ class _$InvoiceItemEntity extends InvoiceItemEntity {
|
|||
{this.productKey,
|
||||
this.notes,
|
||||
this.cost,
|
||||
this.qty,
|
||||
this.quantity,
|
||||
this.taxName1,
|
||||
this.taxRate1,
|
||||
this.taxName2,
|
||||
|
|
@ -1833,8 +1834,8 @@ class _$InvoiceItemEntity extends InvoiceItemEntity {
|
|||
if (cost == null) {
|
||||
throw new BuiltValueNullFieldError('InvoiceItemEntity', 'cost');
|
||||
}
|
||||
if (qty == null) {
|
||||
throw new BuiltValueNullFieldError('InvoiceItemEntity', 'qty');
|
||||
if (quantity == null) {
|
||||
throw new BuiltValueNullFieldError('InvoiceItemEntity', 'quantity');
|
||||
}
|
||||
if (taxName1 == null) {
|
||||
throw new BuiltValueNullFieldError('InvoiceItemEntity', 'taxName1');
|
||||
|
|
@ -1878,7 +1879,7 @@ class _$InvoiceItemEntity extends InvoiceItemEntity {
|
|||
productKey == other.productKey &&
|
||||
notes == other.notes &&
|
||||
cost == other.cost &&
|
||||
qty == other.qty &&
|
||||
quantity == other.quantity &&
|
||||
taxName1 == other.taxName1 &&
|
||||
taxRate1 == other.taxRate1 &&
|
||||
taxName2 == other.taxName2 &&
|
||||
|
|
@ -1920,7 +1921,7 @@ class _$InvoiceItemEntity extends InvoiceItemEntity {
|
|||
$jc(
|
||||
$jc($jc($jc(0, productKey.hashCode), notes.hashCode),
|
||||
cost.hashCode),
|
||||
qty.hashCode),
|
||||
quantity.hashCode),
|
||||
taxName1.hashCode),
|
||||
taxRate1.hashCode),
|
||||
taxName2.hashCode),
|
||||
|
|
@ -1946,7 +1947,7 @@ class _$InvoiceItemEntity extends InvoiceItemEntity {
|
|||
..add('productKey', productKey)
|
||||
..add('notes', notes)
|
||||
..add('cost', cost)
|
||||
..add('qty', qty)
|
||||
..add('quantity', quantity)
|
||||
..add('taxName1', taxName1)
|
||||
..add('taxRate1', taxRate1)
|
||||
..add('taxName2', taxName2)
|
||||
|
|
@ -1984,9 +1985,9 @@ class InvoiceItemEntityBuilder
|
|||
double get cost => _$this._cost;
|
||||
set cost(double cost) => _$this._cost = cost;
|
||||
|
||||
double _qty;
|
||||
double get qty => _$this._qty;
|
||||
set qty(double qty) => _$this._qty = qty;
|
||||
double _quantity;
|
||||
double get quantity => _$this._quantity;
|
||||
set quantity(double quantity) => _$this._quantity = quantity;
|
||||
|
||||
String _taxName1;
|
||||
String get taxName1 => _$this._taxName1;
|
||||
|
|
@ -2064,7 +2065,7 @@ class InvoiceItemEntityBuilder
|
|||
_productKey = _$v.productKey;
|
||||
_notes = _$v.notes;
|
||||
_cost = _$v.cost;
|
||||
_qty = _$v.qty;
|
||||
_quantity = _$v.quantity;
|
||||
_taxName1 = _$v.taxName1;
|
||||
_taxRate1 = _$v.taxRate1;
|
||||
_taxName2 = _$v.taxName2;
|
||||
|
|
@ -2107,7 +2108,7 @@ class InvoiceItemEntityBuilder
|
|||
productKey: productKey,
|
||||
notes: notes,
|
||||
cost: cost,
|
||||
qty: qty,
|
||||
quantity: quantity,
|
||||
taxName1: taxName1,
|
||||
taxRate1: taxRate1,
|
||||
taxName2: taxName2,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ abstract class CalculateInvoiceTotal {
|
|||
final map = <String, double>{};
|
||||
|
||||
invoiceItems.forEach((item) {
|
||||
final double qty = round(item.qty, 4);
|
||||
final double qty = round(item.quantity, 4);
|
||||
final double cost = round(item.cost, 4);
|
||||
final double itemDiscount = round(item.discount, 2);
|
||||
final double taxRate1 = round(item.taxRate1, 3);
|
||||
|
|
@ -108,7 +108,7 @@ abstract class CalculateInvoiceTotal {
|
|||
double itemTax = 0.0;
|
||||
|
||||
invoiceItems.forEach((item) {
|
||||
final double qty = round(item.qty, 4);
|
||||
final double qty = round(item.quantity, 4);
|
||||
final double cost = round(item.cost, 4);
|
||||
final double itemDiscount = round(item.discount, 2);
|
||||
final double taxRate1 = round(item.taxRate1, 3);
|
||||
|
|
@ -177,7 +177,7 @@ abstract class CalculateInvoiceTotal {
|
|||
var total = 0.0;
|
||||
|
||||
invoiceItems.forEach((item) {
|
||||
final double qty = round(item.qty, 4);
|
||||
final double qty = round(item.quantity, 4);
|
||||
final double cost = round(item.cost, 4);
|
||||
final double discount = round(item.discount, 2);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:core';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:invoiceninja_flutter/.env.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
|
|
@ -39,7 +40,7 @@ class WebClient {
|
|||
{dynamic data, String filePath, String fileIndex}) async {
|
||||
url = _checkUrl(url);
|
||||
print('POST: $url');
|
||||
print('Data: $data');
|
||||
debugPrint('Data: $data');
|
||||
http.Response response;
|
||||
|
||||
if (filePath != null) {
|
||||
|
|
@ -60,7 +61,7 @@ class WebClient {
|
|||
{dynamic data, String filePath, String fileIndex = 'file'}) async {
|
||||
url = _checkUrl(url);
|
||||
print('PUT: $url');
|
||||
print('Data: $data');
|
||||
debugPrint('Data: $data');
|
||||
|
||||
http.Response response;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ InvoiceItemEntity convertExpenseToInvoiceItem(
|
|||
..expenseId = expense.id
|
||||
..productKey = categoryMap[expense.categoryId]?.name ?? ''
|
||||
..notes = expense.publicNotes
|
||||
..qty = 1
|
||||
..quantity = 1
|
||||
..cost = expense.convertedAmount
|
||||
..taxName1 = expense.taxName1
|
||||
..taxRate1 = expense.taxRate1
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ InvoiceItemEntity convertProductToInvoiceItem(
|
|||
..productKey = product.productKey
|
||||
..notes = product.notes
|
||||
..cost = product.price
|
||||
..qty = product.quantity
|
||||
..quantity = product.quantity
|
||||
..customValue1 = product.customValue1
|
||||
..customValue2 = product.customValue2
|
||||
..taxName1 = product.taxName1
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ InvoiceItemEntity convertTaskToInvoiceItem(
|
|||
..notes = notes
|
||||
..cost = taskRateSelector(
|
||||
company: state.selectedCompany, project: project, client: client)
|
||||
..qty = round(task.duration / 3600, 3));
|
||||
..quantity = round(task.duration / 3600, 3));
|
||||
}
|
||||
|
||||
var memoizedTaskList = memo2(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class InvoiceItemListTile extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final String cost =
|
||||
formatNumber(invoiceItem.cost, context, clientId: invoice.clientId);
|
||||
final String qty = formatNumber(invoiceItem.qty, context,
|
||||
final String qty = formatNumber(invoiceItem.quantity, context,
|
||||
clientId: invoice.clientId, formatNumberType: FormatNumberType.double);
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class ItemEditDetailsState extends State<ItemEditDetails> {
|
|||
_notesController.text = invoiceItem.notes;
|
||||
_costController.text = formatNumber(invoiceItem.cost, context,
|
||||
formatNumberType: FormatNumberType.input);
|
||||
_qtyController.text = formatNumber(invoiceItem.qty, context,
|
||||
_qtyController.text = formatNumber(invoiceItem.quantity, context,
|
||||
formatNumberType: FormatNumberType.input);
|
||||
_discountController.text = formatNumber(invoiceItem.discount, context,
|
||||
formatNumberType: FormatNumberType.input);
|
||||
|
|
@ -164,7 +164,7 @@ class ItemEditDetailsState extends State<ItemEditDetails> {
|
|||
..productKey = _productKeyController.text.trim()
|
||||
..notes = _notesController.text
|
||||
..cost = parseDouble(_costController.text)
|
||||
..qty = parseDouble(_qtyController.text)
|
||||
..quantity = parseDouble(_qtyController.text)
|
||||
..discount = parseDouble(_discountController.text)
|
||||
..customValue1 = _custom1Controller.text.trim()
|
||||
..customValue2 = _custom2Controller.text.trim());
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class _InvoiceItemSelectorState extends State<InvoiceItemSelector>
|
|||
} else {
|
||||
items.add(InvoiceItemEntity().rebuild((b) => b
|
||||
..productKey = product.productKey
|
||||
..qty = 1));
|
||||
..quantity = 1));
|
||||
}
|
||||
} else if (entity.entityType == EntityType.task) {
|
||||
final task = entity as TaskEntity;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
||||
import 'package:invoiceninja_flutter/ui/settings/invoice_design_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
@ -18,11 +20,10 @@ class InvoiceDesign extends StatefulWidget {
|
|||
|
||||
class _InvoiceDesignState extends State<InvoiceDesign>
|
||||
with SingleTickerProviderStateMixin {
|
||||
//static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
|
||||
TabController _controller;
|
||||
|
||||
bool autoValidate = false;
|
||||
FocusScopeNode _focusNode;
|
||||
|
||||
final _nameController = TextEditingController();
|
||||
|
||||
|
|
@ -31,12 +32,14 @@ class _InvoiceDesignState extends State<InvoiceDesign>
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_focusNode = FocusScopeNode();
|
||||
_controller = TabController(vsync: this, length: 3);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
_focusNode.dispose();
|
||||
_controllers.forEach((dynamic controller) {
|
||||
controller.removeListener(_onChanged);
|
||||
controller.dispose();
|
||||
|
|
@ -75,12 +78,70 @@ class _InvoiceDesignState extends State<InvoiceDesign>
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
//final viewModel = widget.viewModel;
|
||||
final viewModel = widget.viewModel;
|
||||
final state = viewModel.state;
|
||||
//final settings = viewModel.;
|
||||
|
||||
return SettingsScaffold(
|
||||
title: localization.invoiceDesign,
|
||||
onSavePressed: null,
|
||||
body: SizedBox(),
|
||||
onSavePressed: viewModel.onSavePressed,
|
||||
appBarBottom: TabBar(
|
||||
key: ValueKey(state.settingsUIState.updatedAt),
|
||||
controller: _controller,
|
||||
tabs: [
|
||||
Tab(
|
||||
text: localization.settings,
|
||||
),
|
||||
Tab(
|
||||
text: localization.invoiceFields,
|
||||
),
|
||||
Tab(
|
||||
text: localization.productFields,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: AppTabForm(
|
||||
tabController: _controller,
|
||||
formKey: _formKey,
|
||||
focusNode: _focusNode,
|
||||
children: <Widget>[
|
||||
ListView(children: <Widget>[
|
||||
FormCard(
|
||||
children: <Widget>[
|
||||
/*
|
||||
InputDecorator(
|
||||
decoration: InputDecoration(
|
||||
labelText: localization.firstMonthOfTheYear,
|
||||
),
|
||||
//isEmpty: company.financialYearStart == null,
|
||||
child: DropdownButtonHideUnderline(
|
||||
child: DropdownButton<int>(
|
||||
value: company.financialYearStart,
|
||||
isExpanded: true,
|
||||
isDense: true,
|
||||
onChanged: (value) => viewModel.onCompanyChanged(company
|
||||
.rebuild((b) => b..financialYearStart = value)),
|
||||
items: kMonthsOfTheYear
|
||||
.map((id, month) =>
|
||||
MapEntry<int, DropdownMenuItem<int>>(
|
||||
id,
|
||||
DropdownMenuItem<int>(
|
||||
child: Text(localization.lookup(month)),
|
||||
value: id,
|
||||
)))
|
||||
.values
|
||||
.toList()),
|
||||
),
|
||||
)
|
||||
|
||||
*/
|
||||
],
|
||||
),
|
||||
]),
|
||||
ListView(),
|
||||
ListView(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/company_model.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/settings/invoice_design.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
|
||||
|
|
@ -29,19 +36,46 @@ class InvoiceDesignVM {
|
|||
@required this.state,
|
||||
@required this.onSavePressed,
|
||||
@required this.onCancelPressed,
|
||||
@required this.settings,
|
||||
@required this.onSettingsChanged,
|
||||
|
||||
});
|
||||
|
||||
static InvoiceDesignVM fromStore(Store<AppState> store) {
|
||||
final state = store.state;
|
||||
|
||||
return InvoiceDesignVM(
|
||||
state: state,
|
||||
onSavePressed: null,
|
||||
onCancelPressed: null,
|
||||
);
|
||||
state: state,
|
||||
settings: state.uiState.settingsUIState.settings,
|
||||
onSettingsChanged: (settings) {
|
||||
store.dispatch(UpdateSettings(settings: settings));
|
||||
},
|
||||
onCancelPressed: (context) => store.dispatch(ResetSettings()),
|
||||
onSavePressed: (context) {
|
||||
final settingsUIState = state.uiState.settingsUIState;
|
||||
final completer = snackBarCompleter(
|
||||
context, AppLocalization.of(context).savedSettings);
|
||||
switch (settingsUIState.entityType) {
|
||||
case EntityType.company:
|
||||
store.dispatch(SaveCompanyRequest(
|
||||
completer: completer,
|
||||
company: settingsUIState.userCompany.company));
|
||||
break;
|
||||
case EntityType.group:
|
||||
store.dispatch(SaveGroupRequest(
|
||||
completer: completer, group: settingsUIState.group));
|
||||
break;
|
||||
case EntityType.client:
|
||||
store.dispatch(SaveClientRequest(
|
||||
completer: completer, client: settingsUIState.client));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
final SettingsEntity settings;
|
||||
final Function(SettingsEntity) onSettingsChanged;
|
||||
final Function(BuildContext) onSavePressed;
|
||||
final Function(BuildContext) onCancelPressed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,11 +75,11 @@ class _TaxRatesState extends State<TaxRates>
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
//final viewModel = widget.viewModel;
|
||||
final viewModel = widget.viewModel;
|
||||
|
||||
return SettingsScaffold(
|
||||
title: localization.taxRates,
|
||||
onSavePressed: null,
|
||||
onSavePressed: viewModel.onSavePressed,
|
||||
body: SizedBox(),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ abstract class LocaleCodeAware {
|
|||
mixin LocalizationsProvider on LocaleCodeAware {
|
||||
static final Map<String, Map<String, String>> _localizedValues = {
|
||||
'en': {
|
||||
'invoice_fields': 'Invoice Fields',
|
||||
'product_fields': 'Product Fields',
|
||||
'invoice_terms': 'Invoice Terms',
|
||||
'invoice_footer': 'Invoice Footer',
|
||||
'quote_terms': 'Quote Terms',
|
||||
|
|
@ -15302,6 +15304,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get quoteFooter => _localizedValues[localeCode]['quote_footer'];
|
||||
|
||||
String get invoiceFields => _localizedValues[localeCode]['invoice_fields'];
|
||||
|
||||
String get productFields => _localizedValues[localeCode]['product_fields'];
|
||||
|
||||
String lookup(String key) {
|
||||
final lookupKey = toSnakeCase(key);
|
||||
return _localizedValues[localeCode][lookupKey] ??
|
||||
|
|
|
|||
Loading…
Reference in New Issue