Deluge function to copy parent record file upload field to child record file upload field

Deluge function to copy parent record file upload field to child record file upload field

I'm stuck trying to write a deluge function that is triggered via automation in child record "Appointments," confirms if a file is in file upload "Report" field of parent "Contacts" record via Contacts lookup field "Contact_Name".  If no file is in parent record, function exits.  If there is a file, saves a copy of that file in Appointments.Report file upload field.

Any help would be appreciated, here's what I have so far, also attached as a .txt file.

If it simplifies, it would also be fine saving the copy of the file in Appointments attachment section instead of directly in the file upload field, but ideally it's copied from file upload Contacts.Report file upload to file upload Appointments.Report.

// Trigger: Workflow / automation on the CHILD module "Appointments"
// Goal: Copy the first file from parent Contact.Report into Appointments.Report
// NOTE: This version triggers workflow/approval/blueprint/orchestration on the final updateRecord

void automation.copyReportFromContactToAppointment(int appointmentId)
{
    // ----------------------------
    // CONFIG
    // ----------------------------
    string apptModule = "Appointments";
    string contactModule = "Contacts";
    string contactLookupApi = "Contact_Name";   // lookup field on Appointments -> Contacts
    string fileFieldApi = "Report";             // file upload field on both modules
    string oauthConn = "crm_oauth_connection";  // update to your CRM OAuth connection link name

    // Trigger downstream automations on CRM updates
    options = Map();
    options.put("trigger", {"workflow","approval","blueprint","orchestration"});

    // ----------------------------
    // 1) Get Appointment
    // ----------------------------
    appt = zoho.crm.getRecordById(apptModule, appointmentId);
    if(appt == null || appt.isEmpty())
    {
        info "Appointment not found: " + appointmentId;
        return;
    }

    // ----------------------------
    // 2) Resolve parent Contact via lookup
    // ----------------------------
    contactIdStr = "";
    try
    {
        lookup = appt.get(contactLookupApi);
        if(lookup != null && lookup.get("id") != null)
        {
            contactIdStr = lookup.get("id").toString();
        }
    }
    catch (e1)
    {
        contactIdStr = "";
    }

    if(contactIdStr == "" || !contactIdStr.matches("[0-9]+"))
    {
        info "Could not resolve Contact via lookup field " + contactLookupApi;
        return;
    }

    contactId = contactIdStr.toLong();

    // ----------------------------
    // 3) Get Contact
    // ----------------------------
    contact = zoho.crm.getRecordById(contactModule, contactId);
    if(contact == null || contact.isEmpty())
    {
        info "Contact not found: " + contactId;
        return;
    }

    // ----------------------------
    // 4) Check Contact.Report file upload field
    // ----------------------------
    filesList = ifnull(contact.get(fileFieldApi), list());
    if(filesList.isEmpty())
    {
        info "No file present in Contact." + fileFieldApi + " — exiting.";
        return;
    }

    // Read FIRST file's file_Id (typical key name in CRM file upload fields)
    fileId = "";
    fileName = "";
    try { fileId = ifnull(filesList.get(0).get("file_Id"), "").toString(); } catch (e2) { fileId = ""; }
    try { fileName = ifnull(filesList.get(0).get("file_Name"), "").toString(); } catch (e3) { fileName = ""; }

    if(fileId.trim() == "")
    {
        info "File exists but could not read file_Id from Contact." + fileFieldApi;
        return;
    }

    // ----------------------------
    // 5) Download the file
    // ----------------------------
    downloadedFile = null;
    try
    {
        downloadedFile = invokeurl
        [
            url :"https://www.zohoapis.com/crm/v2.1/files/" + fileId
            type :GET
            connection: oauthConn
            response-format: FILE
        ];
    }
    catch (dlErr)
    {
        info "Download error: " + dlErr.toString();
        return;
    }

    if(downloadedFile == null)
    {
        info "Download returned null. fileId=" + fileId;
        return;
    }

    // Optional file metadata helpers (safe to ignore if unsupported)
    try { downloadedFile.setFileName(fileName); } catch (nf1) {}
    try { downloadedFile.setParamName("file"); } catch (pn1) { try { downloadedFile.setparamname("file"); } catch (pn2) {} }

    // ----------------------------
    // 6) Upload to /crm/v2.1/files to get a NEW file id
    // ----------------------------
    uploadedResp = null;
    try
    {
        uploadedResp = invokeurl
        [
            url :"https://www.zohoapis.com/crm/v2.1/files"
            type :POST
            files: downloadededFile
            connection: oauthConn
        ];
    }
    catch (upErr)
    {
        info "Upload-to-files error: " + upErr.toString();
        return;
    }

    newFileId = "";
    try { newFileId = uploadedResp.get("data").get(0).get("details").get("id").toString(); } catch (e4) { newFileId = ""; }

    if(newFileId.trim() == "")
    {
        info "Upload-to-files did not return new id. Response: " + uploadedResp.toString();
        return;
    }

    // ----------------------------
    // 7) Update Appointments.Report using List(Map(file_id))
    // ----------------------------
    fileUploadList = List();
    fileUploadList.add({"file_id": newFileId});

    updateMap = Map();
    updateMap.put(fileFieldApi, fileUploadList);

    updateResp = zoho.crm.updateRecord(apptModule, appointmentId, updateMap, options);
    info "Appointment update response: " + updateResp;
}