Александра, к сожалению, пошаговой инструкции как это реализовать нет, но Вы можете попробовать реализовать по аналогии с базовыми разделами.
Вся логика, как общая, так и по модификации конкретных разделов, находится в пакете Completeness. Например, там есть замещение объекта Account с добавлением числового поля Completeness, а также замещение AccountPageV2 с добавлением в неё компонентов AccountCompletenessContainer, CompletenessValue, CompletenessTip, атрибутов CompletenessValue и MissingParametersCollection и скриптов для управления ими.
И общее для всех разделов: в объекте Completeness хранится список объектов, по которым запускается функциональность пересчета обновления профиля (это справочник «Полнота наполнения данными»), далее в объекте CompletenessParameter]хранится список параметров/полей, по которым рассчитывается полнота из объекта выше (это уже справочник «Полнота наполнения данными»). Далее в системе используется бизнес-процесс «Обновить полноту профиля» для массового пересчета показателя полноты профиля, к примеру, после импорта из Excel. А также бизнес процесс «Запустить обновление полноты профиля», который выполняет обновление данных по наполнению для конкретной записи. В свою очередь, при запуске процесса «Обновление полноты профиля» в базе данных вызывается процедура tsp_CompletenessRenew.
Идея добавить возможность пользовательского включения полноты профиля в любом разделе системы уже зафиксирована.
Ошибка при запуске "полнота наполнения данными" вручную процесса. В академии написано что необходимо запустить бизнес-процесс “Обновить полноту профиля”, но это приводит в ошибке. Подскажите как правильно произвести пересчет этого показателя?
Если бы тут привели текст выводимого на экран или в логи при запуске БП сообщения, гадать о причинах было бы намного легче: фаза Луны, погода на Марсе...
А так можно только посоветовать воспользоваться инструментами Visual Studio и Management Studio: отладить функцию RecalculateAll в схеме BaseCompletenessService, которую запускает этот БП и запустить с теми же параметрами хранимку tsp_CompletenessRenew в базе, которую функция запускает.
Oracle.DataAccess.Client.OracleException ORA-00936: missing expression
ORA-06512: at "BPM.tspkg_Completeness", line 113
ORA-06512: at line 2 at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck)
at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
at Polly.Policy.<>c__DisplayClass119_0`1.<Execute>b__0(Context ctx, CancellationToken ct)
at Polly.Policy.<>c__DisplayClass129_0`1.<ExecuteInternal>b__0(Context ctx, CancellationToken ct)
at Polly.Policy.<>c__DisplayClass103_0.<NoOp>b__1(Context ctx, CancellationToken ct)
at Polly.NoOp.NoOpEngine.Implementation[TResult](Func`3 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.<>c.<NoOp>b__103_0(Action`2 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.ExecuteInternal[TResult](Func`3 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.Execute[TResult](Func`3 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.Execute[TResult](Func`1 action)
at Terrasoft.DB.Oracle.OracleExecutor.FailoverExecute[TResult](DbCommand command, Func`1 func)
at Terrasoft.Core.DB.DBExecutor.ExecuteCommand[TResult](Func`2 commandExecutionCallback, String sqlText, QueryParameterCollection queryParameters, CancellationToken cancellationToken)
at Terrasoft.Core.DB.DBExecutor.Execute(String sqlText, QueryParameterCollection queryParameters)
at Terrasoft.Core.DB.StoredProcedure.Execute()
at Terrasoft.Configuration.BaseCompletenessService.RecalculateAll()
at Terrasoft.Core.Process.CompletenessRenew.ScriptTask1Execute(ProcessExecutingContext context)
at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)
Если запускать "Запустить обновление полноты профиля"
System.NullReferenceException: Object reference not set to an instance of an object.
at Terrasoft.Configuration.BaseCompletenessService.get_AppConnection()
at Terrasoft.Configuration.BaseCompletenessService.RecalculateAllByCompleteness(Guid completenessId)
at Terrasoft.Configuration.BaseCompletenessService.RecalculateAll()
at Terrasoft.Core.Process.CompletenessRenew.ScriptTask1Execute(ProcessExecutingContext context)
at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)
Значит ещё и используется Oracle... Нужно смотреть, что находится в пакете spkg_Completeness во второй строке и во входящей в него хранимке tsp_CompletenessRenew в 113 строке и рядом. Были ли в них доработки?
Есть ли замещения схемы BaseCompletenessService? Если есть, попробуйте удалить, скомпилироваться, повторить запуск процесса.
Изменений и замещений нет. Содержание хранимой процедуры
create or replace PACKAGE BODY "tspkg_Completeness"
AS
FUNCTION "fn_Is_Number"(stringValue IN VARCHAR2)
RETURN INT
IS
new_Number NUMBER;
BEGIN
new_Number := TO_NUMBER(stringValue);
RETURN 1;
EXCEPTION
WHEN VALUE_ERROR THEN
RETURN 0;
END;
PROCEDURE "tsp_CompletenessRenew"(CompletenessId VARCHAR2)
IS
BEGIN
DECLARE
EntitySchemaName VARCHAR2(50);
TypeColumn VARCHAR2(50);
TypeValue VARCHAR2(38);
ResultColumn VARCHAR2(50);
sqlcmd VARCHAR2(30000);
createTableSql VARCHAR2(30000);
whereSql VARCHAR2(30000);
updateSql VARCHAR2(30000);
fromSelectSql VARCHAR2(30000);
c_id VARCHAR2(38);
c_column_name VARCHAR2(500);
c_detail_name VARCHAR2(500);
c_detail_column VARCHAR2(500);
c_master_column VARCHAR2(500);
c_is_column VARCHAR2(1);
c_is_detail VARCHAR2(1);
c_percentage INT;
c_type_column VARCHAR2(50);
c_type_value VARCHAR2(38);
typed_detail_name VARCHAR2(500);
attributes_count INT;
CURSOR attributes_cursor IS
SELECT
cp."Id",
cp."ColumnName",
cp."DetailEntityName",
cp."DetailColumn",
cp."MasterColumn",
cp."IsColumn",
cp."IsDetail",
cp."Percentage",
cp."TypeColumn",
cp."TypeValue"
FROM "CompletenessParameter" cp
WHERE cp."CompletenessId"=(
SELECT "Id" FROM "Completeness" c WHERE c."Id"= CompletenessId);
BEGIN
attributes_count :=0;
SELECT "EntitySchemaName", "TypeColumnName", "TypeColumnValue", "ResultColumnName"
INTO EntitySchemaName, TypeColumn, TypeValue, ResultColumn
FROM "Completeness" WHERE "Id"= CompletenessId;
createTableSql :='CREATE TABLE "CalcCompleteness" AS SELECT "Id", "'||ResultColumn||'", SUM(';
fromSelectSql :='FROM "'|| entitySchemaName ||'" a ';
whereSql :=' WHERE ';
OPEN attributes_cursor;
LOOP
FETCH attributes_cursor into
c_id,
c_column_name,
c_detail_name,
c_detail_column,
c_master_column,
c_is_column,
c_is_detail,
c_percentage,
c_type_column,
c_type_value;
EXIT WHEN attributes_cursor%notfound;
attributes_count := attributes_count +1;
IF c_is_column ='1' THEN
createTableSql := createTableSql ||' CASE WHEN ("'|| c_column_name ||'" IS NULL) OR (LENGTH("'|| c_column_name ||'") = 0)';
createTableSql := createTableSql ||' OR ("tspkg_Completeness"."fn_Is_Number"("'|| c_column_name ||'") = 1 AND TO_NUMBER("'|| c_column_name ||'") = 0) THEN 0 ELSE '|| c_percentage ||' END +';
ELSE
typed_detail_name := c_detail_name;
IF (c_type_column IS NOT NULL OR c_type_column <>'') AND (c_type_value IS NOT NULL OR c_type_value <>'') THEN
typed_detail_name := c_detail_name || TO_CHAR(attributes_count);
END IF;
createTableSql := createTableSql ||' CASE WHEN NVL('|| typed_detail_name ||'."'|| c_detail_name ||'", 0) = 0 THEN 0 ELSE '|| c_percentage ||' END +';
fromSelectSql := fromSelectSql ||', (SELECT COUNT("'|| c_detail_name ||'"."'||c_detail_column||'") "'|| c_detail_name ||'", "'||c_detail_column||'" FROM "'||c_detail_name||'"';
IF (c_type_column IS NOT NULL OR c_type_column <>'') AND (c_type_value IS NOT NULL OR c_type_value <>'') THEN
fromSelectSql := fromSelectSql ||' WHERE "'|| c_detail_name ||'"."'||c_type_column||'" = '''||c_type_value||'''';
END IF;
fromSelectSql := fromSelectSql ||' GROUP BY "'||c_detail_column||'") '|| typed_detail_name;
whereSql := whereSql ||'a."Id" = '||typed_detail_name||'."'||c_detail_column||'"(+) AND ';
END IF;
END LOOP;
CLOSE attributes_cursor;
IF attributes_count <>0 THEN
createTableSql := SUBSTR(createTableSql, 0, LENGTH(createTableSql)-2);
createTableSql := createTableSql ||') AS "NewCompleteness"';
whereSql := SUBSTR(whereSql, 0, LENGTH(whereSql)-6);
IF (TypeColumn IS NOT NULL OR TypeColumn <>'')
AND (TypeValue IS NOT NULL OR TypeValue <>'') THEN
whereSql := whereSql ||' AND a."'|| TypeColumn ||'" = '''||TypeValue||'''';
END IF;
createTableSql := createTableSql || fromSelectSql || whereSql;
createTableSql := createTableSql ||' GROUP BY a."Id", a."'||ResultColumn||'"';
EXECUTE IMMEDIATE createTableSql;
sqlcmd :='CREATE UNIQUE INDEX calcCompleteness_id_ix ON "CalcCompleteness" ("Id")';
EXECUTE IMMEDIATE sqlcmd;
updateSql :='UPDATE
(SELECT
t1."Id",
t2."Id",
t1."'||ResultColumn||'" "Completeness1",
t2."NewCompleteness" "NewCompleteness"
FROM
"'||EntitySchemaName||'" t1,
"CalcCompleteness" t2 WHERE t1."Id" = t2."Id" AND t1."'||ResultColumn||'" <> t2."NewCompleteness") SET "Completeness1" = "NewCompleteness"';
EXECUTE IMMEDIATE updateSql;
sqlcmd :='DROP TABLE "CalcCompleteness"';
EXECUTE IMMEDIATE sqlcmd;
ELSE
sqlcmd :='UPDATE "'||EntitySchemaName||'" SET "'||ResultColumn||'" = 0';
EXECUTE IMMEDIATE sqlcmd;
END IF;
END;
END;
END "tspkg_Completeness";
Попробуйте для отладки запускать функцию с тем же параметром, которым его запускает система,чтобы увидеть, где именно падает выполнение хранимки. Возможно, в разделе настраивали детали и у одной из них что-то настроено некорректно.