Загрузка данных


ПОИСК

динамические проверки и OR внутри AND

	const crosses_count = await ViewContext.fields.price_lists.app.search().where((f,g)=>g.and(
		f.__deletedAt.eq(null), 
		f.__id.neq(Context.id), 
		f.product.link(Context.data.product!), 
		f.price_list_type.link(Context.data.price_list_type!), 
		f.shipment_period.eq(Context.data.shipment_period!),
		f.shipment_period_uom.eq(Context.data.shipment_period_uom!),
		f.warranty_period.eq(Context.data.warranty_period!),
		Context.data.price_id ?  f.price_id.link(Context.data.price_id!) : f.price_id.eq(null),
		g.or( g.and(f.date_from.lte(Context.data.date_from!), 
					f.date_to.gte(Context.data.date_from!)),
			g.and(f.date_from.gte(Context.data.date_from!), 
					f.date_to.lte(Context.data.date_to!)),
			g.and(f.date_from.gte(Context.data.date_from!), 
					f.date_from.lte(Context.data.date_to!)))
		)).count();


-----------------------------------------------------------
динамический набор условий
	Context.fields.filedname.data.setFilter(function(f,c,g){
		let operands: Filter[] = [];
		let operandsOr: Filter[] = [];
		for (const position of Context.data.positions){
			operandsOr.push(f.nomenclature_position.has(positions))
		}
		operands.push(g.or(...operandsOr));
		operands.push(f.__deletedAt.eq(null));
		if (Context.data.address) 
			operands.push(f.address.like(Context.data.address));
		return g.and(...operands);
	});
	
	
-----------------------------------------------------------
EQL
	
    let productId = Context.data.productid!.id;
    let projectId = Context.data.ProjectId!.id;
    let lowThresholdDate = salesOrderIdItem.data.OrderDate.addDate(0,0,-93);
    let codesArr:string[] = ['qwer','asdf','zxcv'];
    let searchStr:string = "";
    searchStr = "'" + codesArr.join("','") + "'";
	
    let pp = await Context.fields.produkt_proekta.app.search().where(`
        [__deletedAt] = NULL AND 
        [ProjectId] IN (SELECT [__id] FROM [test.leads] WHERE 
            [__id] = '${projectId}') AND 
		[code] IN (${searchStr}) AND
        [PlannedEndDate]>'${lowThresholdDate.format()}' AND ((
        NOT [Status] IN ('zakryt','zakryt_-_proigran')) OR [Status] = NULL) AND 
        [priceListProduct] IN (SELECT [__id] FROM [test.PriceListProduct] WHERE 
            [ProductId] IN (SELECT [__id] FROM [test.products] WHERE 
                [__id] = '${productId}')) AND
		COUNT (FROM [mdm.Attachment] WHERE PARENT.[__id] in [RelatedToId]) > 0 AND
		[__id] IN (SELECT [ContactId] FROM [mdm.Attachment])
	`).first();   

-----------------------------------------------------------
Поиск по дате-времени

	truncateTime() не работает на некоторых версиях, вместо него использовать (new Datetime(`${(new Datetime()).getDate().format()}T00:00:00`))
	
Поиск StartDate<= TODAY <=EndDate
    let todayLowThreshold = new Datetime();
    let todayHighThreshold = (new Datetime(`${(new Datetime()).getDate().format()}T00:00:00`)).addDate(0,0,1);
	
            [StartDate] <= '${todayHighThreshold.format()}' AND
            [EndDate] >= '${todayLowThreshold.format()}' AND 
			
	
	EQL поиск не работает по приравниванию даты. Для поиска по совпадению с днем надо искать в интервале от (new Datetime(`${(new Datetime()).getDate().format()}T00:00:00`)) до (new Datetime(`${(new Datetime()).getDate().format()}T00:00:00`)).addDate(0,0,1)
	
Поиск по подтипу "дата":
	let today_date = (new Datetime()).getDate();
		EQL нужно учитывать время (см выше), т.е строка [data] >= '2025-07-08' сработает, а [data] <= '2025-07-08' не включит крайнее значение
		SDK не учитывает время, можно использовать f.data.gte(today_date) и f.data.lte(today_date)
	today_date.format() выведет '2025-07-08'
	
	
Расчет количества рабочих дней

    const start = Context.data.data!.asDatetime(new TTime(0,0,0,0));
    const end = (new Datetime(`${(Context.data.data_vremya!).getDate().format()}T00:00:00`)).addDate(0,0,1);
    const time = await System.productionSchedule.getWorkingTime(start,end);
    ViewContext.data.kolichestvo_rabochikh_dnei = Math.ceil(time.hours / 8);
-----------------------------------------------------------
api фильтра в методе seach	
	// Для создания кастомного фильтра
	class PhoneFilter {
		constructor (private filter: any) {
		}
		json () {
			return this.filter;
		}
	}
	//** Функция для вычисление номеров телефонов по контактам */
	async function getContactsPhone(phone_tel: string) {
		const contacts = await Context.fields.contact.app.search()
		.where((f,g) => g.and(
			f.__deletedAt.eq(null),
			(f as any)["_phone"].neq(null))
		)
		.where(f => new PhoneFilter(
			{"tf":
				{
					"_phone": phone_tel
				}
			}
		))
		.all();
	}
	Чтобы корректно сформировать запрос нужно использовать список полей доступных для фильтрации: https://api.elma365.com/ru/public-api/guides/Filter/
	А тут можно найти пример от элмы. https://community.elma365.com/ru/threads/66/ - там же поиск по множественному полю типа приложение

-----------------------------------------------------------
поиск более 10к объектов

const orders_search = Context.fields.orders.search().where((f,g) => g.and());
let count = await orders_search.count();
let orders = await orders_search.size(10000).all();

if (count > 10000){
	for (let i = 1; ; i++) {
		const orders_slice = await orders_search.size(10000).from(10000 * i).all();
		if (orders_slice){
			orders = orders.concat(orders_slice);
			if (orders_slice.length < 10000) {
				break;  
			}
		}else{
			break;
		}
	}
}
-----------------------------------------------------------
поиск через линк когда есть массив id

	async function getContactIdsDuplicatesOnAnotherTarget(contactIds: string[]) {
		const lookups = (contactIds as any) as Array<ApplicationItemRef<Application$_clients$_contacts$Data, Application$_clients$_contacts$Params>>;
			f.ContactId.link(lookups),