mirror of
https://github.com/frappe/books.git
synced 2025-02-02 12:08:27 +00:00
incr: add keyword fields, start with doc search
This commit is contained in:
parent
eedb4415ce
commit
a0f812e1a8
@ -243,8 +243,9 @@ export default class DatabaseCore extends DatabaseBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hasCreated = !!schema.fields.find((f) => f.fieldname === 'created');
|
const hasCreated = !!schema.fields.find((f) => f.fieldname === 'created');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
fields = ['name', ...(schema.keywordFields ?? [])],
|
fields = ['name'],
|
||||||
filters,
|
filters,
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
|
@ -143,13 +143,5 @@
|
|||||||
"readOnly": true
|
"readOnly": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quickEditFields": [
|
"quickEditFields": ["name", "rootType", "parentAccount", "accountType", "isGroup", "balance"]
|
||||||
"name",
|
|
||||||
"rootType",
|
|
||||||
"parentAccount",
|
|
||||||
"accountType",
|
|
||||||
"isGroup",
|
|
||||||
"balance"
|
|
||||||
],
|
|
||||||
"keywordFields": ["name", "rootType", "accountType"]
|
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,5 @@
|
|||||||
"balance",
|
"balance",
|
||||||
"reverted",
|
"reverted",
|
||||||
"reverts"
|
"reverts"
|
||||||
],
|
]
|
||||||
"keywordFields": ["account", "party", "referenceName"]
|
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,5 @@
|
|||||||
"country",
|
"country",
|
||||||
"postalCode"
|
"postalCode"
|
||||||
],
|
],
|
||||||
"keywordFields": [
|
|
||||||
"addressLine1",
|
|
||||||
"addressLine2",
|
|
||||||
"city",
|
|
||||||
"state",
|
|
||||||
"country",
|
|
||||||
"postalCode"
|
|
||||||
],
|
|
||||||
"inlineEditDisplayField": "addressDisplay"
|
"inlineEditDisplayField": "addressDisplay"
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,5 @@
|
|||||||
"required": true,
|
"required": true,
|
||||||
"target": "Address"
|
"target": "Address"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"keywordFields": ["companyName"]
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,5 @@
|
|||||||
"fieldtype": "Data"
|
"fieldtype": "Data"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"keywordFields": ["name", "symbol"],
|
|
||||||
"quickEditFields": ["name", "symbol"]
|
"quickEditFields": ["name", "symbol"]
|
||||||
}
|
}
|
||||||
|
@ -135,5 +135,5 @@
|
|||||||
"expenseAccount",
|
"expenseAccount",
|
||||||
"hsnCode"
|
"hsnCode"
|
||||||
],
|
],
|
||||||
"keywordFields": ["name", "description"]
|
"keywordFields": ["name", "itemType", "for"]
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
"fieldname": "userRemark",
|
"fieldname": "userRemark",
|
||||||
"label": "User Remark",
|
"label": "User Remark",
|
||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
"placeholder": "User Remark"
|
"placeholder": "Add a remark"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "numberSeries",
|
"fieldname": "numberSeries",
|
||||||
@ -100,5 +100,6 @@
|
|||||||
"required": true,
|
"required": true,
|
||||||
"default": "JV-"
|
"default": "JV-"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
}
|
"keywordFields": ["name", "entryType"]
|
||||||
|
}
|
||||||
|
@ -23,5 +23,6 @@
|
|||||||
"fieldtype": "Currency"
|
"fieldtype": "Currency"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tableFields": ["account", "debit", "credit"]
|
"tableFields": ["account", "debit", "credit"],
|
||||||
}
|
"keywordFields": ["account"]
|
||||||
|
}
|
||||||
|
@ -59,6 +59,5 @@
|
|||||||
"readOnly": true
|
"readOnly": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quickEditFields": ["referenceType", "start", "padZeros"],
|
"quickEditFields": ["referenceType", "start", "padZeros"]
|
||||||
"keywordFields": []
|
|
||||||
}
|
}
|
||||||
|
@ -90,5 +90,5 @@
|
|||||||
"role",
|
"role",
|
||||||
"taxId"
|
"taxId"
|
||||||
],
|
],
|
||||||
"keywordFields": ["name"]
|
"keywordFields": ["name", "email", "role"]
|
||||||
}
|
}
|
||||||
|
@ -36,5 +36,6 @@
|
|||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tableFields": ["referenceType", "referenceName", "amount"]
|
"tableFields": ["referenceType", "referenceName", "amount"],
|
||||||
|
"keywordFields": ["referenceName", "referenceType"]
|
||||||
}
|
}
|
||||||
|
@ -105,5 +105,5 @@
|
|||||||
"default": "PINV-"
|
"default": "PINV-"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"keywordFields": ["name", "party", "numberSeries"]
|
"keywordFields": ["name", "party"]
|
||||||
}
|
}
|
||||||
|
@ -68,5 +68,6 @@
|
|||||||
"placeholder": "HSN/SAC Code"
|
"placeholder": "HSN/SAC Code"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tableFields": ["item", "tax", "quantity", "rate", "amount"]
|
"tableFields": ["item", "tax", "quantity", "rate", "amount"],
|
||||||
|
"keywordFields": ["item", "tax"]
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
"isSingle": false,
|
"isSingle": false,
|
||||||
"isChild": false,
|
"isChild": false,
|
||||||
"isSubmittable": true,
|
"isSubmittable": true,
|
||||||
"keywordFields": ["name", "party"],
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"label": "Invoice No",
|
"label": "Invoice No",
|
||||||
@ -93,6 +92,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "terms",
|
"fieldname": "terms",
|
||||||
"label": "Notes",
|
"label": "Notes",
|
||||||
|
"placeholder": "Add invoice terms",
|
||||||
"fieldtype": "Text"
|
"fieldtype": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -103,5 +103,6 @@
|
|||||||
"required": true,
|
"required": true,
|
||||||
"default": "SINV-"
|
"default": "SINV-"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"keywordFields": ["name", "party"]
|
||||||
}
|
}
|
||||||
|
@ -69,5 +69,6 @@
|
|||||||
"placeholder": "HSN/SAC Code"
|
"placeholder": "HSN/SAC Code"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tableFields": ["item", "tax", "quantity", "rate", "amount"]
|
"tableFields": ["item", "tax", "quantity", "rate", "amount"],
|
||||||
|
"keywordFields": ["item", "tax"]
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,5 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"keywordFields": []
|
}
|
||||||
}
|
|
||||||
|
@ -90,12 +90,5 @@
|
|||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quickEditFields": [
|
"quickEditFields": ["locale", "dateFormat", "currency", "displayPrecision", "hideGetStarted"]
|
||||||
"locale",
|
|
||||||
"dateFormat",
|
|
||||||
"currency",
|
|
||||||
"displayPrecision",
|
|
||||||
"hideGetStarted"
|
|
||||||
],
|
|
||||||
"keywordFields": []
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,6 @@ export default {
|
|||||||
'name',
|
'name',
|
||||||
schema.titleField,
|
schema.titleField,
|
||||||
this.df.groupBy,
|
this.df.groupBy,
|
||||||
...schema.keywordFields,
|
|
||||||
]),
|
]),
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ function getListConfig(schemaName) {
|
|||||||
const listConfig = fyo.models[schemaName]?.getListViewSettings?.(fyo);
|
const listConfig = fyo.models[schemaName]?.getListViewSettings?.(fyo);
|
||||||
if (listConfig?.columns === undefined) {
|
if (listConfig?.columns === undefined) {
|
||||||
return {
|
return {
|
||||||
columns: fyo.schemaMap[schemaName].keywordFields ?? ['name'],
|
columns: ['name'],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return listConfig;
|
return listConfig;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { t } from 'fyo';
|
import { t } from 'fyo';
|
||||||
|
import { DocValueMap } from 'fyo/core/types';
|
||||||
import { ModelNameEnum } from 'models/types';
|
import { ModelNameEnum } from 'models/types';
|
||||||
import reports from 'reports/view';
|
import reports from 'reports/view';
|
||||||
|
import { OptionField } from 'schemas/types';
|
||||||
import { fyo } from 'src/initFyo';
|
import { fyo } from 'src/initFyo';
|
||||||
|
import { GetAllOptions } from 'utils/db/types';
|
||||||
import { routeTo } from './ui';
|
import { routeTo } from './ui';
|
||||||
|
|
||||||
export const searchGroups = ['Docs', 'List', 'Create', 'Report', 'Page'];
|
export const searchGroups = ['Docs', 'List', 'Create', 'Report', 'Page'];
|
||||||
@ -208,3 +211,161 @@ export function getSearchList() {
|
|||||||
getSetupList(),
|
getSetupList(),
|
||||||
].flat();
|
].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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user