This commit is contained in:
Hillel Coren 2019-10-29 12:06:00 +02:00
parent 3f33299575
commit 1e111c1eef
14 changed files with 146 additions and 43 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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);

View File

@ -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());

View File

@ -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;

View File

@ -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(),
],
),
);
}
}

View File

@ -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,6 +36,9 @@ class InvoiceDesignVM {
@required this.state,
@required this.onSavePressed,
@required this.onCancelPressed,
@required this.settings,
@required this.onSettingsChanged,
});
static InvoiceDesignVM fromStore(Store<AppState> store) {
@ -36,12 +46,36 @@ class InvoiceDesignVM {
return InvoiceDesignVM(
state: state,
onSavePressed: null,
onCancelPressed: null,
);
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;
}

View File

@ -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(),
);
}

View File

@ -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] ??