mirror of
https://github.com/frappe/books.git
synced 2024-12-22 10:58:59 +00:00
fix: support option field value or label
- remove address placeholder - allow more types of entries to be imported
This commit is contained in:
parent
aa04e1493c
commit
48797dff62
@ -73,7 +73,6 @@
|
||||
"label": "Address",
|
||||
"fieldtype": "Link",
|
||||
"target": "Address",
|
||||
"placeholder": "Click to create",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
|
@ -40,7 +40,6 @@
|
||||
"label": "Address",
|
||||
"fieldtype": "Link",
|
||||
"target": "Address",
|
||||
"placeholder": "Click to create",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
|
@ -16,7 +16,6 @@
|
||||
"label": "Address",
|
||||
"fieldtype": "Link",
|
||||
"target": "Address",
|
||||
"placeholder": "Click to create",
|
||||
"inline": true
|
||||
}
|
||||
],
|
||||
|
@ -73,7 +73,6 @@
|
||||
"label": "Address",
|
||||
"fieldtype": "Link",
|
||||
"target": "Address",
|
||||
"placeholder": "Click to create",
|
||||
"inline": true
|
||||
}
|
||||
],
|
||||
|
@ -8,13 +8,17 @@ import {
|
||||
Field,
|
||||
FieldType,
|
||||
FieldTypeEnum,
|
||||
OptionField,
|
||||
RawValue,
|
||||
Schema,
|
||||
TargetField,
|
||||
} from 'schemas/types';
|
||||
import { generateCSV, parseCSV } from 'utils/csvParser';
|
||||
import { getValueMapFromList } from 'utils/index';
|
||||
|
||||
export type TemplateField = Field & {
|
||||
export type TemplateField = Field & TemplateFieldProps;
|
||||
|
||||
type TemplateFieldProps = {
|
||||
schemaName: string;
|
||||
schemaLabel: string;
|
||||
fieldKey: string;
|
||||
@ -82,6 +86,15 @@ export class Importer {
|
||||
*/
|
||||
docs: Doc[];
|
||||
|
||||
/**
|
||||
* Used if an options field is imported where the import data
|
||||
* provided maybe the label and not the value
|
||||
*/
|
||||
optionsMap: {
|
||||
values: Record<string, Set<string>>;
|
||||
labelValueMap: Record<string, Record<string, string>>;
|
||||
};
|
||||
|
||||
constructor(schemaName: string, fyo: Fyo) {
|
||||
if (!fyo.schemaMap[schemaName]) {
|
||||
throw new ValidationError(
|
||||
@ -94,6 +107,10 @@ export class Importer {
|
||||
this.fyo = fyo;
|
||||
this.docs = [];
|
||||
this.valueMatrix = [];
|
||||
this.optionsMap = {
|
||||
values: {},
|
||||
labelValueMap: {},
|
||||
};
|
||||
|
||||
const templateFields = getTemplateFields(schemaName, fyo, this);
|
||||
this.assignedTemplateFields = templateFields.map((f) => f.fieldKey);
|
||||
@ -423,6 +440,10 @@ export class Importer {
|
||||
return vmi;
|
||||
}
|
||||
|
||||
if ('options' in tf && typeof vmi.rawValue === 'string') {
|
||||
return this.getOptionFieldVmi(vmi, tf);
|
||||
}
|
||||
|
||||
try {
|
||||
vmi.value = Converter.toDocValue(rawValue, tf, this.fyo);
|
||||
} catch {
|
||||
@ -432,6 +453,39 @@ export class Importer {
|
||||
return vmi;
|
||||
}
|
||||
|
||||
getOptionFieldVmi(
|
||||
{ rawValue }: ValueMatrixItem,
|
||||
tf: OptionField & TemplateFieldProps
|
||||
): ValueMatrixItem {
|
||||
if (typeof rawValue !== 'string') {
|
||||
return { error: true, value: null, rawValue };
|
||||
}
|
||||
|
||||
if (!tf?.options.length) {
|
||||
return { value: null, rawValue };
|
||||
}
|
||||
|
||||
if (!this.optionsMap.labelValueMap[tf.fieldKey]) {
|
||||
const values = new Set(tf.options.map(({ value }) => value));
|
||||
const labelValueMap = getValueMapFromList(tf.options, 'label', 'value');
|
||||
|
||||
this.optionsMap.labelValueMap[tf.fieldKey] = labelValueMap;
|
||||
this.optionsMap.values[tf.fieldKey] = values;
|
||||
}
|
||||
|
||||
const hasValue = this.optionsMap.values[tf.fieldKey].has(rawValue);
|
||||
if (hasValue) {
|
||||
return { value: rawValue, rawValue };
|
||||
}
|
||||
|
||||
const value = this.optionsMap.labelValueMap[tf.fieldKey][rawValue];
|
||||
if (value) {
|
||||
return { value, rawValue };
|
||||
}
|
||||
|
||||
return { error: true, value: null, rawValue };
|
||||
}
|
||||
|
||||
assignTemplateFieldsFromParsedRow(row: string[]): boolean {
|
||||
const isKeyRow = row.some((key) => this.templateFieldsMap.has(key));
|
||||
if (!isKeyRow) {
|
||||
@ -550,6 +604,10 @@ function getTemplateFields(
|
||||
tf.readOnly = false;
|
||||
}
|
||||
|
||||
if (schema.isChild && tf.fieldname === 'name') {
|
||||
tf.required = false;
|
||||
}
|
||||
|
||||
const schemaName = schema.name;
|
||||
const schemaLabel = schema.label;
|
||||
const fieldKey = `${schema.name}.${field.fieldname}`;
|
||||
|
@ -4,12 +4,12 @@
|
||||
<PageHeader :title="t`Import Wizard`">
|
||||
<DropdownWithActions
|
||||
:actions="actions"
|
||||
v-if="hasImporter && !complete"
|
||||
v-if="hasImporter"
|
||||
:disabled="isMakingEntries"
|
||||
:title="t`More`"
|
||||
/>
|
||||
<Button
|
||||
v-if="hasImporter && !complete"
|
||||
v-if="hasImporter"
|
||||
:title="t`Add Row`"
|
||||
@click="() => importer.addRow()"
|
||||
:disabled="isMakingEntries"
|
||||
@ -18,7 +18,7 @@
|
||||
<feather-icon name="plus" class="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
v-if="hasImporter && !complete"
|
||||
v-if="hasImporter"
|
||||
:title="t`Save Template`"
|
||||
@click="saveTemplate"
|
||||
:icon="true"
|
||||
@ -45,7 +45,7 @@
|
||||
</PageHeader>
|
||||
|
||||
<!-- Main Body of the Wizard -->
|
||||
<div class="flex text-base w-full flex-col" v-if="!complete">
|
||||
<div class="flex text-base w-full flex-col">
|
||||
<!-- Select Import Type -->
|
||||
<div
|
||||
class="
|
||||
@ -367,16 +367,16 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { DocValue } from 'fyo/core/types';
|
||||
import { RawValue } from 'schemas/types';
|
||||
import { Action as BaseAction } from 'fyo/model/types';
|
||||
import { ValidationError } from 'fyo/utils/errors';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { OptionField, SelectOption } from 'schemas/types';
|
||||
import { OptionField, RawValue, SelectOption } from 'schemas/types';
|
||||
import Button from 'src/components/Button.vue';
|
||||
import AutoComplete from 'src/components/Controls/AutoComplete.vue';
|
||||
import Check from 'src/components/Controls/Check.vue';
|
||||
import Data from 'src/components/Controls/Data.vue';
|
||||
import FormControl from 'src/components/Controls/FormControl.vue';
|
||||
import Select from 'src/components/Controls/Select.vue';
|
||||
import DropdownWithActions from 'src/components/DropdownWithActions.vue';
|
||||
import FormHeader from 'src/components/FormHeader.vue';
|
||||
import Modal from 'src/components/Modal.vue';
|
||||
@ -389,8 +389,6 @@ import { docsPathRef } from 'src/utils/refs';
|
||||
import { showMessageDialog } from 'src/utils/ui';
|
||||
import { defineComponent } from 'vue';
|
||||
import Loading from '../components/Loading.vue';
|
||||
import Select from 'src/components/Controls/Select.vue';
|
||||
import { isWeakMap } from 'lodash';
|
||||
|
||||
type Action = Pick<BaseAction, 'condition' | 'component'> & {
|
||||
action: Function;
|
||||
@ -443,7 +441,6 @@ export default defineComponent({
|
||||
if (fyo.store.isDevelopment) {
|
||||
// @ts-ignore
|
||||
window.iw = this;
|
||||
this.setImportType('Item');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -532,14 +529,13 @@ export default defineComponent({
|
||||
return this.numColumnsPicked;
|
||||
}
|
||||
|
||||
let vmColumnCount = 0;
|
||||
if (this.importer.valueMatrix.length) {
|
||||
vmColumnCount = this.importer.valueMatrix[0].length;
|
||||
if (!this.importer.valueMatrix.length) {
|
||||
return this.importer.assignedTemplateFields.length;
|
||||
}
|
||||
|
||||
return Math.min(
|
||||
this.importer.assignedTemplateFields.length,
|
||||
vmColumnCount
|
||||
this.importer.valueMatrix[0].length
|
||||
);
|
||||
},
|
||||
columnIterator(): number[] {
|
||||
@ -587,6 +583,10 @@ export default defineComponent({
|
||||
ModelNameEnum.Party,
|
||||
ModelNameEnum.Item,
|
||||
ModelNameEnum.JournalEntry,
|
||||
ModelNameEnum.Tax,
|
||||
ModelNameEnum.Account,
|
||||
ModelNameEnum.Address,
|
||||
ModelNameEnum.NumberSeries,
|
||||
];
|
||||
|
||||
const hasInventory = fyo.doc.singles.AccountingSettings?.enableInventory;
|
||||
|
@ -6,7 +6,7 @@ export function getValueMapFromList<T, K extends keyof T, V extends keyof T>(
|
||||
key: K,
|
||||
valueKey: V,
|
||||
filterUndefined: boolean = true
|
||||
): Record<string, unknown> {
|
||||
): Record<string, T[V]> {
|
||||
if (filterUndefined) {
|
||||
list = list.filter(
|
||||
(f) =>
|
||||
@ -20,7 +20,7 @@ export function getValueMapFromList<T, K extends keyof T, V extends keyof T>(
|
||||
const value = f[valueKey];
|
||||
acc[keyValue] = value;
|
||||
return acc;
|
||||
}, {} as Record<string, unknown>);
|
||||
}, {} as Record<string, T[V]>);
|
||||
}
|
||||
|
||||
export function getRandomString(): string {
|
||||
|
Loading…
Reference in New Issue
Block a user