Tip handling or restricting the deletion of lines from an array

Let's imagine that you are in a CRUD management, with header and lines to manage. In some cases, you don't want a user to be able to delete a line at a given position in the lines array. How can you do this?

The first bad answer would be to search a way to disable the "delete line" link in the user interface. This is a bad answer despite the fact that this is how it happens in V6 version.

Why is this bad? Because the code we have to implement must be robust and able to work in service mode and thus must not consider that the user interface requests are authorized for the only reason that they could be sent.

In fact, controlling the deletion of lines can be done by using the ADELLINE_BEFORE event. In this event, ALINE contains the position where the deletion is requested. If an error displays, no deletion will occur.

The way to prevent from deleting the line is the following:

# Code executed on $METHODS label, when ACTION is "DELLINE_BEFORE" and CURPRO is the right collection
  [L]ASTATUS=Fmet This.ASETERROR("","You cannot delete lines in the collection"-CURPRO,[V]CST_AERROR)
  Return

Some of the reasons that prevent a user from deleting lines in a document are the following:
  • It can be linked to a property of a header of the document (for example, when a FINAL property is set to 2 which means "true").
  • It can be linked to a property of a line of the document (for example, when a QTYDELIVERED is not null).
  • It can be linked to a property of the line collection (at least one line must remain).

Let's see how we can manage these examples:

In every case, the control is based on the 'DELLINE_BEFORE' event. This event is called in the different scripts associated with the classes.

For example, if you have a 'DOCUMENT' class, including a collection called 'LINES' of 'DOCLINE' class instances. The scripts associated with the classes are 'DOCUMENT_CSTD' and 'DOCLINE_CSTD'. Before authorizing a Delete operation, we have to perform the control in the two scripts:

At the line level, perform the line controls:

# Code found in the DOCLINE_CSTD script associated with DOCLINE class
$METHODS
Case CURPRO
     When "LINES" : Gosub LINES
  ...
Endcase
Return
$LINES
Case ACTION
  When "DELLINE_BEFORE" : Gosub DELLINE_BEFORE_LINES
     ...
Endcase
Return
$DELLINE_BEFORE_LINES
 # Is the QTYDELIVERED not null? If yes, deleting a line is forbidden 
 # "this" is here the current line
 If this.QTYDELIVERED>0
   [L]ASTATUS=Fmet This.ASETERROR("","You cannot delete a line at least partially delivered",[V]CST_AERROR)
   Return
 Endif

In the DOCUMENT_CSTD, perform the global controls:
# Code found in the DOCUMENT_CSTD script associated with DOCUMENT class
$METHODS
Case CURPRO
     When "LINES" : Gosub LINES
  ...
Endcase
Return
$LINES
  Case ACTION
     When "DELLINE_BEFORE" : Gosub DELLINE_BEFORE_LINES
     ...
  Endcase
Return
$DELLINE_BEFORE_LINES
Local Integer I,J
 # Is the FINAL status set to 2? If yes, deleting a line is forbidden 
 If this.FINAL=2
   [L]ASTATUS=Fmet This.ASETERROR("","You cannot delete lines in a document in final status",[V]CST_AERROR)
   Return
 Endif
 # Are there at least two remaining lines? (otherwise, we are trying to delete the last one)
 J=0
 For I=1 To maxtab(This.LINES)
   If find(This.LINES(I).ASTALINE,[V]CST_ADEL,[V]CST_ANEWDEL)=0
     J+=1
     Break (J>=2)
   Endif
 Next I
 If J<2
   [L]ASTATUS=Fmet This.ASETERROR("","You cannot delete the last line",[V]CST_AERROR)
   Return
 Endif