Вопрос

Добрый день!

Создал процесс который создает в календаре задачу и выставляет ей  начало и завершение на ближайшее свободное время в календаре. При попытке проверить отсутствие задачи начало и завершение сравниваются с датами, хотя в условиях стоит фильтр сравнения с датой и временем

У меня такой же вопрос

2 комментария

По умолчанию при добавлении фильтра по колонке «Дата/Время» не учитывается время. Необходимо в параметрах элемента «Читать данные» дополнительно проставлять признак «Учитывать время в фильтре» (изначально стоит false).

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

На страницу выведено поле с датой и временем, нужно передать в него время из справочника при изменении значения в выпадающем списке. Стандартные js способы new Data(dataCode) не работает

У меня такой же вопрос

7 комментариев
Лучший ответ

Добрый день!

А что именно "стандартное" не работает? Какой тип у dataCode? Возможно просто напросто вы не можете создать дату? Так как значение устанавливается просто. Например:

//...
attributes: {
	"SomeDate": {
		"dataValueType": this.Terrasoft.DataValueType.DATE_TIME,
		"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
		"dependencies": [{
			columns: ["Type"],
			methodName: "setSomeDate"
		}]
	},
	"Type": {
		"lookupListConfig": {
			columns: ["CreatedOn"]
		}
	}
},
//...
methods: {
	setSomeDate: function () {
		var value = (this.get("Type") || {}).CreatedOn || null;
		this.set("SomeDate", value);
	}
}
//...

И Вам, наверное, стоит заглянуть в консоль, там скорее всего ошибка, которая прояснит ситуацию

Добрый день!

А что именно "стандартное" не работает? Какой тип у dataCode? Возможно просто напросто вы не можете создать дату? Так как значение устанавливается просто. Например:

//...
attributes: {
	"SomeDate": {
		"dataValueType": this.Terrasoft.DataValueType.DATE_TIME,
		"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
		"dependencies": [{
			columns: ["Type"],
			methodName: "setSomeDate"
		}]
	},
	"Type": {
		"lookupListConfig": {
			columns: ["CreatedOn"]
		}
	}
},
//...
methods: {
	setSomeDate: function () {
		var value = (this.get("Type") || {}).CreatedOn || null;
		this.set("SomeDate", value);
	}
}
//...

И Вам, наверное, стоит заглянуть в консоль, там скорее всего ошибка, которая прояснит ситуацию

Лопатин Константин Николаевич,

Ошибке в консоли нет, в том и дело. Мне по факту нужно понимать как в поле с датой положить значение, его формат.

Пробовал this.set("dataColume", new Date(); - не работает, хотя в js даёт текущую дату и время. Так же пробовал из другого поля скопировать дату this.set("date", new Date(this.get("date2").toString()))

И

this.set("date1", this.get("date2"))

Prime Source,

А в каком методе Вы это делаете? По событию? Запрос может быть к базе какой-то выполняете? Контекст верный? Вариант с

this.set("SomeDate", new Date());

очень даже рабочий. Тяжело помочь, когда не видишь полной картины

Лопатин Константин Николаевич,

define("PsPPsPApprovalPuRequests1Page", [], function() {
	return {
		entitySchemaName: "PsPApprovalPuRequests",
		attributes: {
			"PsPDateTimeApproval": {
				dataValueType: Terrasoft.DataValueType.FLOAT,
				dependencies: [
					{
						columns: ["PsPsPMatchResult"],
						methodName: "approvalDate"
					}
				]
			}
		},
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		businessRules: /**SCHEMA_BUSINESS_RULES*/{
			"PsPsPMatchResult": {
				"b7a163a0-228d-4005-bfd3-3d19229a6328": {
					"uId": "b7a163a0-228d-4005-bfd3-3d19229a6328",
					"enabled": true,
					"removed": false,
					"ruleType": 0,
					"property": 1,
					"logical": 0,
					"conditions": [
						{
							"comparisonType": 3,
							"leftExpression": {
								"type": 3,
								"value": "CurrentUserContact",
								"dataValueType": 10
							},
							"rightExpression": {
								"type": 1,
								"attribute": "PsPApprovalMan"
							}
						},
						{
							"comparisonType": 1,
							"leftExpression": {
								"type": 1,
								"attribute": "PsPsPMatchResult"
							}
						}
					]
				}
			},
			"PsPComent": {
				"e39449ef-895f-4341-8133-2e773a4dec7d": {
					"uId": "e39449ef-895f-4341-8133-2e773a4dec7d",
					"enabled": true,
					"removed": false,
					"ruleType": 0,
					"property": 1,
					"logical": 0,
					"conditions": [
						{
							"comparisonType": 3,
							"leftExpression": {
								"type": 3,
								"value": "CurrentUserContact",
								"dataValueType": 10
							},
							"rightExpression": {
								"type": 1,
								"attribute": "PsPApprovalMan"
							}
						}
					]
				}
			}
		}/**SCHEMA_BUSINESS_RULES*/,
		methods: {
			approvalDate: function() {
				var matchResult = this.get("PsPsPMatchResult");
				if (matchResult) {
					var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "PsPMatchResult"});
					//esq.addColumn("PsPTimeLimit", "PsPTimeLimit");
					debugger;
					esq.getEntity(matchResult.value, function(result) {
						if (!result.success) {
							// обработка/логирование ошибки, например
							this.showInformationDialog("Ошибка запроса данных");
							return;
						}
						this.set("PsPDateTimeApproval", new Date());
					}, this);
				}
			}
		},
		dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "PsPApprovalMan",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 1,
						"layoutName": "Header"
					},
					"bindTo": "PsPApprovalMan"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "PsPsPMatchResult",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 2,
						"layoutName": "Header"
					},
					"bindTo": "PsPsPMatchResult",
					"labelConfig": {
						"caption": {
							"bindTo": "Resources.Strings.PsPsPMatchResultLabelCaption"
						}
					},
					"enabled": true,
					"contentType": 5
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 1
			},
			{
				"operation": "insert",
				"name": "PsPComent",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 3,
						"layoutName": "Header"
					},
					"bindTo": "PsPComent"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 2
			},
			{
				"operation": "insert",
				"name": "PsPDateTimeApproval27fcf723-04c0-4c5d-86d1-e4ef52f8b467",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 0,
						"layoutName": "Header"
					},
					"bindTo": "PsPDateTimeApproval",
					"enabled": false
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 3
			}
		]/**SCHEMA_DIFF*/
	};
});

 

Лопатин Константин Николаевич,

attributes: {
	"PsPTimeLimit": {
		dataValueType: Terrasoft.DataValueType.FLOAT,
		dependencies: [
			{
				columns: ["PsPProcurementType"],
				methodName: "calculateTimeLimit"
			}
		]
	}
},
methods: {
	onEntityInitialized: function() {
		this.callParent(arguments);
		this.calculateTimeLimit();
		this.calculateDepartment();
	},
	calculateTimeLimit: function() {
		var recordId = this.get("PsPProcurementType");
		var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "PsPProcurementType"});
		esq.addColumn("PsPTimeLimit", "PsPTimeLimit");
		if (recordId) {
			esq.getEntity(recordId.Id, function(result) {
				if (!result.success) {
					// обработка/логирование ошибки, например
					this.showInformationDialog("Ошибка запроса данных");
					return;
				}
				var timeLimit = result.entity.get("PsPTimeLimit").toString();
				this.set("PsPTimeLimit", {
					displayValue: new Date(timeLimit)
				});
			}, this);
		}
	}
}

Это из базы уже

Prime Source,

А что Вы ожидаете получить в целом? Колонка PsPTimeLimit имеет  тип FLOAT, и в нее различными способами пытаются запихнуть дату, логично что не работает. А способ

this.set("PsPTimeLimit", { displayValue: new Date(timeLimit) });

Вы где подсмотрели?

Повнимательней перечитайте мой первый комментарий. Можете оттуда выбросить VITRUAL_COLUMN, подставить свои названия полей и все заработает

Лопатин Константин Николаевич,

Спасибо, тип изменил и все заработало, нужно больше спать)))

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Заполняем поле менеджер(пользователь системы), заполняем поле даты/время, при заполнении этого поля нужно проверить свободен ли в это время(и следующих 15 мин) менеджер, если да то делаем кнопку доступной.
Интересует как сделать саму проверку.

У меня такой же вопрос

9 комментариев

Добрый вечер, Виталий.

Для решения Вашей задачи необходимо:
1) Привязать доступность кнопки к булевому атрибуту, имеющему по умолчанию значение false.
2) При каждом изменении поля Дата/Время делать запрос к базе данных проверяя свободен ли он и на основании результат менять значение атрибута из пункта 1.

Вот что получилось:
var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "Activity"});
esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "Id");
esq.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL,
"Owner",
this.get("Owner").value
));
esq.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.Greater,
"StartDate",
new Date()
));
esq.getEntityCollection(
function(response) {
var e = response.collection.getByIndex(0).get("Id");
e = e + e;
},
this
);
на строке var e = response.collection.getByIndex(0).get("Id"); выбивает ошибку - елемент не найден, если убрать фильтр по дате - выбирает все как есть, значит проблема в фильтре, что я сделал не так? возможно формат другой? я не смог найти пример с датами

... жесть, не Greater а GREATER

так, наткнулся на другую проблему, как я понял оно работает:
формируем запрос и отправили его на сервер и когда придет ответ - обрабатываем его, но не ждем пока он придет код выполняется дальше. когда приходит ответ - выполняется функция "getEntityCollection( function(response". И тут 2 вопроса можно ли сделать так чтоб все висло и ждало пока придет ответ и как передать в эту функцию параметры

Виталий, javascript асинхронный по умолчанию и с этим ничего сделать нельзя.

По поводу параметров:

1) В метод getEntityCollection вторым параметром передается scope выполнения функции обратного вызова. Т.е. если в него передать this - функция сможет работать с любыми атрибутами или методами карточки.

2) Аналогично можно перед вызовом getEntityCollection закешировать this.
var scope = this;
Тогда можно будет получить или изменить любой атрибут обращаясь к scope внутри функции обратного вызова.
var param = scope.get("Owner");
scope.set("Owner", {id: "", displayValue: "Supervisor"})

да но что делать когда нужно выполнить вот такой код:

esq.getEntityCollection(
	function(response) {
		var ActivitytCount = response.collection.getByIndex(0).get("Id");
		if (ActivitytCount === 0) {
			this.callParent([function() {
				this.Terrasoft.chain(this.publishOnSaveEvents, function() {
					this.onSaved(callback, scope);
				}, this);
			}, this]);

выбивает ошибку:
TypeError: e is undefined

Как вариант зависания - используйте метод showBodyMask() перед вызовом getEntityCollection. Это позволит отобразить на карточке маску загрузки которая не позволит менять данные.

В функции обратного вызова скройте маску this.hideBodyMask()

this.showBodyMask();
esq.getEntityCollection(function(response) {
	//вычисления
	this.hideBodyMask()
}, this);

рекомендую также смотреть в сторону использования try catch что бы избежать вечной маски загрузки если в коллбэке возникнет ошибка

Ошибка в том, что вызвать callParent в функции обратного вызова невозможно, контекст уже утерян.

Пример решения (метод onEntityInitialized взят для примера):

onEntityInitialized: function() {
	if(this.get("test") === true){
		this.set("test", false);
		this.callParent([function() {
			this.Terrasoft.chain(this.publishOnSaveEvents, function() {
				this.onSaved(callback, scope);
			}, this);
		}, this]
                return;
	}
	esq.getEntityCollection(
		function(response) {
			var ActivitytCount = response.collection.getByIndex(0).get("Id");
			if (ActivitytCount === 0) {
				this.set("test", true)
				this.onEntityInitialized();
			}
		},
	this);
}

Вау! Никогда не использовал такую логику!!! Сработало, благодарю!

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Здравствуйте, подскажите пожалуйста
Имеется поле "Фактическое время" (после выполнения задачи считает сколько часов было потрачено на задачу). Поле является "Text Data Control"
И имеется drop-down список с коэффициентом (от 0.1 до 2.0)
Мне необходимо при выборе коэффициента реализовать автоматическое умножение этого коэффициента на "Фактическое время" и результат занести в поле "Количество часов".

Надеюсь на вашу помощь. Заранее спасибо

У меня такой же вопрос

13 комментариев

Добрый день Дмитрий!!!

ну я думаю подход у вас должен быть очень простым. Получаем текущее затраченное время, я думаю вы его уже знаете. Переводим полученное время в Минуты, в Секунды, в Миллисекунды, в ту единицу измерения в которой вам будет удобно считать. После конвертации из вида Часы.Минуты.Секунды к примеру в Секунды, умножаем полученный результат на выбранный Коэффициент и полученный результат конвертируем обратно к виду Часы.Минуты.Секунды.

Спасибо за помощь, а то, что поле с затраченным временем является "Text Data control" это ничего страшного? :)

Здравствуйте,

можете привести пример окна (принскрин окна в Terrasoft, а также принскрин окна в Администраторе).
Также укажите тип drop-down компонента и компонентов которые будут задействованы в операции по вычислению "Количества часов".

drop-down сделал через enm

Уточните, какой именно Enum:

  • EnumDataControl
  • EnumControl

Прошу прощения, не так понял Вас
EnumDataControl

В датасете (dlData) окна на события dlDataOnDatasetDataChange пишите код:

var DataFieldName = DataField.Name;
if (DataFieldName == 'Имя Вашего поля в компоненте EnumDataControl') {
	var Val = преобразовываете значение поля [Фактическое время] в цифровое значение;
	var Res = Val * (1 * DataField.ValAsEnumItem.Code);
	[Количество часов] = Res;
}

Где-то приблизительно должен получиться такой код, при условии, что Enum такого вида:

Павел, спасибо большое за помощь! Сейчас попробую

Павел, а может быть Вы мне еще подскажете принцип вычитания 2-ух дат?
Или где это можно подсмотреть :)

Посмотрите на сайтах:

В итоге получилось так:

//Коэффициент занятости
case ('CoefficientID'):
	if (DataFieldName == 'CoefficientID') {
	var theDateStart = new Date(Date.parse(Dataset.ValAsDateTime('ActualStartDate')));
    	var theDateFinish = new Date(Date.parse(Dataset.ValAsDateTime('ActualFinishDate')));
 
        var oneHour=1000*60*60;
	var Val = ((theDateFinish - theDateStart) / oneHour);
 
        var Res = (Val * (1 * DataField.ValAsEnumItem.Code));
    	Res = Res.toFixed(2);
	Dataset.Values('RealHours') = Res;
 
        }		
break;	 

У Вас лишний if, его можно убрать, т.к. case как раз выполняет роль if. Получилась лишняя проверка.

Ой, спасибо. Сейчас уберем :wink:

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Как в терасофте поставить месяц в родительный падеж???
Например, чтобы выдавалось вместо Январь Января

У меня такой же вопрос

22 комментария

Можно написать свою функцию, которая по номеру месяца возвращает его название в нужном падеже...

скорее по номеру числа в месяце а не по номеру месяца

"Шевченко Юрий" написал:скорее по номеру числа в месяце а не по номеру месяца

Первое января
второе января
двадцать девятое января

Кстати у меня была давняя задумка вообще функцию добавить в Terrasoft, которая бы возвращала любой падеж... Понятно, что неидеально и сложно бы она работала, но все же. Решилась бы проблема обращений, месяцев и т.д...
но руки естественно не доходят:smile: может в Идеи?

"Александр Кудряшов" написал:Решилась бы проблема обращений, месяцев и т.д.

А это вообще возможно? Если только с использованием каких-нибудь веб-сервисов больших словарей

как вариант платная библиотека http://morpher.ru/Default.aspx. Либо аналоги...
Понятно, что для наилучших результатов нужны большие словари, либо пополняемые, либо доступные в сети.

"Александр Кудряшов" написал:для наилучших результатов нужны большие словари

Лучше самому просклонять фамилию клиента, нежели потом автоматом будет выслано неправильно.

Собственно, нужно для Fast Report, чтобы поле типа "Дата" выходило с месяцем в нужном падеже.
Простым форматированием получается "1 Январь 2010"

Наверное, придется в элементе управления прописывать iif([MonthOf([Date])] = 1; 'Января'; iif()) и так далее.

"Раловец Ольга" написал:Наверное, придется в элементе управления прописывать iif([MonthOf([Date])] = 1; 'Января'; iif()) и так далее.

Или такие варианты:
- в Dataset отчета добавить вычисляемое поле, которое заполняется в скрипте к Dataset;
- в SelectQuery отчета добавить колонку с текстом SQL, в котором через (CASE WHEN THEN END) вычислить месяц.

"Парфенов Евгений" написал:Собственно, нужно для Fast Report, чтобы поле типа "Дата" выходило с месяцем в нужном падеже.
Простым форматированием получается "1 Январь 2010"

в отчете в Code добавляете функцию типа

function MonthDecl(aDate: TDateTime): String;  
begin
    case MonthOf(aDate) of
    0: Result:= 'Января';
    1: Result:= 'Февраля';
    //...
    end            
end;

и вызываете ее где необходимо

Всем спасибо. Публикую полученную версию - может кому понадобится :)

// Дата в родительном падеже
function DecodeDateRod(aDate: TDateTime): String;
var m : string;
d, y : integer;
begin
m:= '';

case MonthOf(aDate) of
0: m:= 'Января';
1: m:= 'Февраля';
2: m:= 'Марта';
3: m:= 'Апреля';
4: m:= 'Мая';
5: m:= 'Июня';
6: m:= 'Июля';
7: m:= 'Августа';
8: m:= 'Сентября';
9: m:= 'Октября';
10: m:= 'Ноября';
11: m:= 'Декабря';
end;

d := DayOf(aDate);
y := YearOf(aDate);

Result := Inttostr(d) + ' ' + m + ' ' + Inttostr(y) + 'г.';
end;

Около года назад тоже сделал такую процедурку)) Возникала частая потребность, так что даже выделил в отдельный скрипт, хотел еще назвать 'имени FastReport':lol:

Поправочка - отчет должен идти с 1цы... 1= Январь и пр..

Да нет, все же с 0. Я настаиваю:wink:

"Fishi" написал:Да нет, все же с 0. Я настаиваю

Вы настаиваете, а у меня счета будущим месяцем проходят...
Меня такое как то мягко говоря не очень устраивает :)

Тогда у меня надо сначала m++)))
У меня версия TS 3.1.1 X25, хотя не думаю что это существенно... Ждем пока кто разяснит ситуацию, пока 1:1)

А у меня TS 3.3.0.61 )))

Подскажите, куда вставлять данную функцию и как ее вызвать в FastReports?

Функция DecodeDateRod описанная в комментарии
http://www.community.terrasoft.ru/forum/topic/4393#comment-17243
формирует дату в формате 29 Сентября 2011 г.
Данную фунцию следует объявить в вкладке Code в сервисе FastReport

Саму функцию следует объявить до самого ее вызова, к примеру в самом начеле кода.

Предположим, что у нас есть Memo1 контрол который находится на странице FastReport в котором мы отображаем дату

Добавим обработчик OnBeforePrint на Memo1

В коде обработчика будем вызывать функцию преобразования даты

procedure Memo1OnBeforePrint(Sender: TfrxComponent);
begin
Memo1.Text :=DecodeDateRod(<TSDataset1."MyDate">);
end;

В данном коде предполагается, что к отчету подключен TSDataset1, в котором задан конкретный Dataset, в котором есть колонка MyDate где хранится даты для отображения
В предпросмотре получим следующий результат

Полный код сервиса FastReport:

function DecodeDateRod(aDate: TDateTime): String;
var m : string;
d, y : integer;
begin
m:= ''; 
case MonthOf(aDate) of
0: m:= 'Января';
1: m:= 'Февраля';
2: m:= 'Марта';
3: m:= 'Апреля';
4: m:= 'Мая';
5: m:= 'Июня';
6: m:= 'Июля';
7: m:= 'Августа';
8: m:= 'Сентября';
9: m:= 'Октября';
10: m:= 'Ноября';
11: m:= 'Декабря';
end;
d := DayOf(aDate);
y := YearOf(aDate); 
Result := Inttostr(d) + ' ' + m + ' ' + Inttostr(y) + 'г.';
end;
 
procedure Memo1OnBeforePrint(Sender: TfrxComponent);
begin
Memo1.Text :=DecodeDateRod(<TSDataset1."MyDate">);
end;
 
begin
 
end.

Пример сервисов, на которых тестировал вывод, в прикрепленных файлах.

Алексей, без Ваших пояснений никогда бы не разобрался) Все получилось!

Единственное, результат полностью перебивал значение Memo (выводилась только дата), а мне в нем нужны были еще данные, для заголовка счета. В результате дописал процедуру, не знаю насколько это корректно, но нужного результата я добился:

procedure Memo13OnBeforePrint(Sender: TfrxComponent);
begin
Memo13.Text :='Счет №' + Inttostr(<ds_ReportInvoiceWithNDSForRussia."InvoiceNumber">)+ ' ' + 'от' + ' ' + DecodeDateRod(<ds_ReportInvoiceWithNDSForRussia."InvoiceDate">);
end;

Рад, что у вас все получилось, если будут вопросы, обращайтесь.

Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Как известно, в стандартной версии приложения Terrasoft CRM при активации напоминания, например, в карточке задачи, проставляется текущая дата и текущее время.
Для того, чтобы реализовать появление напоминания в этот же день, но спустя, например два часа, необходимо выполнить следующие действия:
1. Откройте сервис wnd_TaskEdit. Перейдите в обработчик события OnClick контрола chbRemindToOwner.
2. В этом обработчике события Вы найдете вызов функции UpdateRemindToOwnerControls(IsReminding). Вам необходимо именно эту функцию отредактировать. В этом же скрипте Вам ищем реализацию этой функции.
3. Закомментируем строку

BaseDBEdit.Dataset.Values('RemindToOwnerDate') =  BaseDBEdit.Dataset.Values('StartDate');
которая отвечает за проставление текущей даты.
4. Добавьте в эту функцию следующие строки:
var StartDate =  BaseDBEdit.Dataset.Values('StartDate');    
     StartDate  = IsEmptyValue(StartDate) ? new Date() : new Date(StartDate);
     var ToDay = new Date(StartDate.setHours(StartDate.getHours() + 2));
     BaseDBEdit.Dataset.Values('RemindToOwnerDate') = ToDay.getVarDate();

5. Сохраните внесенные изменения, перезапустите рабочее приложение Terrasoft CRM и протестируйте работоспособность системы.

С уважением,
Мельникова Екатерина

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать