You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Trigger将带业务数据的PDF关联到Opportunity及空白问题排查

问题修复方案

核心问题原因

  • 上下文隔离问题:你在future方法中手动实例化的OpportunityPdfController和VF页面渲染时系统自动创建的控制器是完全独立的两个实例,前者填充的数据无法传递给后者,VF页面读取的是全新实例中未赋值的pricingDetails,因此内容为空。
  • 空集合未初始化:OpportunityPdfController中的pricingDetails属性仅声明未初始化,直接调用add()方法会触发空指针异常,也是数据无法正常加载的原因之一。
  • 字段拼写错误:Attachment对象的关联父记录字段是ParentId,你的代码中写为ParenId,会导致附件关联失败。
  • 触发器事件不匹配:触发器声明仅支持after insert事件,但判断逻辑包含after update,插入场景下逻辑不会执行。

修复代码

1. 修正触发器

// 新增after update事件支持
trigger OpportunityTrigger on Opportunity (after insert, after update)
if(trigger.isAfter && (trigger.isInsert || trigger.isUpdate)) {
    opportunityTriggerHelper.attachFileToOpportunityRecord(trigger.new);
}

2. 修正Helper类

private void attachFileToOpportunityRecord(List<Opportunity> lstOpp) {
    List<Id> oppListIdsForAttach = new List<Id>();
    for(Opportunity opp : lstOpp) {
        oppListIdsForAttach.add(opp.Id);
    }
    attachFileToOpportunities(oppListIdsForAttach);
}

@future(callout=true)
private static void attachFileToOpportunities(List<Id> OpportunityIds) {
    List<Attachment> attachList = new List<Attachment>();
    for(Id oppId : OpportunityIds) {
        // 给VF页面传递oppId参数,不需要手动实例化控制器
        PageReference pdfPage = Page.PdfAttachmentForOpp;
        pdfPage.getParameters().put('oppId', oppId);
        Blob pdfBody = pdfPage.getContent();

        Attachment attach = new Attachment();
        attach.Body = pdfBody;
        attach.Name = 'Pdf file';
        attach.IsPrivate = false;
        // 修正拼写错误
        attach.ParentId = oppId;
        attachList.add(attach);
    }
    insert attachList;
}

3. 修正VF页面控制器

public with sharing class OpportunityPdfController {
    public List<PricingDetailWrapper> pricingDetails {get;set;}

    // 构造函数:VF页面加载时自动获取参数,初始化数据
    public OpportunityPdfController() {
        // 初始化集合,避免空指针
        pricingDetails = new List<PricingDetailWrapper>();
        String oppId = ApexPages.currentPage().getParameters().get('oppId');
        if(oppId != null) {
            getData(oppId);
        }
    }

    public void getData(Id opportunityId) {
        List<Pricing_Detail__c> pdList = [
            SELECT basePrice
            FROM Pricing_Detail__c
            WHERE OpportunityId =: opportunityId
        ];
    
        for(Pricing_Detail__c pd : pdList) {
            PricingDetailWrapper pdw = new PricingDetailWrapper();
            pdw.basePrice = pd.basePrice;
            pricingDetails.add(pdw);
        }
    }

    public class PricingDetailWrapper {
        public String basePrice {get;set;}
    }
}

4. VF页面无需修改,保持原有逻辑即可。

内容的提问来源于stack exchange,提问作者ChrisB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 09:12:03