@@ -161,7 +161,9 @@ public void copyAttachments(AttachmentCopyEventContext context) throws IOExcepti
161161 .customPropertyValues (null )
162162 .build ();
163163
164- createDraftEntries (draftRequest , customPropertyDefinitions );
164+ // Pass the entity for type conversion
165+ CdsEntity targetEntity = entity .isPresent () ? entity .get () : null ;
166+ createDraftEntries (draftRequest , customPropertyDefinitions , targetEntity );
165167
166168 context .setCompleted ();
167169 }
@@ -1297,6 +1299,17 @@ private void processSecondaryProperty(
12971299 return ;
12981300 }
12991301
1302+ // Check if this is an association field (e.g., customProperty1)
1303+ // For associations, we should only populate the foreign key field (e.g., customProperty1_code)
1304+ // Skip the association field itself as CDS will resolve it from the _code field
1305+ CdsElement element = targetEntity .getElement (dbPropertyName );
1306+ if (element != null && element .getType ().isAssociation ()) {
1307+ logger .info (
1308+ "Skipping association field '{}' - association will be resolved from corresponding _code field" ,
1309+ dbPropertyName );
1310+ return ;
1311+ }
1312+
13001313 Object convertedValue = convertValueIfNeeded (value , dbPropertyName , targetEntity );
13011314 filteredProperties .put (dbPropertyName , convertedValue );
13021315 logger .info ("Added to DB map: '{}' = '{}'" , dbPropertyName , convertedValue );
@@ -1312,28 +1325,36 @@ private void processSecondaryProperty(
13121325 * @return converted value or original value if no conversion needed
13131326 */
13141327 private Object convertValueIfNeeded (Object value , String dbPropertyName , CdsEntity targetEntity ) {
1315- if (!(value instanceof Long )) {
1316- return value ;
1317- }
1328+ // Handle Long values - convert to Instant for DateTime fields
1329+ if (value instanceof Long ) {
1330+ CdsElement element = targetEntity .getElement (dbPropertyName );
1331+ if (isDateTimeField (element )) {
1332+ Object converted = Instant .ofEpochMilli ((Long ) value );
1333+ logger .info (
1334+ "Converted Long timestamp {} to Instant {} for DateTime field '{}'" ,
1335+ value ,
1336+ converted ,
1337+ dbPropertyName );
1338+ return converted ;
1339+ }
13181340
1319- CdsElement element = targetEntity .getElement (dbPropertyName );
1320- if (isDateTimeField (element )) {
1321- Object converted = Instant .ofEpochMilli ((Long ) value );
13221341 logger .info (
1323- "Converted Long timestamp {} to Instant {} for DateTime field '{}'" ,
1342+ "Keeping Long value {} as-is for non- DateTime field '{}' (type: {}) " ,
13241343 value ,
1325- converted ,
1326- dbPropertyName );
1327- return converted ;
1344+ dbPropertyName ,
1345+ element != null && element .getType () != null
1346+ ? element .getType ().getQualifiedName ()
1347+ : "unknown" );
1348+ return value ;
13281349 }
13291350
1351+ // For all other types (String, Integer, Boolean, etc.), return as-is
1352+ // This ensures codelist/dropdown String values are properly handled
13301353 logger .info (
1331- "Keeping Long value {} as-is for non-DateTime field '{}' (type: {}) " ,
1354+ "Keeping value {} (type: {}) as-is for field '{}'" ,
13321355 value ,
1333- dbPropertyName ,
1334- element != null && element .getType () != null
1335- ? element .getType ().getQualifiedName ()
1336- : "unknown" );
1356+ value != null ? value .getClass ().getSimpleName () : "null" ,
1357+ dbPropertyName );
13371358 return value ;
13381359 }
13391360
@@ -1349,6 +1370,81 @@ private boolean isDateTimeField(CdsElement element) {
13491370 && "cds.DateTime" .equals (element .getType ().getQualifiedName ());
13501371 }
13511372
1373+ /**
1374+ * Converts custom property value from String to appropriate type based on CDS field definition.
1375+ * Used for copy operations where values come as String from SDM response.
1376+ *
1377+ * @param value the String value from SDM
1378+ * @param dbPropertyName the DB field name
1379+ * @param targetEntity the target entity for type checking
1380+ * @return converted value or original value if no conversion needed
1381+ */
1382+ private Object convertCustomPropertyValue (
1383+ String value , String dbPropertyName , CdsEntity targetEntity ) {
1384+ if (value == null || value .isEmpty () || targetEntity == null ) {
1385+ return value ;
1386+ }
1387+
1388+ CdsElement element = targetEntity .getElement (dbPropertyName );
1389+ if (element == null || element .getType () == null ) {
1390+ return value ;
1391+ }
1392+
1393+ String fieldType = element .getType ().getQualifiedName ();
1394+
1395+ try {
1396+ // Handle DateTime fields - convert Long timestamp to Instant
1397+ if ("cds.DateTime" .equals (fieldType )) {
1398+ long timestamp = Long .parseLong (value );
1399+ Object converted = Instant .ofEpochMilli (timestamp );
1400+ logger .info (
1401+ "Converted String timestamp '{}' to Instant {} for DateTime field '{}'" ,
1402+ value ,
1403+ converted ,
1404+ dbPropertyName );
1405+ return converted ;
1406+ }
1407+
1408+ // Handle Integer fields
1409+ if ("cds.Integer" .equals (fieldType )) {
1410+ int convertedInt = Integer .parseInt (value );
1411+ logger .info (
1412+ "Converted String '{}' to Integer {} for field '{}'" ,
1413+ value ,
1414+ convertedInt ,
1415+ dbPropertyName );
1416+ return convertedInt ;
1417+ }
1418+
1419+ // Handle Boolean fields
1420+ if ("cds.Boolean" .equals (fieldType )) {
1421+ boolean convertedBool = Boolean .parseBoolean (value );
1422+ logger .info (
1423+ "Converted String '{}' to Boolean {} for field '{}'" ,
1424+ value ,
1425+ convertedBool ,
1426+ dbPropertyName );
1427+ return convertedBool ;
1428+ }
1429+
1430+ } catch (NumberFormatException e ) {
1431+ logger .warn (
1432+ "Failed to convert value '{}' for field '{}' of type '{}', keeping as String: {}" ,
1433+ value ,
1434+ dbPropertyName ,
1435+ fieldType ,
1436+ e .getMessage ());
1437+ }
1438+
1439+ // For String fields (including codelist/dropdown) and other types, return as-is
1440+ logger .info (
1441+ "Keeping String value '{}' as-is for field '{}' (type: {})" ,
1442+ value ,
1443+ dbPropertyName ,
1444+ fieldType );
1445+ return value ;
1446+ }
1447+
13521448 // Rollback a single attachment to source folder
13531449 private void rollbackSingleAttachment (
13541450 String objectId ,
@@ -1521,7 +1617,9 @@ private void createDraftEntriesForMove(DraftEntryMoveData data) {
15211617 * copy operations where custom properties come from the SDM copyAttachment response.
15221618 */
15231619 private void createDraftEntries (
1524- CreateDraftEntriesRequest request , Map <String , String > customPropertyDefinitions ) {
1620+ CreateDraftEntriesRequest request ,
1621+ Map <String , String > customPropertyDefinitions ,
1622+ CdsEntity targetEntity ) {
15251623
15261624 for (int i = 0 ; i < request .getAttachmentsMetadata ().size (); i ++) {
15271625 Map <String , String > attachmentMetadata = request .getAttachmentsMetadata ().get (i );
@@ -1565,7 +1663,9 @@ private void createDraftEntries(
15651663
15661664 if (attachmentMetadata .containsKey (sdmPropertyName )) {
15671665 String value = attachmentMetadata .get (sdmPropertyName );
1568- updatedFields .put (columnName , value );
1666+ // Convert value based on CDS field type
1667+ Object convertedValue = convertCustomPropertyValue (value , columnName , targetEntity );
1668+ updatedFields .put (columnName , convertedValue );
15691669 }
15701670 }
15711671 }
0 commit comments