2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 10:58:59 +00:00

incr: add deleteAll

- fix db where clauses
This commit is contained in:
18alantom 2022-11-02 19:37:54 +05:30
parent 6805ebcaba
commit 2a5686058d
4 changed files with 126 additions and 21 deletions

View File

@ -266,6 +266,12 @@ export default class DatabaseCore extends DatabaseBase {
)) as FieldValueMap[];
}
async deleteAll(schemaName: string, filters: QueryFilter): Promise<number> {
const builder = this.knex!(schemaName);
this.#applyFiltersToBuilder(builder, filters);
return await builder.delete();
}
async getSingleValues(
...fieldnames: ({ fieldname: string; parent?: string } | string)[]
): Promise<SingleValue<RawValue>> {
@ -444,10 +450,35 @@ export default class DatabaseCore extends DatabaseBase {
// {"date": [">=", "2017-09-09", "<=", "2017-11-01"]}
// => `date >= 2017-09-09 and date <= 2017-11-01`
const filtersArray = [];
const filtersArray = this.#getFiltersArray(filters);
for (const i in filtersArray) {
const filter = filtersArray[i];
const field = filter[0] as string;
const operator = filter[1];
const comparisonValue = filter[2];
const type = i === '0' ? 'where' : 'andWhere';
if (operator === '=') {
builder[type](field, comparisonValue);
} else if (
operator === 'in' &&
(comparisonValue as (string | null)[]).includes(null)
) {
const nonNulls = (comparisonValue as (string | null)[]).filter(
Boolean
) as string[];
builder[type](field, operator, nonNulls).orWhere(field, null);
} else {
builder[type](field, operator as string, comparisonValue as string);
}
}
}
#getFiltersArray(filters: QueryFilter) {
const filtersArray = [];
for (const field in filters) {
const value = filters[field];
let operator: string | number = '=';
let comparisonValue = value as string | number | (string | number)[];
@ -477,25 +508,7 @@ export default class DatabaseCore extends DatabaseBase {
}
}
filtersArray.map((filter) => {
const field = filter[0] as string;
const operator = filter[1];
const comparisonValue = filter[2];
if (operator === '=') {
builder.where(field, comparisonValue);
} else if (
operator === 'in' &&
(comparisonValue as (string | null)[]).includes(null)
) {
const nonNulls = (comparisonValue as (string | null)[]).filter(
Boolean
) as string[];
builder.where(field, operator, nonNulls).orWhere(field, null);
} else {
builder.where(field, operator as string, comparisonValue as string);
}
});
return filtersArray;
}
async #getColumnDiff(schemaName: string): Promise<ColumnDiff> {

View File

@ -549,3 +549,78 @@ test('CRUD dependent schema', async function (t) {
await db.close();
});
test('db deleteAll', async (t) => {
const db = await getDb();
const emailOne = 'one@temp.com';
const emailTwo = 'two@temp.com';
const emailThree = 'three@temp.com';
const phoneOne = '1';
const phoneTwo = '2';
const customers = [
{ name: 'customer-a', phone: phoneOne, email: emailOne },
{ name: 'customer-b', phone: phoneOne, email: emailOne },
{ name: 'customer-c', phone: phoneOne, email: emailTwo },
{ name: 'customer-d', phone: phoneOne, email: emailTwo },
{ name: 'customer-e', phone: phoneTwo, email: emailTwo },
{ name: 'customer-f', phone: phoneTwo, email: emailThree },
{ name: 'customer-g', phone: phoneTwo, email: emailThree },
];
for (const { name, email, phone } of customers) {
await db.insert('Customer', {
name,
email,
phone,
...getDefaultMetaFieldValueMap(),
});
}
// Get total count
t.equal((await db.getAll('Customer')).length, customers.length);
// Single filter
t.equal(
await db.deleteAll('Customer', { email: emailOne }),
customers.filter((c) => c.email === emailOne).length
);
t.equal(
(await db.getAll('Customer', { filters: { email: emailOne } })).length,
0
);
// Multiple filters
t.equal(
await db.deleteAll('Customer', { email: emailTwo, phone: phoneTwo }),
customers.filter(
({ phone, email }) => email === emailTwo && phone === phoneTwo
).length
);
t.equal(
await db.deleteAll('Customer', { email: emailTwo, phone: phoneTwo }),
0
);
// Includes filters
t.equal(
await db.deleteAll('Customer', { email: ['in', [emailTwo, emailThree]] }),
customers.filter(
({ email, phone }) =>
[emailTwo, emailThree].includes(email) &&
!(phone === phoneTwo && email === emailTwo)
).length
);
t.equal(
(
await db.getAll('Customer', {
filters: { email: ['in', [emailTwo, emailThree]] },
})
).length,
0
);
await db.close();
});

View File

@ -6,7 +6,12 @@ import Observable from 'fyo/utils/observable';
import { translateSchema } from 'fyo/utils/translation';
import { Field, RawValue, SchemaMap } from 'schemas/types';
import { getMapFromList } from 'utils';
import { DatabaseBase, DatabaseDemuxBase, GetAllOptions } from 'utils/db/types';
import {
DatabaseBase,
DatabaseDemuxBase,
GetAllOptions,
QueryFilter,
} from 'utils/db/types';
import { schemaTranslateables } from 'utils/translationHelpers';
import { LanguageMap } from 'utils/types';
import { Converter } from './converter';
@ -207,6 +212,16 @@ export class DatabaseHandler extends DatabaseBase {
this.observer.trigger(`delete:${schemaName}`, name);
}
async deleteAll(schemaName: string, filters: QueryFilter): Promise<number> {
const count = (await this.#demux.call(
'deleteAll',
schemaName,
filters
)) as number;
this.observer.trigger(`deleteAll:${schemaName}`, filters);
return count;
}
// Other
async exists(schemaName: string, name?: string): Promise<boolean> {
const doesExist = (await this.#demux.call(

View File

@ -43,6 +43,8 @@ export abstract class DatabaseBase {
// Delete
abstract delete(schemaName: string, name: string): Promise<void>;
abstract deleteAll(schemaName:string, filters:QueryFilter): Promise<number>;
// Other
abstract close(): Promise<void>;