CSV Upload und Verarbeitung mit RAP am Beispiel von Geschaeftspartner-Personen

Aus SAP Wiki ツ

Das Ziel dieser Übung war ein CSV Upload und Verarbeitung mit RAP umzusetzen.

Die zu verarbeitenden Daten sind allgemeine Geschäftspartner-Personen Daten.

Verwendeter Code für die Verarbeitung wurden nicht mit Cloudification Repository Viewer o.ä. abgeglichen.

D.h. bei der eigenen umzusetzenden RAP-App im Produktivumfeld ist darauf natürlich zu achten nach Möglichkeit freigegebenem bzw. Clean-Core-Level A-B Code zu verwenden.

Von der Modellierung sollte man die CSV File und die Zeilen der Datei als Eltern-Kind Beziehung darstellen. Bei der Testentwicklung habe ich direkt die Projection auf die Basic Views gelegt. Hier fehlt klar die Consumption-/Composite-Views dazwischen. Das sollte man bei der eigenen Umsetzung berücksichtigen. Für mich interessant bei dem Test war nur das Handling mit der .csv Datei.

Die beschriebenen Objekte wurden in Bezug zu den Datenbanktabellen mit Rechtsklick "Generate ABAP Repository Objects..." erstellt. Die Bezeichner habe ich nicht geändert und nicht notwendigen Objekte auch nicht mehr entfernt.

Ursprünglich wollte ich die CSV als rawstring nicht in einer DB-Tabelle speichern, sondern direkt als PopUp als Import zur Verfügung stehen haben, aber das geht bislang anscheinend nur in der Cloud Public, weshalb der File Upload via ObjectPage laufen muss. S. Codeblock für die ursprüngliche Idee den rawstring direkt zur Verfügung zu haben:

Codeblock
abstract;
strict ( 2 );
with hierarchy;
define behavior for ZA_YMD_BP_CSV_UPLOAD_STREAM alias uploadStream
{
}

abstract;
strict ( 2 );
with hierarchy;
define behavior for ZA_YMD_BP_CSV_UPLOAD_FILE alias uploadFile
{
  association _StreamProperties with hierarchy;
}

Vorschau

Galerie

Umsetzung

Datenbanktabellen

Die Daten der .csv Datei werden als rawstring in einer DB-Tabelle gespeichert.

Beim Hochladen der Datei werden direkt die Zeilen der .csv Datei gelesen und in eine DB-Tabelle gespeichert.

Zu der Verarbeitung jeder Zeile der Datei gibt es ein Log, die in einer DB-Tabelle gespeichert wird.

DB-Tabelle CSV-Upload
@EndUserText.label : 'csv upload'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ymd_bp_csvupload {

  key client            : abap.clnt not null;
  key fileid            : abap.int4 not null;
  status                : abap.char(2);
  attachment            : abap.rawstring(0);
  mimetype              : abap.char(128);
  filename              : abap.char(128);
  created_by            : abp_creation_user;
  created_at            : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}
DB-Tabelle CSV-Upload Draft
@EndUserText.label : '##GENERATED YMD_BPCSVUPLOAD'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zymd_bp_csvuplod {

  key mandt             : mandt not null;
  key fileid            : abap.int4 not null;
  key draftuuid         : sdraft_uuid not null;
  status                : abap.char(2);
  statuscriticality     : abap.int1;
  statuscriticalitytext : abap.char(29);
  attachment            : abap.rawstring(0);
  mimetype              : abap.char(128);
  filename              : abap.char(128);
  createdby             : abp_creation_user;
  createdat             : abp_creation_tstmpl;
  locallastchangedby    : abp_locinst_lastchange_user;
  locallastchangedat    : abp_locinst_lastchange_tstmpl;
  lastchangedat         : abp_lastchange_tstmpl;
  "%admin"              : include sych_bdl_draft_admin_inc;
}
DB-Tabelle CSV-Zeilen
 @EndUserText.label : 'csv rows'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ymd_bp_csv_rows {

  key client            : abap.clnt not null;
  key fileid            : abap.int4 not null;
  key fileidrow         : abap.int4 not null;
  bp                    : abap.char(10);
  firstname             : abap.char(40);
  lastname              : abap.char(40);
  title                 : abap.char(50);
  gender                : abap.char(1);
  languagecode          : abap.lang;
  salutation            : abap.char(20);
  street1               : abap.char(60);
  street2               : abap.char(60);
  postalcode            : abap.char(10);
  city                  : abap.char(40);
  county                : abap.char(40);
  country               : abap.char(3);
  phone                 : abap.char(30);
  mobilephone           : abap.char(30);
  fax                   : abap.char(30);
  email                 : abap.char(241);
  created_by            : abp_creation_user;
  created_at            : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;
}
DB-Tabelle Ergebnis Verarbeitung GP
@EndUserText.label : 'YMD_BP_CSVUP_CRBP'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ymd_bp_csvupcrbp {

  key client    : abap.clnt not null;
  key fileid    : abap.int4 not null;
  key fileidrow : abap.int4 not null;
  status        : abap.char(2);
  bpid          : abap.char(10);
  logid         : abap.int4;

}
DB-Tabelle Log Verarbeitung GP
@EndUserText.label : 'log'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ymd_bp_upcrbplog {

  key client    : abap.clnt not null;
  key logid     : abap.int4 not null;
  key logitemid : abap.int4 not null;
  message       : abap.string(1024);

}

CDS-Views

Basic Views auf die DB-Tabellen

Basic View auf DB-Tabelle CSV-Upload
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '##GENERATED YMD_BP_CSVUPLOAD'
define root view entity ZR_YMD_BP_CSVUPLOAD
  as select from ymd_bp_csvupload as BP_CSVUPLOAD 

  association [1..*] to ZR_YMD_BP_CSVUPLOAD_CREAT_BP  as _ResultCreationBP 
  on _ResultCreationBP.Fileid = $projection.FileID
  
  association [1..*] to ZR_YMD_BP_CSV_ROWS  as _CSVRows 
  on _CSVRows.FileID = $projection.FileID  
 
{

  key  fileid as FileID,
  status as Status,
        case status
        when '00' then 1 // version in work | 1 red color
        when '01' then 0 // version in work | 0: no color
        when '02' then 3 // release done    | 3: green color
        when '03' then 2 // release in progress | 2: yellow color
        when '04' then 1
        else 1
      end as StatusCriticality,
  case status
        when '00' then 'Unknown Processing State'
        when '01' then 'Ready'
        when '02' then 'BP creation successful'
        when '03' then 'BP creation partly successful'
        when '04' then 'BP creation failed'
        else 'Unknown Processing State'
  end as StatusCriticalityText,
  attachment as Attachment,
  mimetype as MimeType,
  filename as FileName,
  @Semantics.user.createdBy: true
  created_by as CreatedBy,
  @Semantics.systemDateTime.createdAt: true
  created_at as CreatedAt,
  @Semantics.user.localInstanceLastChangedBy: true
  local_last_changed_by as LocalLastChangedBy,
  @Semantics.systemDateTime.localInstanceLastChangedAt: true
  local_last_changed_at as LocalLastChangedAt,
  @Semantics.systemDateTime.lastChangedAt: true
  last_changed_at as LastChangedAt
}
Basic View auf DB-Tabelle CSV-Zeilen
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '##GENERATED YMD_BP_CSV_ROWS'
define root view entity ZR_YMD_BP_CSV_ROWS
  as select from ymd_bp_csv_rows as CSVRows

association [1..*] to ZR_YMD_BP_CSVUPLOAD_CREAT_BP as _ResultCreatedBP
 on   _ResultCreatedBP.Fileid    = $projection.FileID
  and _ResultCreatedBP.Fileidrow = $projection.FileIDRow

   association [1] to ZR_YMD_BP_CSVUPLOAD  as _CSVUpload
  on _CSVUpload.FileID = $projection.FileID

{
  key fileid as FileID,
  key fileidrow as FileIDRow,
  bp as Bp,
  firstname as Firstname,
  lastname as Lastname,
  title as Title,
  gender as Gender,
  languagecode as Languagecode,
  salutation as Salutation,
  street1 as Street1,
  street2 as Street2,
  postalcode as Postalcode,
  city as City,
  county as County,
  country as Country,
  phone as Phone,
  mobilephone as Mobilephone,
  fax as Fax,
  email as Email,
  @Semantics.user.createdBy: true
  created_by as CreatedBy,
  @Semantics.systemDateTime.createdAt: true
  created_at as CreatedAt,
  @Semantics.user.localInstanceLastChangedBy: true
  local_last_changed_by as LocalLastChangedBy,
  @Semantics.systemDateTime.localInstanceLastChangedAt: true
  local_last_changed_at as LocalLastChangedAt,
  @Semantics.systemDateTime.lastChangedAt: true
  last_changed_at as LastChangedAt
  
}
Basic View auf DB-Tabelle Ergebnis Verarbeitung GP
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'ZR_YMD_BP_CSVUPLOAD_CREAT_BP'
@Metadata.ignorePropagatedAnnotations: true
define root view entity ZR_YMD_BP_CSVUPLOAD_CREAT_BP as select from ymd_bp_csvupcrbp as csvUpload
{
  key fileid as Fileid,
  key fileidrow as Fileidrow,
  status as Status,
        case status
        when '00' then 0 // version in work | 0: unknown
        when '01' then 3 // version in work | 0: unknown
        when '02' then 1 // release done    | 3: green color
        else 0
      end as StatusCriticality,
  case status
        when '00' then 'Unknown' // version in work | 0: unknown
        when '01' then 'BP creation successful' // version in work | 0: unknown
        when '02' then 'BP creation failed' // release done    | 3: green color
        else 'Unkown'
      end as StatusCriticalityText,
  bpid as BpID,
  logid as LogID
}
Basic View auf DB-Tabelle Log Verarbeitung GP
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'lolg'
define root view entity ZR_YMD_BP_CSVUP_CREAT_BP_LOG as select from ymd_bp_upcrbplog
{
         
    key logid as Logid,
    key logitemid as Logitemid,
    message as Message
}

Projection Views

Projection View CSV-Upload
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: 'Projection View CSV Upload'
@ObjectModel.semanticKey: [ 'FileID' ]
define root view entity ZC_YMD_BP_CSVUPLOAD
  provider contract transactional_query
  as projection on ZR_YMD_BP_CSVUPLOAD
  
  association [1..*] to ZC_YMD_BP_CSVUPLOAD_CREAT_BP  as _ResultCreationBP 
  on _ResultCreationBP.Fileid = $projection.FileID
  
  association [1] to ZC_YMD_BP_CSV_ROWS  as _CSVRows 
  on _CSVRows.FileID = $projection.FileID     
    
  {
  
  key FileID,
  @ObjectModel.text.element: [ 'StatusCriticalityText' ]
  Status,
  StatusCriticality,
  StatusCriticalityText,
  FileName,
        @Semantics.largeObject: {
        contentDispositionPreference: #INLINE, // #ATTACHMENT - download as file
                                                   // #INLINE - open in new window
        fileName: 'FileName',
        mimeType: 'MimeType' }
  Attachment,
  @Semantics.mimeType: true
  MimeType,
  LocalLastChangedAt,
  
  _CSVRows,
  _ResultCreationBP
    
}
Metadata Extensions
@Metadata.layer: #CORE
@UI: {
  headerInfo: {
    typeName: 'Businesspartner CSV Upload', 
    typeNamePlural: 'Businesspartner CSV Upload'
  }
}
annotate view ZC_YMD_BP_CSVUPLOAD with
{
     
 // --- HEADER
  @UI.facet: [ 
  
  {
   id: 'FilenameDataHeader',
   purpose: #HEADER,
   type: #DATAPOINT_REFERENCE,
   position: 10,
   targetQualifier: 'FilenameData' 
  },
  {
   
   id: 'FileDataHeader',
   purpose: #HEADER,
   type: #DATAPOINT_REFERENCE,
   position: 10,
   targetQualifier: 'FileData' 
  },
  {
   id: 'StatusDataHeader',
   purpose: #HEADER,
   type: #DATAPOINT_REFERENCE,
   position: 20,
   targetQualifier: 'StatusData' 
  },
  
  {
  id         : 'idFiles',
  label      : 'File Upload',
  position   : 10,
  type       : #IDENTIFICATION_REFERENCE,
  targetQualifier: 'FILE' }
// GROUPS
   , {
      id: 'CSVUploadRows',
      purpose: #STANDARD,
      type: #LINEITEM_REFERENCE,
      label: 'File Processing',
      position: 20,
      targetElement: '_ResultCreationBP'
    }
    , {
      id: 'CreationBP',
      purpose: #STANDARD,
      type: #LINEITEM_REFERENCE,
      label: 'File Entries',
      position: 10,
      targetElement: '_CSVRows'
    }

]

  @UI.lineItem: [ {
    position: 10 , 
    importance: #HIGH, 
    label: 'File ID' } ]
  @UI.dataPoint: { qualifier: 'FileData', title: 'File ID' }
  FileID;
  
  @UI.lineItem: [ {
    position: 20 , 
    importance: #MEDIUM, 
    label: 'Status',
    criticality: 'StatusCriticality'
  } ]
  @UI.dataPoint: { qualifier: 'StatusData', title: 'Status', criticality: 'StatusCriticality' }
  Status;
    
  @UI.hidden: true
  LocalLastChangedAt;
  
  @UI.dataPoint: { qualifier: 'FilenameData', title: 'Filename' }
  FileName;
  
  @UI:{ identification: [{ position: 80, qualifier: 'FILE' }] }
  Attachment;
}


Projection View CSV-Zeilen
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: 'Projection View CSV Rows'
define root view entity ZC_YMD_BP_CSV_ROWS
  provider contract transactional_query
  as projection on ZR_YMD_BP_CSV_ROWS

  association [1..*] to ZC_YMD_BP_CSVUPLOAD_CREAT_BP as _ResultCreatedBP
 on   _ResultCreatedBP.Fileid    = $projection.FileID
  and _ResultCreatedBP.Fileidrow = $projection.FileIDRow
  
   association [1] to ZC_YMD_BP_CSVUPLOAD  as _CSVUpload
  on _CSVUpload.FileID = $projection.FileID
{
  key FileID,           
  key FileIDRow,    
  Bp,           
  Firstname,
  Lastname,
  Title,
  Gender,
  Languagecode,
  Salutation,
  Street1,
  Street2,
  Postalcode,
  City,
  County,
  Country,
  Phone,
  Mobilephone,
  Fax,
  Email,
  LocalLastChangedAt
}
Metadata Extensions
@Metadata.layer: #CORE
@UI: {
  headerInfo: {
    typeName: 'CSV Row', 
    typeNamePlural: 'CSV Rows'
  }
}
annotate view ZC_YMD_BP_CSV_ROWS with
{
  
    @UI.lineItem: [ {
    position: 1 , 
    importance: #MEDIUM, 
    type: #STANDARD,
    label: 'File ID' }]
    @UI.dataPoint: { qualifier: 'FileData', title: 'File ID' }           
    FileID;
    
    @UI.lineItem: [ {
    position: 2 , 
    importance: #MEDIUM, 
    label: 'File Row ID' } ]
    @UI.dataPoint: { qualifier: 'FileRowData', title: 'File Row ID' }   
    FileIDRow;
  
  @UI.facet: [ {
    id: 'idIdentification', 
    type: #IDENTIFICATION_REFERENCE, 
    label: 'CSVRows', 
    position: 10
  } ]
  @UI.lineItem: [ {
    position: 10 , 
    importance: #MEDIUM, 
    label: 'Bp'
  },  { type: #FOR_ACTION,
         dataAction: 'Process',
         label: 'Process',
         invocationGrouping:#CHANGE_SET,
         position: 10,
         importance: #HIGH }  ]
  @UI.identification: [ {
    position: 10 , 
    label: 'Bp'
  } ]
  Bp;
  
  @UI.lineItem: [ {
    position: 20 , 
    importance: #MEDIUM, 
    label: 'Firstname'
  } ]
  @UI.identification: [ {
    position: 20 , 
    label: 'Firstname'
  } ]
  Firstname;
  
  @UI.lineItem: [ {
    position: 30 , 
    importance: #MEDIUM, 
    label: 'Lastname'
  } ]
  @UI.identification: [ {
    position: 30 , 
    label: 'Lastname'
  } ]
  Lastname;
  
  @UI.lineItem: [ {
    position: 40 , 
    importance: #MEDIUM, 
    label: 'Title'
  } ]
  @UI.identification: [ {
    position: 40 , 
    label: 'Title'
  } ]
  Title;
  
  @UI.lineItem: [ {
    position: 50 , 
    importance: #MEDIUM, 
    label: 'Gender'
  } ]
  @UI.identification: [ {
    position: 50 , 
    label: 'Gender'
  } ]
  Gender;
  
  @UI.lineItem: [ {
    position: 60 , 
    importance: #MEDIUM, 
    label: 'Languagecode'
  } ]
  @UI.identification: [ {
    position: 60 , 
    label: 'Languagecode'
  } ]
  Languagecode;
  
  @UI.lineItem: [ {
    position: 70 , 
    importance: #MEDIUM, 
    label: 'Salutation'
  } ]
  @UI.identification: [ {
    position: 70 , 
    label: 'Salutation'
  } ]
  Salutation;
  
  @UI.lineItem: [ {
    position: 80 , 
    importance: #MEDIUM, 
    label: 'Street1'
  } ]
  @UI.identification: [ {
    position: 80 , 
    label: 'Street1'
  } ]
  Street1;
  
  @UI.lineItem: [ {
    position: 90 , 
    importance: #MEDIUM, 
    label: 'Street2'
  } ]
  @UI.identification: [ {
    position: 90 , 
    label: 'Street2'
  } ]
  Street2;
  
  @UI.lineItem: [ {
    position: 100 , 
    importance: #MEDIUM, 
    label: 'Postalcode'
  } ]
  @UI.identification: [ {
    position: 100 , 
    label: 'Postalcode'
  } ]
  Postalcode;
  
  @UI.lineItem: [ {
    position: 110 , 
    importance: #MEDIUM, 
    label: 'City'
  } ]
  @UI.identification: [ {
    position: 110 , 
    label: 'City'
  } ]
  City;
  
  @UI.lineItem: [ {
    position: 120 , 
    importance: #MEDIUM, 
    label: 'County'
  } ]
  @UI.identification: [ {
    position: 120 , 
    label: 'County'
  } ]
  County;
  
  @UI.lineItem: [ {
    position: 130 , 
    importance: #MEDIUM, 
    label: 'Country'
  } ]
  @UI.identification: [ {
    position: 130 , 
    label: 'Country'
  } ]
  Country;
  
  @UI.lineItem: [ {
    position: 140 , 
    importance: #MEDIUM, 
    label: 'Phone'
  } ]
  @UI.identification: [ {
    position: 140 , 
    label: 'Phone'
  } ]
  Phone;
  
  @UI.lineItem: [ {
    position: 150 , 
    importance: #MEDIUM, 
    label: 'Mobilephone'
  } ]
  @UI.identification: [ {
    position: 150 , 
    label: 'Mobilephone'
  } ]
  Mobilephone;
  
  @UI.lineItem: [ {
    position: 160 , 
    importance: #MEDIUM, 
    label: 'Fax'
  } ]
  @UI.identification: [ {
    position: 160 , 
    label: 'Fax'
  } ]
  Fax;
  
  @UI.lineItem: [ {
    position: 170 , 
    importance: #MEDIUM, 
    label: 'Email'
  } ]
  @UI.identification: [ {
    position: 170 , 
    label: 'Email'
  } ]
  Email;
  
  @UI.hidden: true
  LocalLastChangedAt;
}


Projection View Ergebnis Verarbeitung GP
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Proj. View Proc. BP'
@Metadata.allowExtensions: true
@Metadata.ignorePropagatedAnnotations: true

define root view entity ZC_YMD_BP_CSVUPLOAD_CREAT_BP 
provider contract transactional_query
as projection on ZR_YMD_BP_CSVUPLOAD_CREAT_BP

association [1..*] to ZC_YMD_BP_CSVUP_CREAT_BP_LOG  as _CreationBPLogs
  on _CreationBPLogs.Logid = $projection.LogID

{
    key Fileid,
    key Fileidrow,
    @ObjectModel.text.element: [ 'StatusCriticalityText' ]
    Status,
    StatusCriticalityText,
    StatusCriticality,
    BpID,
    LogID,
    
    _CreationBPLogs
}
Metadata Extensions
@Metadata.layer: #CORE
@UI: {
  headerInfo: {
    typeName: 'Result of Creation', 
    typeNamePlural: 'Result of Creation'
  }
}
annotate entity ZC_YMD_BP_CSVUPLOAD_CREAT_BP
    with 
{    

    // --- HEADER
  @UI.facet: [ 
  
  {
   id: 'FileDataHeader',
   purpose: #HEADER,
   type: #DATAPOINT_REFERENCE,
   position: 10,
   targetQualifier: 'FileData' 
  },
  {
   id: 'FileRowDataHeader',
   purpose: #HEADER,
   type: #DATAPOINT_REFERENCE,
   position: 20,
   targetQualifier: 'FileRowData' 
  },
  {
   id: 'StatusDataHeader',
   purpose: #HEADER,
   type: #DATAPOINT_REFERENCE,
   position: 30,
   targetQualifier: 'StatusData' 
  },
  {
      id: 'CreationBP',
      purpose: #STANDARD,
      type: #LINEITEM_REFERENCE,
      label: 'File Processing',
      position: 20,
      targetElement: '_CreationBPLogs'
   }
]
    
  @UI.lineItem: [ {
    position: 10 , 
    importance: #MEDIUM, 
    type: #STANDARD,
    label: 'File ID' }]
    @UI.dataPoint: { qualifier: 'FileData', title: 'File ID' }           
    Fileid;
    
    @UI.lineItem: [ {
    position: 20 , 
    importance: #MEDIUM, 
    label: 'File Row ID' } ]
    @UI.dataPoint: { qualifier: 'FileRowData', title: 'File Row ID' }   
    Fileidrow;
    
    @UI.lineItem: [ {
    position: 30 , 
    importance: #MEDIUM, 
    label: 'Status',
    criticality: 'StatusCriticality'
  } ]
    @UI.dataPoint: { qualifier: 'StatusData', title: 'Status', criticality: 'StatusCriticality' }   
    Status;
       
    @UI.lineItem: [ { position: 40, importance: #MEDIUM, semanticObject: 'Businesspartner', semanticObjectAction: 'Manage', type: #WITH_INTENT_BASED_NAVIGATION, value: 'BpID', label: 'Businesspartner' } ]
    @Consumption.semanticObject: 'Businesspartner'
    BpID;
    
    @UI.lineItem: [ {
    position: 50 , 
    importance: #MEDIUM, 
    label: 'Log ID' } ]
    LogID;
    
}


Projection View Log Verarbeitung GP
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Proj. View Log Proc. BP'
@Metadata.allowExtensions: true
//@Metadata.ignorePropagatedAnnotations: true
@UI: {
  headerInfo: {
    typeName: 'Log Entry', 
    typeNamePlural: 'Log Entries'
  }
}
define root view entity ZC_YMD_BP_CSVUP_CREAT_BP_LOG
provider contract transactional_query
as projection on ZR_YMD_BP_CSVUP_CREAT_BP_LOG

{

 @UI.facet: [ {
  id         : 'idMessage',
  label      : 'Message',
  position   : 10,
  type       : #IDENTIFICATION_REFERENCE,
  targetQualifier: 'Message' } ]
  
  @UI.lineItem: [ {
  position: 10 , 
  importance: #HIGH, 
  label: 'Log ID' } ]
  @UI.dataPoint: { qualifier: 'LogIDData', title: 'Log ID' }     
  key Logid,
  @UI.lineItem: [ {
  position: 20 , 
  importance: #MEDIUM, 
  label: 'Log Item ID' } ] 
  @UI.dataPoint: { qualifier: 'LogItemIDData', title: 'Log Item ID' }     
  key Logitemid,
  @UI.lineItem: [ {
  position: 30 , 
  importance: #MEDIUM, 
  label: 'Message' } ]
@UI:{ identification: [{ position: 80, qualifier: 'Message' }] }
  Message
 
}

Behavior Definitions & Implementations

Managed mit Draft

Managed mit Draft
managed implementation in class ZBP_YMD_BP_CSVUPLOAD unique;
strict ( 2 );
with draft;

define behavior for ZR_YMD_BP_CSVUPLOAD alias BP_CSVUPLOAD
persistent table ymd_bp_csvupload
with additional save
draft table zymd_bp_csvuplod
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master ( global )
late numbering
{

  field ( readonly )
  FileID,
  CreatedAt,
  CreatedBy,
  LastChangedAt,
  LocalLastChangedAt,
  LocalLastChangedBy;

  field ( features : instance ) Attachment;

  create;
  update ( features : instance );
  delete ( features : instance );

  determination set_init_status on save { create; }

  draft action Edit;
  draft action Activate optimized;
  draft action Discard;
  draft action Resume;
  draft determine action Prepare;

  mapping for ymd_bp_csvupload
    {
      FileID             = fileid;
      Status             = status;
      Attachment         = attachment;
      MimeType           = mimetype;
      FileName           = filename;
      CreatedBy          = created_by;
      CreatedAt          = created_at;
      LocalLastChangedBy = local_last_changed_by;
      LocalLastChangedAt = local_last_changed_at;
      LastChangedAt      = last_changed_at;
    }
}
CSV-Upload Impl.
CLASS lsc_zr_ymd_bp_csvupload DEFINITION INHERITING FROM cl_abap_behavior_saver.

  PROTECTED SECTION.



    METHODS adjust_numbers REDEFINITION.

    METHODS save_modified REDEFINITION.

ENDCLASS.

CLASS lsc_zr_ymd_bp_csvupload IMPLEMENTATION.

  METHOD adjust_numbers.

    SELECT SINGLE
           MAX( fileid )
      FROM ymd_bp_csvupload
      INTO @DATA(lv_max_id).

    lv_max_id += 1.

    LOOP AT mapped-bp_csvupload ASSIGNING FIELD-SYMBOL(<ls_map>).
      <ls_map>-FileID = lv_max_id.
    ENDLOOP.

  ENDMETHOD.

  METHOD save_modified.
    IF create-bp_csvupload IS NOT INITIAL.

      IF create-bp_csvupload[ 1 ]-Attachment IS INITIAL.
        reported-bp_csvupload = VALUE #( ( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error
                                                                       text     = 'File Upload is mandatory' ) ) ).
        RETURN.

      ENDIF.




      DATA(lv_csv_as_string) =  cl_abap_codepage=>convert_from( source = create-bp_csvupload[ 1 ]-Attachment ).

      DATA lt_csv_as_string_tab TYPE TABLE OF string.
      SPLIT lv_csv_as_string AT cl_abap_char_utilities=>newline INTO TABLE lt_csv_as_string_tab.
      DELETE lt_csv_as_string_tab INDEX 1.

      DATA ls_db_csv_row TYPE ymd_bp_csv_rows.
      DATA lt_db_csv_row TYPE TABLE OF ymd_bp_csv_rows WITH DEFAULT KEY.

      DATA lv_filerow_counter TYPE i.

      LOOP AT lt_csv_as_string_tab INTO DATA(lv_row).
        REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_row WITH ''.
        REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_row WITH ''.
        REPLACE ALL OCCURRENCES OF REGEX '[\r\n]' IN lv_row WITH ''.
        SPLIT lv_row AT ';'
          INTO DATA(lv_debitorennumber)
               DATA(lv_customerid)
               DATA(lv_lastname)
               DATA(lv_firstname)
               DATA(lv_title)
               DATA(lv_gender)
               DATA(lv_languagecode)
               DATA(lv_salutation)
               DATA(lv_street1)
               DATA(lv_street2)
               DATA(lv_zipcode)
               DATA(lv_city)
               DATA(lv_county)
               DATA(lv_country)
               DATA(lv_phone)
               DATA(lv_mobilphone)
               DATA(lv_fax)
               DATA(lv_email).

        ls_db_csv_row-fileid = create-bp_csvupload[ 1 ]-FileID.
        lv_filerow_counter += 1.
        ls_db_csv_row-fileidrow = lv_filerow_counter.
        ls_db_csv_row-bp = lv_debitorennumber.
        ls_db_csv_row-lastname = lv_lastname.
        ls_db_csv_row-firstname = lv_firstname.
        ls_db_csv_row-title = lv_title.
        ls_db_csv_row-gender = lv_gender.
        ls_db_csv_row-languagecode = lv_languagecode.
        ls_db_csv_row-salutation = lv_salutation.
        ls_db_csv_row-street1 = lv_street1.
        ls_db_csv_row-street2 = lv_street2.
        ls_db_csv_row-postalcode = lv_zipcode.
        ls_db_csv_row-city = lv_city.
        ls_db_csv_row-county = lv_county.
        ls_db_csv_row-country = lv_country.
        ls_db_csv_row-phone = lv_phone.
        ls_db_csv_row-mobilephone = lv_mobilphone.
        ls_db_csv_row-fax = lv_fax.
        ls_db_csv_row-email = lv_email.
        APPEND ls_db_csv_row TO lt_db_csv_row.

      ENDLOOP.

      INSERT ymd_bp_csv_rows FROM TABLE lt_db_csv_row.

    ENDIF.

    IF delete-bp_csvupload IS NOT INITIAL.
     DATA(lv_fileid) = delete-bp_csvupload[ 1 ]-FileID.
     DELETE FROM ymd_bp_csv_rows WHERE fileid = lv_fileid.
    ENDIF.

  ENDMETHOD.

ENDCLASS.

CLASS lhc_bp_csvupload DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.
    METHODS:
      get_global_authorizations FOR GLOBAL AUTHORIZATION
        IMPORTING
        REQUEST requested_authorizations FOR bp_csvupload
        RESULT result.
    METHODS set_init_status FOR DETERMINE ON SAVE
      IMPORTING keys FOR bp_csvupload~set_init_status.
    METHODS get_instance_features FOR INSTANCE FEATURES
      IMPORTING keys REQUEST requested_features FOR bp_csvupload RESULT result.
ENDCLASS.

CLASS lhc_bp_csvupload IMPLEMENTATION.
  METHOD get_global_authorizations.
  ENDMETHOD.

  METHOD set_init_status.
    MODIFY ENTITIES OF zr_ymd_bp_csvupload IN LOCAL MODE
    ENTITY bp_csvupload
     UPDATE FIELDS ( Status )
    WITH VALUE #( (  %tky = keys[ 1 ]-%tky
                     Status = '01' ) ).
  ENDMETHOD.

  METHOD get_instance_features.
    READ ENTITIES OF zr_ymd_bp_csvupload IN LOCAL MODE
     ENTITY bp_csvupload
      FIELDS ( FileID Status )
       WITH CORRESPONDING #( keys )
          RESULT DATA(lt_files).

    result = VALUE #(
     FOR mfile IN lt_files
      ( %tky = mfile-%tky
        %features-%delete = COND #( WHEN mfile-status = '02' THEN if_abap_behv=>fc-o-disabled
                                    WHEN mfile-status = '03' THEN if_abap_behv=>fc-o-disabled
                                    WHEN mfile-status = '04' THEN if_abap_behv=>fc-o-disabled
                                    WHEN mfile-status = '00' THEN if_abap_behv=>fc-o-disabled  )
        %features-%update = COND #( WHEN mfile-status = '02' THEN if_abap_behv=>fc-o-disabled )
        %features-%field-Attachment = COND #( WHEN  (    mfile-status = '00'
                                                      OR mfile-status = '02'
                                                      OR mfile-status = '03'
                                                      OR mfile-status = '04'  )
                                               AND mfile-%is_draft = if_abap_behv=>mk-on
                                              THEN if_abap_behv=>fc-f-read_only )
      )
     ).

  ENDMETHOD.

ENDCLASS.    

Managed ohne Draft

CSV Rows Def.
managed implementation in class ZBP_YMD_BP_CSV_ROWS unique;
strict ( 2 );
//with draft;

define behavior for ZR_YMD_BP_CSV_ROWS alias CSVRows
persistent table ymd_bp_csv_rows
//draft table zymd_bp_csv_rowd
etag master LocalLastChangedAt
//lock master total etag LastChangedAt
lock master
authorization master ( global )
with additional save with full data

{

  field ( mandatory )
  city,
  country;


  field ( readonly )
  FileID,
  FileIDRow,
  CreatedAt,
  CreatedBy,
  LastChangedAt,
  LocalLastChangedAt,
  LocalLastChangedBy;

  factory action ( features : instance ) Process [1];

  //create;
  update ( features : instance );
  delete ( features : instance );

  side effects {
   action Process affects entity _CSVUpload, entity _CSVUpload._ResultCreationBP;
  } 

//  draft action Edit;
//  draft action Activate optimized;
//  draft action Discard;
//  draft action Resume;
//  draft determine action Prepare;

  mapping for ymd_bp_csv_rows
    {
      FileID             = fileid;
      FileIDRow          = fileidrow;
      Bp                 = bp;
      Firstname          = firstname;
      Lastname           = lastname;
      Title              = title;
      Gender             = gender;
      Languagecode       = languagecode;
      Salutation         = salutation;
      Street1            = street1;
      Street2            = street2;
      Postalcode         = postalcode;
      City               = city;
      County             = county;
      Country            = country;
      Phone              = phone;
      Mobilephone        = mobilephone;
      Fax                = fax;
      Email              = email;
      CreatedBy          = created_by;
      CreatedAt          = created_at;
      LocalLastChangedBy = local_last_changed_by;
      LocalLastChangedAt = local_last_changed_at;
      LastChangedAt      = last_changed_at;
    }
}
CSV Rows Impl.
CLASS lsc_zr_ymd_bp_csv_rows DEFINITION INHERITING FROM cl_abap_behavior_saver.

  PROTECTED SECTION.

    METHODS save_modified REDEFINITION.

ENDCLASS.

CLASS lsc_zr_ymd_bp_csv_rows IMPLEMENTATION.

  METHOD save_modified.
    "reported-csvrows =
  ENDMETHOD.

ENDCLASS.

CLASS lhc_csvrows DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.

    TYPES tt_read_result_csv_rows         TYPE TABLE FOR READ RESULT zr_ymd_bp_csv_rows\\csvrows.
    TYPES ts_read_result_csv_row          TYPE STRUCTURE FOR READ RESULT zr_ymd_bp_csv_rows\\csvrows.
    TYPES tt_read_result_creation_bp      TYPE TABLE FOR READ RESULT zc_ymd_bp_csvupload_creat_bp.
    TYPES tt_action_import_process        TYPE TABLE FOR ACTION IMPORT zr_ymd_bp_csv_rows\\csvrows~process.

    DATA mt_creation_bp_for_insert TYPE STANDARD TABLE OF ymd_bp_csvupcrbp WITH DEFAULT KEY.
    DATA mt_creation_bp_for_modify TYPE STANDARD TABLE OF ymd_bp_csvupcrbp WITH DEFAULT KEY.
    DATA mt_cr_bp_log_for_insert TYPE STANDARD TABLE OF ymd_bp_upcrbplog WITH DEFAULT KEY.
    DATA mt_cr_bp_log_for_modify TYPE STANDARD TABLE OF ymd_bp_upcrbplog WITH DEFAULT KEY.

    DATA mt_result_creation_bp_data TYPE tt_read_result_creation_bp.
    DATA mv_next_log_id TYPE int4.

    DATA mv_first_processing TYPE abap_boolean.

    METHODS:
      get_global_authorizations FOR GLOBAL AUTHORIZATION
        IMPORTING
        REQUEST requested_authorizations FOR CSVRows
        RESULT result,
      get_instance_features FOR INSTANCE FEATURES
        IMPORTING keys REQUEST requested_features FOR CSVRows RESULT result.

    METHODS Process FOR MODIFY
      IMPORTING keys FOR ACTION CSVRows~Process.

    METHODS _get_next_logid
      RETURNING VALUE(r) TYPE int4.
    METHODS _get_row_data
      IMPORTING it_keys  TYPE tt_action_import_process
      RETURNING VALUE(r) TYPE tt_read_result_csv_rows.
    METHODS _get_creation_bp_data
      IMPORTING it_row_data TYPE tt_read_result_csv_rows.
    METHODS _are_prechecks_failed
      IMPORTING is_row             TYPE ts_read_result_csv_row
      RETURNING VALUE(rv_is_error) TYPE abap_boolean.
    METHODS _create_bp
      IMPORTING is_row      TYPE ts_read_result_csv_row
      EXPORTING ev_is_error TYPE abap_boolean.
    METHODS _update_overall_status
      IMPORTING it_row_data TYPE tt_read_result_csv_rows.
ENDCLASS.

CLASS lhc_csvrows IMPLEMENTATION.

  METHOD get_global_authorizations.
  ENDMETHOD.

  METHOD get_instance_features.

    READ ENTITIES OF zc_ymd_bp_csvupload_creat_bp
      ENTITY zc_ymd_bp_csvupload_creat_bp
       FIELDS ( FileID Status )
        WITH CORRESPONDING #( keys )
           RESULT DATA(lt_created_bp).

    IF lt_created_bp IS NOT INITIAL.

      READ ENTITIES OF zr_ymd_bp_csv_rows IN LOCAL MODE
       ENTITY CSVRows
        FIELDS ( FileID )
         WITH CORRESPONDING #( keys )
            RESULT DATA(lt_rows).



      LOOP AT lt_rows ASSIGNING FIELD-SYMBOL(<ls_row>).
        IF line_exists( lt_created_bp[ Fileidrow = <ls_row>-FileIDRow ] ).
          APPEND VALUE #( %tky = <ls_row>-%tky
                          %features-%action-Process = COND #( WHEN lt_created_bp[ Fileidrow = <ls_row>-FileIDRow ]-status = '01'
                                                              THEN if_abap_behv=>fc-o-disabled )
*                    %features-%delete = COND #( WHEN lt_created_bp[ Fileidrow = <ls_row>-FileIDRow  ]-status = '01' THEN if_abap_behv=>fc-o-disabled
*                                                WHEN lt_created_bp[ Fileidrow = <ls_row>-FileIDRow  ]-status = '02' THEN if_abap_behv=>fc-o-disabled )
                          %features-%delete = if_abap_behv=>fc-o-disabled
                          %features-%update = COND #( WHEN lt_created_bp[ Fileidrow = <ls_row>-FileIDRow  ]-status = '01' THEN if_abap_behv=>fc-o-disabled )
                        ) TO result.
        ELSE.
          IF lines( lt_created_bp ) = 0.
            APPEND VALUE #( %tky = <ls_row>-%tky
                            %features-%action-Process = if_abap_behv=>fc-o-enabled
                            %features-%delete = if_abap_behv=>fc-o-disabled
                           ) TO result.
          ELSE.
            APPEND VALUE #( %tky = <ls_row>-%tky
                            %features-%delete = if_abap_behv=>fc-o-disabled
                           ) TO result.
          ENDIF.
        ENDIF.
      ENDLOOP.

    ENDIF.

  ENDMETHOD.

  METHOD Process.

    CLEAR: mv_next_log_id, mt_result_creation_bp_data,
           mt_cr_bp_log_for_modify, mt_cr_bp_log_for_insert,
           mt_creation_bp_for_insert, mt_creation_bp_for_modify.

     LOOP AT keys ASSIGNING FIELD-SYMBOL(<ls_key>).
      mapped-csvrows = VALUE #( ( %cid = <ls_key>-%cid
                                  FileID = <ls_key>-FileID
                                  FileIDRow = <ls_key>-FileIDRow ) ).
      reported-csvrows = VALUE #( (  %msg = new_message_with_text(
                                     severity = CONV #( 'I' )
                                     text     = 'CSV Row(s) processed.'
                                 ) ) ).
    ENDLOOP.


    DATA(lt_rows) = _get_row_data( it_keys = keys ).
    _get_creation_bp_data( it_row_data = lt_rows ).

    LOOP AT lt_rows ASSIGNING FIELD-SYMBOL(<ls_row>).

      CLEAR mv_first_processing.
      IF NOT line_exists( mt_result_creation_bp_data[ Fileid = <ls_row>-FileID
                                                      Fileidrow = <ls_row>-FileIDRow ] ).
        mv_first_processing = abap_true.
      ENDIF.

      IF _are_prechecks_failed( is_row = <ls_row> ).
        CONTINUE.
      ENDIF.

      _create_bp( EXPORTING is_row = <ls_row>
                  IMPORTING ev_is_error = DATA(lv_is_error_creation_bp)
                ).

    ENDLOOP.

    IF mt_creation_bp_for_insert IS NOT INITIAL.
     INSERT ymd_bp_csvupcrbp FROM TABLE mt_creation_bp_for_insert.
    ENDIF.
    IF mt_cr_bp_log_for_insert IS NOT INITIAL.
     INSERT ymd_bp_upcrbplog FROM TABLE mt_cr_bp_log_for_insert.
    ENDIF.

    IF mt_creation_bp_for_modify IS NOT INITIAL.
     MODIFY ymd_bp_csvupcrbp FROM TABLE mt_creation_bp_for_modify.
    ENDIF.
    IF mt_cr_bp_log_for_modify IS NOT INITIAL.
     MODIFY ymd_bp_upcrbplog FROM TABLE mt_cr_bp_log_for_modify.
    ENDIF.

    _update_overall_status( lt_rows ).

  ENDMETHOD.

  METHOD _create_bp.

    CLEAR ev_is_error.

    "for first processing
    DATA(lv_next_log_id) = _get_next_logid( ).
    DATA lv_next_logitem_id TYPE i.

    "already processed and processing again
    IF mv_first_processing = abap_false.
    "#Todo: Auslagerung in Methode und mv.
    DATA(lv_log_id_db) = VALUE #( mt_result_creation_bp_data[ fileid = is_row-FileID
                                                               Fileidrow = is_row-FileIDRow ]-LogID ).

    SELECT SINGLE MAX( logitemid ) FROM ymd_bp_upcrbplog
    WHERE logid = @lv_log_id_db
    INTO @DATA(lv_logitem_id_db).
    ENDIF.

    DATA(lo_bp) = NEW ycl_bp( ).
    lo_bp->set_bp_person_data(
          iv_title                      = is_row-title
          iv_firstname                  = is_row-firstname
          iv_lastname                   = is_row-lastname
          iv_gender                     = is_row-gender
          iv_correspondencelanguagecode = to_upper( is_row-languagecode(1) )
          iv_street                     = is_row-street1
          iv_postalcode                 = is_row-Postalcode
          iv_city                       = is_row-city
          iv_county                     = is_row-county
          iv_country                    = to_upper( is_row-country )
          iv_language                   = to_upper( is_row-languagecode(1) )
          iv_searchterm1                = |{ is_row-firstname } { is_row-lastname }|
          iv_bpgrouping                 = 'BPEE'
        ).

    TRY.
        lo_bp->create_bp_with_bapi( iv_test_run          = abap_false
                                    iv_wait_after_commit = abap_false
                                    iv_do_commit = abap_false ).
      CATCH cx_fiil_error INTO DATA(cx).
        ev_is_error = abap_true.

        IF mv_first_processing = abap_true.

          lv_next_logitem_id += 1.
          APPEND VALUE #( logid = lv_next_log_id
                          logitemid = lv_next_logitem_id
                          message = cx->get_text( )
                        ) TO mt_cr_bp_log_for_insert.

          APPEND VALUE #( fileid    = is_row-FileID
                          fileidrow = is_row-FileIDRow
                          bpid      = ''
                          logid     = lv_next_log_id
                          status    = '02' ) TO mt_creation_bp_for_insert.
        ENDIF.

        IF mv_first_processing = abap_false.
          APPEND VALUE #( logid = lv_log_id_db
                          logitemid = lv_logitem_id_db + 1
                          message = cx->get_text( )
                         ) TO mt_cr_bp_log_for_modify.

          APPEND VALUE #( fileid    = is_row-FileID
                          fileidrow = is_row-FileIDRow
                          bpid      = ''
                          logid     = lv_log_id_db
                          status    = '02' ) TO mt_creation_bp_for_modify.
        ENDIF.

        RETURN.
    ENDTRY.

    IF mv_first_processing = abap_true.
      APPEND VALUE #( fileid    = is_row-FileID
                      fileidrow = is_row-FileIDRow
                      bpid      = lo_bp->get_bp_no( )
                      logid     = lv_next_log_id
                      status    = COND #( WHEN lines( lo_bp->get_protocol( iv_only_errors = abap_true ) ) = 0 THEN '01'
                                          ELSE '02' )
                    ) TO mt_creation_bp_for_insert.

      LOOP AT lo_bp->get_protocol( ) ASSIGNING FIELD-SYMBOL(<ls_add_msg>).
        lv_next_logitem_id += 1.
        MESSAGE ID <ls_add_msg>-messageid TYPE <ls_add_msg>-messagetype NUMBER <ls_add_msg>-messagenumber
        WITH <ls_add_msg>-messagevariable1 <ls_add_msg>-messagevariable2 <ls_add_msg>-messagevariable3 <ls_add_msg>-messagevariable4
        INTO DATA(lv_msg).
        APPEND VALUE #( logid = lv_next_log_id
                        logitemid = lv_next_logitem_id
                        message = lv_msg
                      ) TO mt_cr_bp_log_for_insert.
      ENDLOOP.
       IF sy-subrc <> 0.
        lv_next_logitem_id += 1.
        APPEND VALUE #( logid = lv_next_log_id
                        logitemid = lv_next_logitem_id
                        message = 'No warning or error msgs.'
                      ) TO mt_cr_bp_log_for_insert.
       ENDIF.

      ENDIF.

      IF mv_first_processing = abap_false.
        APPEND VALUE #( fileid    = is_row-FileID
                        fileidrow = is_row-FileIDRow
                        bpid      = lo_bp->get_bp_no( )
                        logid     = lv_log_id_db
                        status    = COND #( WHEN lines( lo_bp->get_protocol( iv_only_errors = abap_true ) ) = 0 THEN '01'
                                            ELSE '02' )
                      ) TO mt_creation_bp_for_modify.

        LOOP AT lo_bp->get_protocol( ) ASSIGNING <ls_add_msg>.

          MESSAGE ID <ls_add_msg>-messageid TYPE <ls_add_msg>-messagetype NUMBER <ls_add_msg>-messagenumber
          WITH <ls_add_msg>-messagevariable1 <ls_add_msg>-messagevariable2 <ls_add_msg>-messagevariable3 <ls_add_msg>-messagevariable4
          INTO lv_msg.
          APPEND VALUE #( logid = lv_log_id_db
                          logitemid = lv_logitem_id_db + 1
                          message = lv_msg
                        ) TO mt_cr_bp_log_for_modify.
        ENDLOOP.
        IF sy-subrc <> 0.
          APPEND VALUE #( logid = lv_log_id_db
                          logitemid = lv_logitem_id_db + 1
                          message = 'No warning or error msgs.'
                        ) TO mt_cr_bp_log_for_modify.
        ENDIF.

      ENDIF.

    ENDMETHOD.

    METHOD _get_creation_bp_data.
      IF it_row_data IS INITIAL.
        RAISE EXCEPTION NEW cx_fiil_error( ).
      ENDIF.

     READ ENTITIES OF zc_ymd_bp_csvupload_creat_bp
       ENTITY zc_ymd_bp_csvupload_creat_bp
       FIELDS ( FileID Status )
       WITH VALUE #( ( Fileid = it_row_data[ 1 ]-FileID ) )
      RESULT mt_result_creation_bp_data.

*    SELECT FROM ymd_bp_csvupcrbp
*    FIELDS *
*    FOR ALL ENTRIES IN @it_row_data
*    WHERE fileid = @it_row_data-FileID
*    INTO TABLE r.
    ENDMETHOD.

    METHOD _get_next_logid.
      CLEAR r.

      IF mv_next_log_id IS INITIAL.
        "#Todo: Auslagerung in Methode und mv, da bereits 2x benutzt wird.
        SELECT SINGLE MAX( logid ) FROM ymd_bp_upcrbplog INTO @DATA(lv_db_max_log_id).
          mv_next_log_id = lv_db_max_log_id + 1.
          RETURN mv_next_log_id.
        ENDIF.

        RETURN mv_next_log_id + 1.
      ENDMETHOD.

      METHOD _get_row_data.
        CLEAR r.

        READ ENTITIES OF zr_ymd_bp_csv_rows IN LOCAL MODE
          ENTITY CSVRows
           ALL FIELDS
          WITH CORRESPONDING #( it_keys )
          RESULT r.
      ENDMETHOD.

      METHOD _are_prechecks_failed.

        CLEAR rv_is_error.

        DATA lt_errors TYPE TABLE OF string.

        "already processed and processing again
        IF mv_first_processing = abap_false.
        "#Todo: Auslagerung in Methode und mv, da mehrmals benutzt wird.
         DATA(lv_log_id_db) = VALUE #( mt_result_creation_bp_data[ fileid = is_row-FileID
                                                                  Fileidrow = is_row-FileIDRow ]-LogID ).
         SELECT SINGLE MAX( logitemid ) FROM ymd_bp_upcrbplog
         WHERE logid = @lv_log_id_db
         INTO @DATA(lv_logitem_id_db).
        ENDIF.

        IF      is_row-Bp IS INITIAL.
          APPEND 'CustomerID is missing' TO lt_errors.
        ELSEIF is_row-Email IS INITIAL.
          APPEND 'EMail is missing' TO lt_errors.
        ELSEIF is_row-email NS '@'.
          APPEND 'Not valid EMail address' TO lt_errors.
        ENDIF.

        IF lines( lt_errors ) > 0.

          rv_is_error = abap_true.

          DATA lv_next_logitem_id TYPE i.
          LOOP AT lt_errors ASSIGNING FIELD-SYMBOL(<lv_error>).

            IF mv_first_processing = abap_true.
              lv_next_logitem_id += 1.
              DATA(lv_next_log_id) = _get_next_logid( ).

              APPEND VALUE #( logid = lv_next_log_id
                              logitemid = lv_next_logitem_id
                              message = <lv_error> ) TO mt_cr_bp_log_for_insert.

              APPEND VALUE #( fileid    = is_row-FileID
                              fileidrow = is_row-FileIDRow
                              bpid      = ''
                              logid     = lv_next_log_id
                              status    = '02' ) TO mt_creation_bp_for_insert.
            ENDIF.

            IF mv_first_processing = abap_false.
              APPEND VALUE #( logid = lv_log_id_db
                              logitemid = lv_logitem_id_db + 1
                              message = <lv_error> ) TO mt_cr_bp_log_for_modify.

              APPEND VALUE #( fileid    = is_row-FileID
                              fileidrow = is_row-FileIDRow
                              bpid      = ''
                              logid     = lv_log_id_db
                              status    = '02' ) TO mt_creation_bp_for_modify.
            ENDIF.

          ENDLOOP.

        ENDIF.

      ENDMETHOD.

      METHOD _update_overall_status.
        READ ENTITIES OF zc_ymd_bp_csvupload_creat_bp
         ENTITY zc_ymd_bp_csvupload_creat_bp
         FIELDS ( FileID Status )
         WITH CORRESPONDING #( it_row_data )
        RESULT DATA(lt_result_creat_after_process).

        DATA(lv_fileid) = it_row_data[ 1 ]-FileID.

        IF line_exists( lt_result_creat_after_process[ status = '02' ] )
         AND line_exists( lt_result_creat_after_process[ status = '01' ] ).

          MODIFY ENTITIES OF zr_ymd_bp_csvupload
           ENTITY bp_csvupload
           UPDATE FIELDS ( Status )
           WITH VALUE #( (  FileID = it_row_data[ 1 ]-FileID
                            Status = '03' ) ).
          "Sometimes it isnt save the right status via EML
          "Dont know why. #ToDO
          UPDATE ymd_bp_csvupload SET status = '03' WHERE fileid = lv_fileid.

          RETURN.

        ELSEIF    line_exists( lt_result_creat_after_process[ status = '01' ] )
            AND   line_exists( lt_result_creat_after_process[ status = '01' ] ).
          MODIFY ENTITIES OF zr_ymd_bp_csvupload
           ENTITY bp_csvupload
           UPDATE FIELDS ( Status )
           WITH VALUE #( (  FileID = lv_fileid
                            Status = '02' ) ).
          RETURN.

        ELSEIF   line_exists( lt_result_creat_after_process[ status = '02' ] )
         AND line_exists( lt_result_creat_after_process[ status = '02' ] ).
          MODIFY ENTITIES OF zr_ymd_bp_csvupload
           ENTITY bp_csvupload
           UPDATE FIELDS ( Status )
           WITH VALUE #( (  FileID = lv_fileid
                            Status = '04' ) ).
          RETURN.
        ENDIF.

      ENDMETHOD.

ENDCLASS.

Unmanaged

Ergebnis Verarbeitung GP Def.
unmanaged implementation in class zbp_r_ymd_bp_csvupload_creat_b unique;
strict ( 2 );

define behavior for ZR_YMD_BP_CSVUPLOAD_CREAT_BP alias CreationBP
lock master
authorization master ( instance )
//etag master <field_name>
{
  field ( readonly )
  Fileid,
  Fileidrow;

  create;
  update;
  delete;
}
Ergebnis Verarbeitung GP Impl.
CLASS lhc_ZR_YMD_BP_CSVUPLOAD_CREAT_ DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.

    METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
      IMPORTING keys REQUEST requested_authorizations FOR creationbp RESULT result.
    METHODS create FOR MODIFY
      IMPORTING entities FOR CREATE creationbp.

    METHODS update FOR MODIFY
      IMPORTING entities FOR UPDATE creationbp.

    METHODS delete FOR MODIFY
      IMPORTING keys FOR DELETE creationbp.

    METHODS read FOR READ
      IMPORTING keys FOR READ creationbp RESULT result.

    METHODS lock FOR LOCK
      IMPORTING keys FOR LOCK creationbp.

ENDCLASS.

CLASS lhc_ZR_YMD_BP_CSVUPLOAD_CREAT_ IMPLEMENTATION.

  METHOD get_instance_authorizations.
  ENDMETHOD.

  METHOD create.
  ENDMETHOD.

  METHOD update.
  ENDMETHOD.

  METHOD delete.
  ENDMETHOD.

  METHOD read.

   SELECT FROM ymd_bp_csvupcrbp
   FIELDS *
   FOR ALL ENTRIES IN @keys
   WHERE fileid = @keys-Fileid
   INTO TABLE @DATA(lt).

   result = VALUE #( FOR ls IN lt INDEX INTO idx
                        ( Fileid = ls-fileid
                          Fileidrow = ls-fileidrow
                          BpID = ls-bpid
                          Status = ls-status
                          LogID = ls-logid )
                    ).

  ENDMETHOD.

  METHOD lock.
  ENDMETHOD.

ENDCLASS.

Projection

Beh. Projection CSV-Upload
projection;
strict ( 2 );
use draft;

define behavior for ZC_YMD_BP_CSVUPLOAD alias BP_CSVUPLOAD
use etag

{
  use create;
  use update;
  use delete;

  use action Edit;
  use action Activate;
  use action Discard;
  use action Resume;
  use action Prepare;
}
Beh. Projection CSV Rows
projection;
strict ( 2 );
//use draft;
use side effects;

define behavior for ZC_YMD_BP_CSV_ROWS alias CSVRows
use etag

{

  use action Process;

  use update;

//  use action Edit;
//  use action Activate;
//  use action Discard;
//  use action Resume;
//  use action Prepare;
}
Beh. Projection Ergebnis Verarbeitung GP
projection;
strict ( 2 );

define behavior for ZC_YMD_BP_CSVUPLOAD_CREAT_BP //alias <alias_name>
{
  //use create;
  //use update;
  //use delete;

}

Business Services

Service Definition

Codeblock
@EndUserText.label: 'Service definition for ZC_YMD_BP_CSVUPLOAD'
define service ZUI_YMD_BP_CSVUPLOAD_O4 {
  expose ZC_YMD_BP_CSVUPLOAD          as CSVUpload;
  expose ZC_YMD_BP_CSVUPLOAD_CREAT_BP as ResultCreationBP;
  expose ZC_YMD_BP_CSVUP_CREAT_BP_LOG as ResultCreationBPLog;
  expose ZC_YMD_BP_CSV_ROWS           as CSVRows;
}

Service Binding

Erstellung

  • Service Defintion → Rechtsklick → New Service Bindung → Binding Type → OData V2 - UI

Publish Preview

  • Doppelklick CSVUpload

Dieses Wiki wird privat in Freizeit nach bestem Wissen und Gewissen gepflegt und dient primär als eigene Wissenssammlung für die tägliche Arbeit im SAP-ERP-Umfeld.
Alle dargestellten Softwareprodukte, auch in Form von Screenshots, sind Eigentum der SAP SE. Ihre Marken, vgl. Link, sind u.a.: SAP®, ABAP®, SAP Fiori®, SAP HANA®, SAP S/4HANA®, SAP S/4HANA® Cloud