2023/VI mit virtuellen Barcodes

Automatisierung einfach gemacht

Egg, 6. Juni 2023: Anlässlich eines Kundengespräches wurde die Frage erörtert, wie die zunehmend digital eingehenden Bestellungen automatisiert mit einem (virtuellen) Barcode bestückt werden können. Damit erübrigt sich z.B. das Ausdrucken der Bestellungen und das manuelle Anbringen eines Barcode-Klebers. Vielmehr wird ein virtueller Barcode auf der ersten Seite oben rechts angebracht.

Die Vorgeschichte: Drucken, Kleben, Scannen…

Vor mehr als einem Jahrzehnt war es nicht unüblich, dass Bestellungen per Post eintrafen. Die eingehenden Belege wurden mit einem Barcode bestückt und anschliessend gescannt. Der erfasste Code auf den Belegen wurde in der ERP-Software mittels Lesepistole an diese übermittelt. Ab diesem Zeitpunkt konnte die Beschlagwortung automatisch erfolgen.

Über die Jahre verlagerten sich die Eingänge vom Papier hin zur digitalen Welt. Der grösste Teil des Bestelleinganges erfolgt aktuell per Mail bzw. mit entsprechend angehängten PDF-Dateien. Dies führte dazu, dass immer mehr PDF-Dateien ausgedruckt wurden, nur um diese mit einem Barcode-Kleber bestücken zu können und diese dem Scanner zuzuführen.

Automatisierung mit virtuellen Barcodes

Diesen manuellen Vorgang galt es möglichst zu optimieren. In einem ca. einstündigen Gespräch wurden zusammen mit dem Kunden die Optionen besprochen. Dabei kristallisierten sich zwei Lösungswege heraus: Erstens, bei jedem eingehenden Dokument wird eine Haftnotiz mit einem Barcode angebracht oder zweitens, der gewünschte Barcode wird oberhalb der ersten Seite “reingepixelt”.

Die erste Variante hätte den Vorteil gehabt, dass die Belege nicht “angefasst” hätten werden müssen. Jedoch, um Haftnotizen mit Barcodes erstellen zu können, hätte auf sämtlichen Clients der entsprechende Barcode-Zeichensatz (Code39) zur Verfügung gestellt werden müssen. Der Webserver hätte zusammen mit der Webseite einfach auch den entsprechenden Zeichensatz ausgeliefert. Jedoch, die Haftnotiz muss ja irgendwo auf dem Beleg platziert werden und könnte unter Umständen einen Bereich “überdecken”, der zentrale Informationen enthält.

Bei der zweiten Variante wird der Barcode oberhalb der ersten Seite angebracht. Dadurch erhält die erste Seite einer Akte ca. 200 Pixel mehr in der Höhe. Damit aber ist sichergestellt, dass der Barcode-Kleber zu keiner Zeit einen anderen Inhalt auf den Belegen überdeckt. Zusammen mit dem Kunden wurde die zweite Variante gewählt.

Implementierung mit Skript

Nachfolgend wird die für den Kunden realisierte Lösung präsentiert:

#!/usr/bin/perl
use lib qw(/home/cvs/archivista/jobs);
use AVJobs;
use GD::Barcode::Code39;
my $start = 5000000;
my $field = "Titel";
my ($host,$db,$user,$pw,$doc) = @ARGV;
my $dbh = MySQLOpen($host,$db,$user,$pw);
if (HostIsSlave($dbh)==0) {
  my $sql = "use $db";
  $dbh->do($sql);
  $sql = "select Laufnummer,Seiten,Archiviert,ArchivArt from archiv ".
    "where Laufnummer=$doc && ($field is null or $field='' or $field=0)";
  my ($lnr,$seiten,$arch,$art) = $dbh->selectrow_array($sql);
  my $ext = "png";
  $ext = "jpg" if $art==3;
  $ext = "tif" if $art==1;
  if ($lnr==$doc && $seiten>0 && $arch==0) {
    my $bc = getUnique($dbh,$start);
    if ($bc>=$start) {
      my $seite = ($doc*1000)+1;
      $sql = "select BildInput from archivbilder where Seite=$seite";
      my ($pimg) = $dbh->selectrow_array($sql);
      my $fin = "/tmp/$db-$lnr-1.$ext";
      my $fbc1 = "/tmp/$db-$lnr-$bc-1.png";
      my $fbc2 = "/tmp/$db-$lnr-$bc-2.png";
      my $fbc3 = "/tmp/$db-$lnr-$bc-3.png";
      my $ftmp = "/tmp/$db-$lnr-2.$ext";
      my $fout = "/tmp/$db-$lnr-3.$ext";
      deleteFiles($fin,$fbc1,$fbc2,$fbc3,$ftmp,$fout);
      writeFile($fin,\$pimg);
      my $bco=GD::Barcode::Code39->new('*'.$bc.'*');
      my $img=$bco->plot();
      writeFile($fbc1,\$img->png());
      my $res=system("econvert -i $fbc1 --scale 2 -o $fbc2");
      $res=system("convert $fbc2 -bordercolor White -border 50 $fbc3");
      $res=system("convert -append $fbc3 $fin $ftmp");
      $res=`edentify $fin`;
      $res =~ /([0-9]+)(x)([0-9]+)(dpi)/;
      if ($1>0 && $2 eq "x" && $3>0 && $4 eq "dpi") {
        $res=system("econvert -i $ftmp --resolution $1x$3 -o $fout");
      } else {
        $res=system("mv $ftmp $fout");
      }
      my $cont="";
      readFile2($fout,\$cont);
      if ($cont ne "") {
        $sql = "update archivbilder set BildInput=".$dbh->quote($cont).
          ",Bild='' where Seite=$seite";
        $dbh->do($sql);
        deleteFiles($fin,$fbc1,$fbc2,$fbc3,$ftmp,$fout);
        $sql = "update archiv set $field=".$dbh->quote($bc)." where ".
          "Laufnummer=$doc";
        $dbh->do($sql);
        logit("stamp $bc sucessfully to $db and doc $doc added!");
      }
    }
  }
}

sub deleteFiles {
  my @files = @_;
  foreach my $file (@files) {
    unlink $file if -e $file;
  }
}

sub getUnique {
  my ($dbh,$start) = @_;
  my $bc=0;
  my $plus="Name='BarcodeStamp' and Art='parameter' and Tabelle='parameter'";
  my $sql0 = "select Inhalt from parameter where $plus";
  for (my $c=1;$c<=10;$c++) {
    ($bc) = $dbh->selectrow_array($sql0);
    if ($bc>0) {
      $bc++;
      my $bc2 = int($bc-(2*$bc));
      my $sql = "update parameter set Inhalt=".$dbh->quote($bc2)." where ".
        "$plus and Inhalt>0";
      $dbh->do($sql);
      my ($bc3) = $dbh->selectrow_array($sql0);
      if ($bc3==$bc2) {
        my $sql = "update parameter set Inhalt=".$dbh->quote($bc)." where ".
          "$plus and Inhalt<0";
        $dbh->do($sql);
	last;
      }
    } elsif ($bc==0) {
      my $sql = "insert parameter set Inhalt=".$dbh->quote($start).",".
        "Name='BarcodeStamp',Art='parameter',Tabelle='parameter'";
      $dbh->do($sql);
      my ($bc) = $dbh->selectrow_array($sql0);
      last $bc==$start;
    }
    sleep $c;
  }
  return $bc;
}

Dieses Skript ist im folgenden Ordner mit dem Namen ‘bcadd’ zu platzieren:

/home/data/archivista/cust/autofields

Damit das Skript nach jeder erfassten Seite aufgerufen wird, wird in WebAdmin bei ‘Scannen’ eine entsprechende Definition benötigt. Konkret zu unserem Beispiel ist eine Scan-Definition mit dem Namen ‘bcadd’ zu erstellen. Weiter wird im Verarbeitungsordner ein entsprechender Ordner benötigt:

cd /home/data/archivista/ftp/office/dbname
mkdir bcadd
chown -R ftp.users bcadd

Damit ist sichergestellt, dass beim Erfassen der Belege über den Ordner ‘bcadd’ immer passend dazu die Scan-Definition ‘bcadd’ verwendet wird. Damit beim Verarbeiten das entsprechende Skript jeweils gestartet wird, ist bei der Scan-Definition bei Vorgabefelder das Skript ‘bcadd.pl’ einzutragen. Damit ist der Prozess aktiviert.

Fazit: Wenig Aufwand für hohe Ersparnis

Bei ca. 100’000 Seiten (50’000 Bestellungen mit durchschnittlich 2 Seiten), die beim Kunden jährlich per Mail eintreffen, kann zunächst einmal der Druck dieser Seiten gespart werden. Unter druckkosten.de werden pro Seite irgendwo zwischen 6.3 und 13.8 Cents (für die 50 günstigsten Modelle) angegeben. Im Schnitt ergibt dies ca. 10 Cents (oder Rappen) pro Seite. Die Druckkosten pro Jahr belaufen sich somit auf ca. 10’000 Euro bzw. Franken.

Dazu kommen die Kosten für die Barcode-Kleber. Ein Blick in diverse Webshops zeigte, dass hier mit minimalen Kosten von ca. 3 Cents/Rappen pro Etikette zu rechnen ist. Dies ergibt für die Etiketten weitere Kosten von 1500.– Franken/Euro.

Der Zeitaufwand, um 100’000 Seiten zu drucken, lässt sich nur sehr grob beziffern. Da die Dokumente jedoch zum grössten Teil aus wenigen Seiten bestehen, dürfte mit ca. 6 Sekunden pro Seite zu rechnen sein. Dies ergibt 600’000 Sekunden bzw. 166 Arbeitsstunden. Für das Anbringen der Kleber (Suchen einer freien Stelle auf dem Beleg inklusive) dürfte pro Vorgang ebenfalls mit ca. 6 Sekunden zu rechnen sein. Dies ergibt zusätzliche 83 Arbeitsstunden. Dazu kommt die benötigte Zeit für das Scannen. Eine gute Scankraft dürfte mit einem anständigen Dokumentenscanner pro Stunde ca. 2000 Seiten verarbeiten können, womit für das Scannen weitere 50 Stunden anfallen.

Demgegenüber ist der benötigte Aufwand für das Verschieben der PDF-Dateien von den Mails in den Freigabeordner zu kalkulieren. Kleine Nebenbemerkung: Mit dem Mail-Modul liesse sich dieser Prozess komplette automatisieren, doch steht dieser Schritt beim Kunden noch aus. Pro Vorgang dürfte wohl in etwa jene Zeit benötigt werden, die für das Anbringen eines Klebers notwendig ist. Folglich beträgt die Zeitersparnis 216 Stunden (166 Stunden beim Drucken und 50 Stunden beim Scannen). Bei geschätzten 25 Franken/Euro (inkl. Fixkosten) ergeben sich 5400.– Franken/Euro an Personalkosten (216*25).

Gesamthaft dürften die Kosten somit 16’900 Franken/Euro pro Jahr betragen, die mit den virtuellen Barcodes so nicht mehr anfallen. Demgegenüber stehen ca. 10 Stunden für die Entwicklungs- und Implementierungszeit. Dies ergibt bei einer Abwicklung über uns bei einem Stundenansatz von 220.– Franken/Euro Gesamtkosten von 2200.– Euro/Franken. Damit ist im ersten Jahr eine Reduktion der Kosten um 14’700 Franken/Euro realisierbar. Hochgerechnet auf 10 Jähre (1*14700+9*16900) ergibt dies die stolze Summe von 166’800.– Franken/Euro.

Selbstverständlich kann der Prozess weiter automatisiert werden, indem die Bestellnummer direkt aus dem Beleg herausgelesen und in einem entsprechenden Feld von ArchivistaDMS gespeichert wird. Damit kann die ERP-Lösung des Kunden den Beleg automatisiert zuweisen und verarbeiten. Jedoch, hier ist der ERP-Anbieter gefragt, da mit dieser Optimierung die ERP-Lösung angepasst werden muss. Im hier beschriebenen Fall sind keine Anpassungen bei der ERP-Software notwendig und dennoch ergeben sich die entsprechenden Einsparungen. Enjoy!

Weiterführender Hinweis: Der Kunde arbeitet mit der ArchivistaBox Matterhorn. Aktuell umfasst das Archiv des Kunden 7.7 Millionen Dokumente mit gesamthaft 11.4 Millionen Seiten. Auf der Festplatte werden dabei 1.1 TByte für die Datenbank benötigt.

« AVMultimedia 2023/V mit SteamDeckSSD und 2023/IX »