Enhancement: Add option to select in/out field during import (#1788)

This commit is contained in:
Jesse Visser
2023-11-05 15:49:00 +01:00
committed by GitHub
parent a6dae398da
commit be18891957
2 changed files with 144 additions and 27 deletions

View File

@@ -193,11 +193,22 @@ function getInitialMappings(transactions) {
),
);
let inOutField = key(
fields.find(
([name, value]) =>
name !== dateField &&
name !== amountField &&
name !== payeeField &&
name !== notesField,
),
);
return {
date: dateField,
amount: amountField,
payee: payeeField,
notes: notesField,
inOut: inOutField,
};
}
@@ -222,7 +233,14 @@ function parseAmount(amount, mapper) {
return value;
}
function parseAmountFields(trans, splitMode, flipAmount, multiplierAmount) {
function parseAmountFields(
trans,
splitMode,
inOutMode,
outValue,
flipAmount,
multiplierAmount,
) {
const multiplier = parseFloat(multiplierAmount) || 1.0;
if (splitMode) {
@@ -240,6 +258,16 @@ function parseAmountFields(trans, splitMode, flipAmount, multiplierAmount) {
inflow,
};
}
if (inOutMode) {
return {
amount:
parseAmount(trans.amount, n =>
trans.inOut === outValue ? Math.abs(n) * -1 : Math.abs(n),
) * multiplier,
outflow: null,
inflow: null,
};
}
return {
amount:
parseAmount(trans.amount, n => (flipAmount ? n * -1 : n)) * multiplier,
@@ -255,6 +283,8 @@ function Transaction({
parseDateFormat,
dateFormat,
splitMode,
inOutMode,
outValue,
flipAmount,
multiplierAmount,
}) {
@@ -269,6 +299,8 @@ function Transaction({
let { amount, outflow, inflow } = parseAmountFields(
transaction,
splitMode,
inOutMode,
outValue,
flipAmount,
multiplierAmount,
);
@@ -320,13 +352,24 @@ function Transaction({
</Field>
</>
) : (
<Field
width={90}
contentStyle={{ textAlign: 'right', ...styles.tnum }}
title={amount}
>
{amount}
</Field>
<>
{inOutMode && (
<Field
width={90}
contentStyle={{ textAlign: 'left', ...styles.tnum }}
title={transaction.inOut}
>
{transaction.inOut}
</Field>
)}
<Field
width={90}
contentStyle={{ textAlign: 'right', ...styles.tnum }}
title={amount}
>
{amount}
</Field>
</>
)}
</Row>
);
@@ -457,11 +500,43 @@ function MultiplierOption({
);
}
function InOutOption({
inOutMode,
outValue,
disabled,
onToggle,
onChangeText,
}) {
return (
<View style={{ flexDirection: 'row', gap: 10, height: 28 }}>
<CheckboxOption
id="form_inOut"
checked={inOutMode}
disabled={disabled}
onChange={onToggle}
>
{inOutMode
? 'in/out identifier'
: 'Select column to specify if amount goes in/out'}
</CheckboxOption>
{inOutMode && (
<Input
type="text"
value={outValue}
onUpdate={onChangeText}
placeholder="Value for out rows, i.e. Credit"
/>
)}
</View>
);
}
function FieldMappings({
transactions,
mappings,
onChange,
splitMode,
inOutMode,
hasHeaderRow,
}) {
if (transactions.length === 0) {
@@ -537,16 +612,30 @@ function FieldMappings({
</View>
</>
) : (
<View style={{ flex: 1 }}>
<SubLabel title="Amount" />
<SelectField
options={options}
value={mappings.amount}
onChange={name => onChange('amount', name)}
hasHeaderRow={hasHeaderRow}
firstTransaction={transactions[0]}
/>
</View>
<>
{inOutMode && (
<View style={{ flex: 1 }}>
<SubLabel title="In/Out" />
<SelectField
options={options}
value={mappings.inOut}
onChange={name => onChange('inOut', name)}
hasHeaderRow={hasHeaderRow}
firstTransaction={transactions[0]}
/>
</View>
)}
<View style={{ flex: 1 }}>
<SubLabel title="Amount" />
<SelectField
options={options}
value={mappings.amount}
onChange={name => onChange('amount', name)}
hasHeaderRow={hasHeaderRow}
firstTransaction={transactions[0]}
/>
</View>
</>
)}
</Stack>
</View>
@@ -569,6 +658,8 @@ export default function ImportTransactions({ modalProps, options }) {
let [filetype, setFileType] = useState(null);
let [fieldMappings, setFieldMappings] = useState(null);
let [splitMode, setSplitMode] = useState(false);
let [inOutMode, setInOutMode] = useState(false);
let [outValue, setOutValue] = useState('');
let [flipAmount, setFlipAmount] = useState(false);
let [multiplierEnabled, setMultiplierEnabled] = useState(false);
let { accountId, onImported } = options;
@@ -684,6 +775,8 @@ export default function ImportTransactions({ modalProps, options }) {
let isSplit = !splitMode;
setSplitMode(isSplit);
setInOutMode(false);
setFlipAmount(false);
// Run auto-detection on the fields to try to detect the fields
// automatically
@@ -749,6 +842,8 @@ export default function ImportTransactions({ modalProps, options }) {
let { amount } = parseAmountFields(
trans,
splitMode,
inOutMode,
outValue,
flipAmount,
multiplierAmount,
);
@@ -757,7 +852,7 @@ export default function ImportTransactions({ modalProps, options }) {
break;
}
let { inflow, outflow, ...finalTransaction } = trans;
let { inflow, outflow, inOut, ...finalTransaction } = trans;
finalTransactions.push({
...finalTransaction,
date,
@@ -812,6 +907,9 @@ export default function ImportTransactions({ modalProps, options }) {
{ name: 'Notes', width: 'flex' },
];
if (inOutMode) {
headers.push({ name: 'In/Out', width: 90, style: { textAlign: 'left' } });
}
if (splitMode) {
headers.push({ name: 'Outflow', width: 90, style: { textAlign: 'right' } });
headers.push({ name: 'Inflow', width: 90, style: { textAlign: 'right' } });
@@ -873,6 +971,8 @@ export default function ImportTransactions({ modalProps, options }) {
dateFormat={dateFormat}
fieldMappings={fieldMappings}
splitMode={splitMode}
inOutMode={inOutMode}
outValue={outValue}
flipAmount={flipAmount}
multiplierAmount={multiplierAmount}
/>
@@ -905,6 +1005,7 @@ export default function ImportTransactions({ modalProps, options }) {
onChange={onUpdateFields}
mappings={fieldMappings}
splitMode={splitMode}
inOutMode={inOutMode}
hasHeaderRow={hasHeaderRow}
/>
</View>
@@ -1018,19 +1119,29 @@ export default function ImportTransactions({ modalProps, options }) {
<CheckboxOption
id="form_flip"
checked={flipAmount}
disabled={splitMode}
disabled={splitMode || inOutMode}
onChange={() => setFlipAmount(!flipAmount)}
>
Flip amount
</CheckboxOption>
{filetype === 'csv' && (
<CheckboxOption
id="form_split"
checked={splitMode}
onChange={onSplitMode}
>
Split amount into separate inflow/outflow columns
</CheckboxOption>
<>
<CheckboxOption
id="form_split"
checked={splitMode}
disabled={inOutMode || flipAmount}
onChange={onSplitMode}
>
Split amount into separate inflow/outflow columns
</CheckboxOption>
<InOutOption
inOutMode={inOutMode}
outValue={outValue}
disabled={splitMode || flipAmount}
onToggle={() => setInOutMode(!inOutMode)}
onChangeText={setOutValue}
/>
</>
)}
<MultiplierOption
multiplierEnabled={multiplierEnabled}

View File

@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [Jessseee]
---
Added option to select in/out field during import.