IDEMPIERE-4911 Silent fail when translated column is shorter than original column (FHCA-2888) (#844)

* IDEMPIERE-4911 Silent fail when translated column is shorter than original column (FHCA-2888)

Changes:
* Saving a value that doesn't fit in the translation now fails with a proper user understandable message
* Synchronize Doc Translation now fails with a user understandable message in case it fails because a value doesn't fit
* When updating a column on a translation table, check for the size of the original column and update the size accordingly
* When updating a translated column, show warnings to user about creating the table, or creating the column, or updating the column size

* IDEMPIERE-4911 Silent fail when translated column is shorter than original column (FHCA-2888)

Improve message for end user
This commit is contained in:
Carlos Ruiz 2021-08-20 13:59:35 +02:00 committed by GitHub
parent f912cf2c21
commit 0167c91424
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 149 additions and 16 deletions

View File

@ -0,0 +1,27 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-4911 Silent fail when translated column is shorter than original column (FHCA-2888)
-- Aug 18, 2021, 8:01:59 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','...',0,0,'Y',TO_DATE('2021-08-18 20:01:59','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-08-18 20:01:59','YYYY-MM-DD HH24:MI:SS'),100,200714,'MismatchTrlColumnSize','D','14ca00be-1dc1-4e27-b908-257704aae45d')
;
-- Aug 18, 2021, 8:13:56 PM CEST
UPDATE AD_Message SET MsgText='Error synchronizing translation, string too long', MsgTip='There is a mismatch in the size of a translated column. Please contact the system administrator to correct the problem.',Updated=TO_DATE('2021-08-18 20:13:56','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200714
;
-- Aug 18, 2021, 9:24:16 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Do not forget to create the corresponding translation table {0} with column {1}',0,0,'Y',TO_DATE('2021-08-18 21:24:15','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-08-18 21:24:15','YYYY-MM-DD HH24:MI:SS'),100,200715,'WarnCreateTrlTable','D','df97a71a-bb65-4ed5-b7dc-000610f807f5')
;
-- Aug 18, 2021, 9:24:27 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Do not forget to create the translation column {0}.{1}',0,0,'Y',TO_DATE('2021-08-18 21:24:26','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-08-18 21:24:26','YYYY-MM-DD HH24:MI:SS'),100,200716,'WarnCreateTrlColumn','D','7bd54fc7-40cc-408d-b88e-ec25f9ae28fa')
;
-- Aug 18, 2021, 9:24:38 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Do not forget to increase the size on translation column {0}.{1} to {2}',0,0,'Y',TO_DATE('2021-08-18 21:24:38','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-08-18 21:24:38','YYYY-MM-DD HH24:MI:SS'),100,200717,'WarnUpdateSizeTrlTable','D','d5951ecd-3d4f-4438-bc48-8d3fbace8693')
;
SELECT register_migration_script('202108182002_IDEMPIERE-4911.sql') FROM dual
;

View File

@ -0,0 +1,24 @@
-- IDEMPIERE-4911 Silent fail when translated column is shorter than original column (FHCA-2888)
-- Aug 18, 2021, 8:01:59 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','...',0,0,'Y',TO_TIMESTAMP('2021-08-18 20:01:59','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-08-18 20:01:59','YYYY-MM-DD HH24:MI:SS'),100,200714,'MismatchTrlColumnSize','D','14ca00be-1dc1-4e27-b908-257704aae45d')
;
-- Aug 18, 2021, 8:13:56 PM CEST
UPDATE AD_Message SET MsgText='Error synchronizing translation, string too long', MsgTip='There is a mismatch in the size of a translated column. Please contact the system administrator to correct the problem.',Updated=TO_TIMESTAMP('2021-08-18 20:13:56','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200714
;
-- Aug 18, 2021, 9:24:16 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Do not forget to create the corresponding translation table {0} with column {1}',0,0,'Y',TO_TIMESTAMP('2021-08-18 21:24:15','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-08-18 21:24:15','YYYY-MM-DD HH24:MI:SS'),100,200715,'WarnCreateTrlTable','D','df97a71a-bb65-4ed5-b7dc-000610f807f5')
;
-- Aug 18, 2021, 9:24:27 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Do not forget to create the translation column {0}.{1}',0,0,'Y',TO_TIMESTAMP('2021-08-18 21:24:26','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-08-18 21:24:26','YYYY-MM-DD HH24:MI:SS'),100,200716,'WarnCreateTrlColumn','D','7bd54fc7-40cc-408d-b88e-ec25f9ae28fa')
;
-- Aug 18, 2021, 9:24:38 PM CEST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Do not forget to increase the size on translation column {0}.{1} to {2}',0,0,'Y',TO_TIMESTAMP('2021-08-18 21:24:38','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-08-18 21:24:38','YYYY-MM-DD HH24:MI:SS'),100,200717,'WarnUpdateSizeTrlTable','D','d5951ecd-3d4f-4438-bc48-8d3fbace8693')
;
SELECT register_migration_script('202108182002_IDEMPIERE-4911.sql') FROM dual
;

View File

@ -20,6 +20,8 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.DBException;
import org.compiere.model.MClient;
import org.compiere.model.MColumn;
import org.compiere.model.MTable;
@ -29,6 +31,7 @@ import org.compiere.util.AdempiereUserError;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Language;
import org.compiere.util.Msg;
/**
@ -103,7 +106,8 @@ public class TranslationDocSync extends SvrProcess
String baseTable = trlTable.substring(0, trlTable.length()-4);
if (log.isLoggable(Level.CONFIG)) log.config(baseTable + ": " + columnNames);
try {
if (client.isMultiLingualDocument()) {
String baselang = Language.getBaseAD_Language();
if (client.getAD_Language().equals(baselang)) {
@ -118,8 +122,8 @@ public class TranslationDocSync extends SvrProcess
.append(baseTable).append("_ID=b.").append(baseTable).append("_ID) WHERE AD_Client_ID=")
.append(getAD_Client_ID()).append(" AND AD_Language=").append(DB.TO_STRING(client.getAD_Language()));
int no = DB.executeUpdate(sql.toString(), get_TrxName());
addLog(0, null, new BigDecimal(no), baseTable);
int no = DB.executeUpdateEx(sql.toString(), get_TrxName());
addBufferLog(0, null, new BigDecimal(no), baseTable, 0, 0);
}
} else {
// auto update all translations
@ -129,9 +133,18 @@ public class TranslationDocSync extends SvrProcess
.append(baseTable).append("_ID=b.").append(baseTable).append("_ID) WHERE AD_Client_ID=")
.append(getAD_Client_ID());
int no = DB.executeUpdate(sql.toString(), get_TrxName());
addLog(0, null, new BigDecimal(no), baseTable);
int no = DB.executeUpdateEx(sql.toString(), get_TrxName());
addBufferLog(0, null, new BigDecimal(no), baseTable, 0, 0);
}
} catch (DBException e) {
String msg = trlTable + " -> ";
if (DBException.isValueTooLarge(e)) {
msg += Msg.getMsg(getCtx(), "MismatchTrlColumnSize");
} else {
msg += e.getLocalizedMessage();
}
throw new AdempiereException(msg, e);
}
} // processTable

View File

@ -36,13 +36,14 @@ import org.compiere.util.DB;
*/
public class DBException extends AdempiereException
{
public static final String DATABASE_OPERATION_TIMEOUT_MSG = "DatabaseOperationTimeout";
public static final String DELETE_ERROR_DEPENDENT_MSG = "DeleteErrorDependent";
public static final String SAVE_ERROR_NOT_UNIQUE_MSG = "SaveErrorNotUnique";
/**
*
*/
private static final long serialVersionUID = 4264201718343118625L;
private static final long serialVersionUID = -1961265420169932726L;
public static final String DATABASE_OPERATION_TIMEOUT_MSG = "DatabaseOperationTimeout";
public static final String DELETE_ERROR_DEPENDENT_MSG = "DeleteErrorDependent";
public static final String SAVE_ERROR_NOT_UNIQUE_MSG = "SaveErrorNotUnique";
private String m_sql = null;
/**
@ -212,7 +213,18 @@ public class DBException extends AdempiereException
return false;
}
}
/**
* Check if value too large for column exception (aka ORA-12899)
* @param e exception
*/
public static boolean isValueTooLarge(Exception e) {
if (DB.isPostgreSQL())
return isSQLState(e, "22001");
//
return isErrorCode(e, 12899);
}
/**
* @param e
*/
@ -227,4 +239,5 @@ public class DBException extends AdempiereException
return null;
}
}
} // DBException

View File

@ -524,6 +524,21 @@ public class MColumn extends X_AD_Column implements ImmutablePOSupport
LogicEvaluator.validate(getReadOnlyLogic());
}
}
// IDEMPIERE-4911
MTable table = MTable.get(getAD_Table_ID());
String tableName = table.getTableName();
if (tableName.toLowerCase().endsWith("_trl")) {
String parentTable = tableName.substring(0, tableName.length()-4);
MColumn column = MColumn.get(getCtx(), parentTable, colname);
if (column != null && column.isTranslated()) {
if (getFieldLength() < column.getFieldLength()) {
log.saveWarning("Warning", "Size increased to " + column.getFieldLength() + " in translated column " + tableName + "." + colname);
setFieldLength(column.getFieldLength());
}
}
}
return true;
} // beforeSave
@ -543,7 +558,26 @@ public class MColumn extends X_AD_Column implements ImmutablePOSupport
|| "EntityType".equals(get_ValueOld(COLUMNNAME_ColumnName).toString()))) {
MChangeLog.resetLoggedList();
}
// IDEMPIERE-4911
if (isTranslated()) {
MTable table = MTable.get(getAD_Table_ID());
String trlTableName = table.getTableName() + "_Trl";
MTable trlTable = MTable.get(getCtx(), trlTableName);
if (trlTable == null) {
log.saveWarning("Warning", Msg.getMsg(getCtx(), "WarnCreateTrlTable", new Object[] {trlTableName, getColumnName()}));
} else {
MColumn trlColumn = MColumn.get(getCtx(), trlTableName, getColumnName());
if (trlColumn == null) {
log.saveWarning("Warning", Msg.getMsg(getCtx(), "WarnCreateTrlColumn", new Object[] {trlTableName, getColumnName()}));
} else {
if (trlColumn.getFieldLength() < getFieldLength()) {
log.saveWarning("Warning", Msg.getMsg(getCtx(), "WarnUpdateSizeTrlTable", new Object[] {trlTableName, getColumnName(), getFieldLength()}));
}
}
}
}
return success;
} // afterSave

View File

@ -3806,7 +3806,18 @@ public abstract class PO
.append(" AND NOT EXISTS (SELECT * FROM ").append(tableName)
.append("_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.")
.append(keyColumn).append("=t.").append(keyColumn).append(")");
int no = DB.executeUpdate(sql.toString(), m_trxName);
int no = -1;
try {
no = DB.executeUpdateEx(sql.toString(), m_trxName);
} catch (DBException e) {
String msg;
if (DBException.isValueTooLarge(e)) {
msg = Msg.getMsg(getCtx(), "MismatchTrlColumnSize");
} else {
msg = "insertTranslations -> " + e.getLocalizedMessage();
}
throw new AdempiereException(msg, e);
}
if (uuidColumn != null && !uuidFunction) {
UUIDGenerator.updateUUID(uuidColumn, get_TrxName());
}
@ -3887,6 +3898,7 @@ public abstract class PO
StringBuilder andNotBaseLang = new StringBuilder(" AND AD_Language!=").append(DB.TO_STRING(baselang));
int no = -1;
try {
if (client.isMultiLingualDocument()) {
if (client.getAD_Language().equals(baselang)) {
// tenant language = base language
@ -3895,7 +3907,7 @@ public abstract class PO
.append(sqlupdate)
.append("IsTranslated='N'")
.append(whereid);
no = DB.executeUpdate(sqlexec.toString(), m_trxName);
no = DB.executeUpdateEx(sqlexec.toString(), m_trxName);
if (log.isLoggable(Level.FINE)) log.fine("#" + no);
} else {
// tenant language <> base language
@ -3907,7 +3919,7 @@ public abstract class PO
.append("IsTranslated='Y'")
.append(whereid)
.append(getAD_Client_ID() == 0 ? andBaseLang : andClientLang);
no = DB.executeUpdate(sqlexec.toString(), m_trxName);
no = DB.executeUpdateEx(sqlexec.toString(), m_trxName);
if (log.isLoggable(Level.FINE)) log.fine("#" + no);
if (no >= 0) {
// set other translations as untranslated
@ -3916,7 +3928,7 @@ public abstract class PO
.append("IsTranslated='N'")
.append(whereid)
.append(getAD_Client_ID() == 0 ? andNotBaseLang : andNotClientLang);
no = DB.executeUpdate(sqlexec.toString(), m_trxName);
no = DB.executeUpdateEx(sqlexec.toString(), m_trxName);
if (log.isLoggable(Level.FINE)) log.fine("#" + no);
}
}
@ -3928,9 +3940,19 @@ public abstract class PO
.append(sqlcols)
.append("IsTranslated='Y'")
.append(whereid);
no = DB.executeUpdate(sqlexec.toString(), m_trxName);
no = DB.executeUpdateEx(sqlexec.toString(), m_trxName);
if (log.isLoggable(Level.FINE)) log.fine("#" + no);
}
} catch (DBException e) {
String msg;
if (DBException.isValueTooLarge(e)) {
msg = Msg.getMsg(getCtx(), "MismatchTrlColumnSize");
} else {
msg = "updateTranslations -> " + e.getLocalizedMessage();
}
throw new AdempiereException(msg, e);
}
return no >= 0;
} // updateTranslations