2
0
mirror of https://github.com/frappe/books.git synced 2024-11-08 14:50:56 +00:00

incr: add keyword fields, start with doc search

This commit is contained in:
18alantom 2022-05-04 21:55:08 +05:30
parent eedb4415ce
commit a0f812e1a8
21 changed files with 190 additions and 51 deletions

View File

@ -243,8 +243,9 @@ export default class DatabaseCore extends DatabaseBase {
}
const hasCreated = !!schema.fields.find((f) => f.fieldname === 'created');
const {
fields = ['name', ...(schema.keywordFields ?? [])],
fields = ['name'],
filters,
offset,
limit,

View File

@ -143,13 +143,5 @@
"readOnly": true
}
],
"quickEditFields": [
"name",
"rootType",
"parentAccount",
"accountType",
"isGroup",
"balance"
],
"keywordFields": ["name", "rootType", "accountType"]
"quickEditFields": ["name", "rootType", "parentAccount", "accountType", "isGroup", "balance"]
}

View File

@ -83,6 +83,5 @@
"balance",
"reverted",
"reverts"
],
"keywordFields": ["account", "party", "referenceName"]
]
}

View File

@ -76,13 +76,5 @@
"country",
"postalCode"
],
"keywordFields": [
"addressLine1",
"addressLine2",
"city",
"state",
"country",
"postalCode"
],
"inlineEditDisplayField": "addressDisplay"
}

View File

@ -18,6 +18,5 @@
"required": true,
"target": "Address"
}
],
"keywordFields": ["companyName"]
]
}

View File

@ -30,6 +30,5 @@
"fieldtype": "Data"
}
],
"keywordFields": ["name", "symbol"],
"quickEditFields": ["name", "symbol"]
}

View File

@ -135,5 +135,5 @@
"expenseAccount",
"hsnCode"
],
"keywordFields": ["name", "description"]
"keywordFields": ["name", "itemType", "for"]
}

View File

@ -90,7 +90,7 @@
"fieldname": "userRemark",
"label": "User Remark",
"fieldtype": "Text",
"placeholder": "User Remark"
"placeholder": "Add a remark"
},
{
"fieldname": "numberSeries",
@ -100,5 +100,6 @@
"required": true,
"default": "JV-"
}
]
}
],
"keywordFields": ["name", "entryType"]
}

View File

@ -23,5 +23,6 @@
"fieldtype": "Currency"
}
],
"tableFields": ["account", "debit", "credit"]
}
"tableFields": ["account", "debit", "credit"],
"keywordFields": ["account"]
}

View File

@ -59,6 +59,5 @@
"readOnly": true
}
],
"quickEditFields": ["referenceType", "start", "padZeros"],
"keywordFields": []
"quickEditFields": ["referenceType", "start", "padZeros"]
}

View File

@ -90,5 +90,5 @@
"role",
"taxId"
],
"keywordFields": ["name"]
"keywordFields": ["name", "email", "role"]
}

View File

@ -36,5 +36,6 @@
"required": true
}
],
"tableFields": ["referenceType", "referenceName", "amount"]
"tableFields": ["referenceType", "referenceName", "amount"],
"keywordFields": ["referenceName", "referenceType"]
}

View File

@ -105,5 +105,5 @@
"default": "PINV-"
}
],
"keywordFields": ["name", "party", "numberSeries"]
"keywordFields": ["name", "party"]
}

View File

@ -68,5 +68,6 @@
"placeholder": "HSN/SAC Code"
}
],
"tableFields": ["item", "tax", "quantity", "rate", "amount"]
"tableFields": ["item", "tax", "quantity", "rate", "amount"],
"keywordFields": ["item", "tax"]
}

View File

@ -4,7 +4,6 @@
"isSingle": false,
"isChild": false,
"isSubmittable": true,
"keywordFields": ["name", "party"],
"fields": [
{
"label": "Invoice No",
@ -93,6 +92,7 @@
{
"fieldname": "terms",
"label": "Notes",
"placeholder": "Add invoice terms",
"fieldtype": "Text"
},
{
@ -103,5 +103,6 @@
"required": true,
"default": "SINV-"
}
]
],
"keywordFields": ["name", "party"]
}

View File

@ -69,5 +69,6 @@
"placeholder": "HSN/SAC Code"
}
],
"tableFields": ["item", "tax", "quantity", "rate", "amount"]
"tableFields": ["item", "tax", "quantity", "rate", "amount"],
"keywordFields": ["item", "tax"]
}

View File

@ -22,6 +22,5 @@
"fieldtype": "Data",
"required": true
}
],
"keywordFields": []
}
]
}

View File

@ -90,12 +90,5 @@
"required": true
}
],
"quickEditFields": [
"locale",
"dateFormat",
"currency",
"displayPrecision",
"hideGetStarted"
],
"keywordFields": []
"quickEditFields": ["locale", "dateFormat", "currency", "displayPrecision", "hideGetStarted"]
}

View File

@ -48,7 +48,6 @@ export default {
'name',
schema.titleField,
this.df.groupBy,
...schema.keywordFields,
]),
].filter(Boolean);

View File

@ -108,7 +108,7 @@ function getListConfig(schemaName) {
const listConfig = fyo.models[schemaName]?.getListViewSettings?.(fyo);
if (listConfig?.columns === undefined) {
return {
columns: fyo.schemaMap[schemaName].keywordFields ?? ['name'],
columns: ['name'],
};
}
return listConfig;

View File

@ -1,7 +1,10 @@
import { t } from 'fyo';
import { DocValueMap } from 'fyo/core/types';
import { ModelNameEnum } from 'models/types';
import reports from 'reports/view';
import { OptionField } from 'schemas/types';
import { fyo } from 'src/initFyo';
import { GetAllOptions } from 'utils/db/types';
import { routeTo } from './ui';
export const searchGroups = ['Docs', 'List', 'Create', 'Report', 'Page'];
@ -208,3 +211,161 @@ export function getSearchList() {
getSetupList(),
].flat();
}
interface Searchable {
schemaName: string;
fields: string[];
meta: string[];
isChild: boolean;
isSubmittable: boolean;
}
interface Keyword {
values: string[];
meta: Record<string, string | boolean | undefined>;
priority: number;
}
interface Keywords {
searchable: Searchable;
keywords: Keyword[];
}
class Search {
keywords: Record<string, Keywords>;
priorityMap: Record<string, number> = {
[ModelNameEnum.SalesInvoice]: 125,
[ModelNameEnum.PurchaseInvoice]: 100,
[ModelNameEnum.Payment]: 75,
[ModelNameEnum.Item]: 50,
[ModelNameEnum.Party]: 50,
[ModelNameEnum.JournalEntry]: 50,
};
constructor() {
this.keywords = {};
}
getSearchList() {
const keywords = Object.values(this.keywords);
return keywords.map((kw) => kw.keywords).flat();
}
async fetchKeywords() {
const searchables = this.#getSearchables();
for (const searchable of searchables) {
const options: GetAllOptions = {
fields: [searchable.fields, searchable.meta].flat(),
order: 'desc',
};
if (!searchable.isChild) {
options.orderBy = 'modified';
}
const maps = await fyo.db.getAllRaw(searchable.schemaName, options);
this.addToSearchable(maps, searchable);
}
this.#setPriority();
}
#getSearchables(): Searchable[] {
const searchable: Searchable[] = [];
for (const schemaName of Object.keys(fyo.schemaMap)) {
const schema = fyo.schemaMap[schemaName];
if (!schema?.keywordFields?.length) {
continue;
}
const fields = [...schema.keywordFields];
const meta = [];
if (schema.isChild) {
meta.push('parent', 'parentSchemaName');
}
if (schema.isSubmittable) {
meta.push('submitted', 'cancelled');
}
searchable.push({
schemaName,
fields,
meta,
isChild: !!schema.isChild,
isSubmittable: !!schema.isSubmittable,
});
}
return searchable;
}
#setPriority() {
for (const schemaName in this.keywords) {
const kw = this.keywords[schemaName];
const basePriority = this.priorityMap[schemaName] ?? 0;
for (const k of kw.keywords) {
k.priority += basePriority;
if (k.meta.submitted) {
k.priority += 25;
}
if (k.meta.cancelled) {
k.priority -= 200;
}
if (kw.searchable.isChild) {
k.priority -= 150;
}
}
}
}
addToSearchable(maps: DocValueMap[], searchable: Searchable) {
if (!maps.length) {
return;
}
this.keywords[searchable.schemaName] ??= { searchable, keywords: [] };
for (const map of maps) {
const keyword: Keyword = { values: [], meta: {}, priority: 0 };
this.#setKeywords(map, searchable, keyword);
this.#setMeta(map, searchable, keyword);
this.keywords[searchable.schemaName]!.keywords.push(keyword);
}
}
#setKeywords(map: DocValueMap, searchable: Searchable, keyword: Keyword) {
// Set individual field values
for (const fn of searchable.fields) {
let value = map[fn] as string | undefined;
const field = fyo.getField(searchable.schemaName, fn);
const { options } = field as OptionField;
if (options) {
value = options.find((o) => o.value === value)?.label ?? value;
}
keyword.values.push(value ?? '');
}
}
#setMeta(map: DocValueMap, searchable: Searchable, keyword: Keyword) {
// Set the meta map
for (const fn of searchable.meta) {
const meta = map[fn];
if (typeof meta === 'number') {
keyword.meta[fn] = Boolean(meta);
} else if (typeof meta === 'string') {
keyword.meta[fn] = meta;
}
}
keyword.meta.schemaName = searchable.schemaName;
}
}
//@ts-ignore
window.sc = new Search();