Where do i manipulate the data for the relationship documents in accounts?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Andorxor
    Member
    • May 2019
    • 65

    Where do i manipulate the data for the relationship documents in accounts?

    We have documents on a server i would like to list under the documents of the accounts. I thought i could just scan the directories and add the files to the data and change the template, but i can not find the point where i can access the data.
    I tried actionRead actionList and actionListLinked in the document controller.
  • telecastg
    Active Community Member
    • Jun 2018
    • 907

    #2
    Not sure how to automate bulk linking of existing documents to accounts, which if I understand correctly it is what you want to do, but if it helps, this is what Espo does when you link a document to an account.

    Please note that I am not 100% certain that this is the exact order in which these operations are performed but the final effect is the same.

    1) It creates a "document" record with the following (relevant) values:
    id:System assigned id for the new "document" record
    name: Human readable name of the file to be uploaded

    2) It creates an "account_document" record to link the "document" to the "account" record with the following (relevant) values:
    id: System assigned id for the new "account_document" record
    account_id: Id of the (parent) "account" record
    document_id: Id of the new "document" record above

    3) It asks you to upload the document, the same as if you were uploading an attachment, so it creates an "attachment" record with the following (relevant) values:
    id: system assigned id number which will also be used as the file name for the actual attachment file which is stored in the folder data/upload/.
    name: Human readable name for the uploaded file
    related_id: Id of the new "document" record above
    related_type: "Document"

    4) It updates the "document" record as follows:
    file_id: Id of the new "attachment" record

    5) It stores the uploaded document as data/upload/(value of file_id)

    Once a document has been created following the previous steps, then in order to list the documents for a given account, you need to got to the Layout Manager and add "Document" to the relationship panel in your Account detail view.

    Clicking on the plus sign at the top of the document list will trigger the function actionCreateRelated in client/src/views/detail.js

    Clicking on a "document" row will trigger the function actionView in client/scr/controllers/record.js

    If you manage to find a way to automate bulk uploading and linking of documents PLEASE post it in this forum. I have seen a lot of interest in this feature from other participants.

    Saludos
    Last edited by telecastg; 03-01-2020, 03:34 PM.

    Comment

    • Andorxor
      Member
      • May 2019
      • 65

      #3
      I only needed Linking because the documents need to stay where they are.
      I added a function to the documentcontroller that searches a mounted drives for the folders with the id for the account and returns the files within them and than i add them in after render to the list with a link to a custom download function.

      Comment

      • telecastg
        Active Community Member
        • Jun 2018
        • 907

        #4
        Excellent solution, could you share your code ?

        Comment

        • Andorxor
          Member
          • May 2019
          • 65

          #5
          Code in the Document Controller:
          PHP Code:
           public function getActionSearchDocuments($params, $data, $request)
              {
                  $stnr = $request->get("id");
                  $r = new \stdClass();
                  $r->sections = array();
                  foreach($this->root_paths as $rootpath)
                  {
                      $item =  $this->ScanDirectoryForId($id, $rootpath);  
                      $item->Titel = array_pop(explode("/", rtrim($rootpath,"/")));
                      $item->Path = $rootpath;          
                      if(count($item->items) > 0)
                      {
                          $r->sections[] = $item;
                      }
                  }
                  return $r;
              }
          
              function getActionDownload($params, $data, $request)
              {
                  //return $request->get("path");
                  ob_clean();
                  $path = $request->get("path");
                  if ($file = fopen($path, "r"))
                  {
                      $size = filesize($path);
                      $path_parts = pathinfo($path);
                      $ext = strtolower($path_parts["extension"]);
                      header("Content-type: " . $this->GetMimeType($ext));
                      header("Content-length: $size");
                      header("Cache-control: private");
                      header("Content-Disposition: filename="" . $path_parts["basename"] . """);
                      while (!feof($file))
                      {
                          $buffer = fread($file, 2048);
                          echo $buffer;
                      }
                      fclose($file);
                      exit();
                  }
                  else
                  {
                      echo "Cannot read '$path'";
                  }
              }
          
              private function GetMimeType($ext)
              {
                  switch ($ext)
                  {
                      case "ods": return "application/vnd.oasis.opendocument.spreadsheet";
                      case "pdf": return "application/pdf";
                      case "doc": return "application/msword";
                      case "xls": return "application/msexcel";
                      case "txt": return "text/plain";
                      case "odt": return "application/vnd.oasis.opendocument.text";
                      default: return "application/octet-stream";
                  }
              }
          
          
              private function ScanDirectoryForId($id, $directory)
              {
                  $r = new \stdClass();
                  $r->items = array();
          
                  $c_dir = opendir($directory);
                  if ($c_dir === false)
                      return array("Could not open directory");
                  while ($entry = readdir($c_dir))
                  {
                      if ($entry == "." || $entry == "..")
                          continue;
                      $c_path = rtrim($directory,"/")."/". $entry;
          
                      $c_path_id = substr($c_path,strpos($c_path,"[") +1);
          
          
                      $c_path_id = substr($c_path_id,0,strpos($c_path_id,"]"));
                      $c_path_id = trim($c_path_id);
          
          
                      if ($c_path_id !=  $id|| strpos($c_path, "Thumbs.db") !== FALSE)
                          continue;
                      if (is_dir($c_path))
                          $r->items = array_merge($r->items, $this->ScanDirectoryForId($id, $c_path)->items);
          
                      if (is_file($c_path))
                      {
                          $doc = new \stdClass();
                          $doc->Path = $c_path;
                          $doc->EnPath = urlencode($c_path);
                          $doc->File = $c_path;
                          foreach ($this->data_paths as $datapath)
                          {
                              $doc->File = str_replace($datapath, "", $doc->File);
                          }
                          $doc->File = trim($doc->File, "/");
          
                          $doc->File = substr($doc->File, strpos($doc->File, "/") + 1);
                          if(strpos($doc->File, "/")!== FALSE)
                          {
                              $doc->Folder = substr($doc->File,0, strrpos($doc->File, "/"));
                              $doc->File = substr($doc->File,strrpos($doc->File, "/")+1);
                          }
                          $doc->State = "OK";
                          $doc->CreatedAt =  date("d.m.Y H:i", filectime($c_path));
                          $r->items[] = $doc;
                      }
                  }
                  return $r;
              } 
          
          View:
          PHP Code:
            afterRender: function ()
              {
          
                  Dep.prototype.afterRender.call(this);
                  if(this.collection.parentModel.has("stammnr"))
                  {
                      var xhttp = new XMLHttpRequest();
                      xhttp.overrideMimeType("text/plain");
                      xhttp.open("GET","......./CRM/api/v1/Document/action/searchDocuments?id=" +  this.collection.parentModel.get("id"), false);
                      xhttp.send();
                      var result =JSON.parse(xhttp.responseText);
                      var templatePath = ".....CRM/client/custom/res/templates/views/Account/fields/documents/list.tpl?x=1";
                      xhttp.open("GET",templatePath, false);
                      xhttp.send();
          
                      var templateSource = xhttp.responseText;
                      var template = Handlebars.compile(templateSource);
                      if($('div[data-name="documents"].panel-body tbody').length > 0)
                      {
                          $('div[data-name="documents"].panel-body tbody tr:first-child').before('<tr><th colspan="100%">Espo Dokumente</th></tr>');
                      }
                      else if(result.sections.length > 0)
                      {
                          $('div[data-name="documents"].panel-body').html('<table class="table"> <thead> <tr> <th style="text-align: left;" width="40%">Name </th> <th style="text-align: left;" width="10%">Datei </th> <th style="text-align: left;" width="25%">Ordner </th> <th style="text-align: left;" width="25%">Erstellt am </th> <th width="25"> </th> </tr> </thead> <tbody> </tbody> </table>');
                      }
                      $('div[data-name="documents"].panel-body tbody:last-child').after(template(result));
                  }
              } 
          
          Template:
          PHP Code:
          {{#each sections}}
          <tbody>
              <tr><th colspan="100%">{{Titel}}</th></tr>
              {{#each items}}
              <tr data-id="5e4bc7905d7e0f108" class="list-row">
                  <td class="cell" data-name="name" width="40%" title="{{File}}">{{File}}</td>
                  <td class="cell" data-name="file" width="10%"><a title="{{Path}}" href=".....CRM/api/v1/Document/action/download?path={{EnPath}}" target="_BLANK"><span class="fas fa-paperclip small"></span></a>    </td>
                  <td class="cell" data-name="folder" title="{{Folder}}">{{Folder}}</td>
                  <td class="cell" data-name="createdAt">{{CreatedAt}}</td>
                  <td class="cell" data-name="buttons"></td>
              </tr>
              {{/each}}
          </tbody>
          {{/each}} 
          
          css:
          PHP Code:
          tbody th
          {
              font-weight: bold;
              color: #999;
              text-align: center;
              text-decoration: underline;
          } 
          
          Last edited by Andorxor; 03-04-2020, 09:19 AM.

          Comment


          • telecastg
            telecastg commented
            Editing a comment
            Thanks so much !

          • esforim
            esforim commented
            Editing a comment
            Code too complex to understand. Anyone can explain to me in laymen on what it do?

            "searches a mounted drives for the folders with the id for the account"

            This explain it a little but does that mean each of the Account have a folder now in "/data/upload/" (or another filepath), and all file (documents) within this folder is automatically linked (Relationship) to the account?
        • Andorxor
          Member
          • May 2019
          • 65

          #6
          Each account has folders on another server i with [id] in their name. After the ESPO documents are loaded and displayed i send a request to the controller to search for folders with [idofthedisplayedAccount] and read the ffilepaths there.Than i use a template to turn them into html and append it to the table with the Espodokuments.The documents that are not added throught ESPO call a custom download function with their path as parameter.Nothing is changed in the database or /data/upload.

          Comment

          Working...