Billing Manager, billing log is blank

Hi @stephenwaite

I am running the code that is in the dev for billing. The billing log is empty after selecting generate x12 then select validate only. The error message below, I keep getting it no matter what.

    [Sat May 08 23:15:09.019815 2021] [php7:error] [pid 30921] [client] PHP Fatal error:  Uncaught Error: Call to a member function addClaim() on null in /var/www/html/boss/src/Billing/BillingProcessor/Tasks/GeneratorX12Direct.php:208\nStack trace:\n#0 /var/www/html/boss/src/Billing/BillingProcessor/Tasks/GeneratorX12Direct.php(144): OpenEMR\\Billing\\BillingProcessor\\Tasks\\GeneratorX12Direct->updateBatchFile()\n#1 /var/www/html/boss/src/Billing/BillingProcessor/Tasks/AbstractGenerator.php(68): OpenEMR\\Billing\\BillingProcessor\\Tasks\\GeneratorX12Direct->validateOnly()\n#2 /var/www/html/boss/src/Billing/BillingProcessor/BillingProcessor.php(139): OpenEMR\\Billing\\BillingProcessor\\Tasks\\AbstractGenerator->execute()\n#3 /var/www/html/boss/src/Billing/BillingProcessor/BillingProcessor.php(91): OpenEMR\\Billing\\BillingProcessor\\BillingProcessor->processClaims()\n#4 /var/www/html/boss/interface/billing/billing_process.php(33): OpenEMR\\Billing\\BillingProcessor\\BillingProcessor->execute( )\n#5 {main}\n  thrown in /var/www/html/boss/src/Billing/BillingProcessor/Tasks/GeneratorX12Direct.php on line 208, referer:

I have applied all of the billing changes on this list.

Is there something that I am missing?

hi @juggernautsei, might have found a bug, new code is pretty fresh

@stephenwaite I did a quick test to see if what the error message is displaying is true

    if (empty($claim)) {
        error_log("claim empty");
    } else {
        error_log("Claim not empty");

The log shows that the $claim is not empty.
The IDE did not show any suggestions when I type in $batch-> so I added $batch->.

So, I am looking at the

 $batch = $this->x12_partner_batches[$claim->getPartner()];

Which is calling a protected function within the class.


Is trying to call a function that is in


but the class is not instantiated inside the function to access the addClaim function.
I am grasping at straws here.

If you have direct submit selected, the billing log gets written to the output directory of the x-12 partner. It creates one x-12 file for each x-12 partner so those can be submitted individually/directly to the insco/x12-partner

@ken thanks for the response. The system is not creating the batch file in the /var/www/html/boss/sites/serenity/documents/edi folder.

I have tried to uncheck the direct submit and the system still does not output a file.

I believe if you run continue, it will generate a file. Otherwise it will print the claim to the screen. I thought @stephenwaite fixed the bug where errors/messages weren’t going to the bill_log (only printed to screen) but maybe not.

You could set a breakpoint at about line 254 or GeneratorX12Direct.php which is where each file is written to disk for each x-12 partner.

// This is the final, validated claim, write to the edi location for this x12 partner

And then in the BillingClaimBatch class…

public function write_batch_file()

It may be a permissions error? or you may not be attempting to write to the directory you think you’re writing to.

Looks like we pass the x12_partner_id to the write_batch_file() function, but shouldn’t and don’t need to. That should only generate a PHP notice though because write_batch_file() doesn’t accept any parameters.


I was off in what I was saying. The system will generate the claim file. I just did it to make sure. So, if I select continue the system does generate a new
The system is just not doing the log report for scrubbing the claims before sending.

That is why I was focused on 208 to build the x12 log. We tried the HCFA form and it populates the log file properly.

@ken Thanks!!

The error in the php error-log above is saying that the $batch is null, not the claim. I thought I fixed that, but that might happen when there’s no x-12 partner for the claim.

I think the x12 direct generator just prints the log to the screen. Maybe Stephen fixed the bill_log file output for HCFA only. I can look at it tomorrow on master.

Let me know if there are any more specifics on what behavior you’re expecting vs what you’re seeing.


After working on this all day. This is what I came up with and can verify from testing.

protected function updateBatchFile(BillingClaim $claim)
     //**This is empty, no name is returned**
    // Get the correct batch file using the X-12 partner ID
    $batch = $this->x12_partner_batches[$claim->getPartner()];

    // Get the correct edi count for this x-12 partner using the partner ID
    $edicount = $this->edi_counts[$claim->getPartner()];

    // Tell our batch that we've processed this claim
    $this->batch = new BillingClaimBatch();  //I added this to get rid of the error messages

    // Use the tr3 format to output for direct-submission to insurance companies
    $log = '';
    $is_last_claim = $claim->getIsLast();
    $HLCount = count($this->batch->getClaims());
    $segs = explode("~\n", X125010837P::gen_x12_837_tr3($claim->getPid(), $claim->getEncounter(), $log, $this->encounter_claim, $is_last_claim, $HLCount, $edicount));
    file_put_contents("/var/www/html/errors/edi.txt", print_r($segs, true)); //This does out put the an array of data 
    // edi count is passed by reference and incremented in the tr3 function, and we need to set it back here
    $this->edi_counts[$claim->getPartner()] = $edicount;

    return $log;

There is still nothing that shows for validate only nor in the billing log to scrub the claim.
I thought if I returned the logs. I would get a display in the billing process window.

I dumped the claim object and this is what I get.

OpenEMR\Billing\BillingProcessor\BillingClaim Object
    [id:protected] => 400-933
    [encounter:protected] => 933
    [pid:protected] => 400
    [partner:protected] => 4
    [payor_id:protected] => 5317
    [payor_type:protected] => 1
    [target:protected] => standard
    [is_last:protected] => 1
//**This is empty, no name is returned**
    // Get the correct batch file using the X-12 partner ID
    $batch = $this->x12_partner_batches[$claim->getPartner()];

This line should return a BillingClaimBatchObject. If it is empty (null), it sounds like maybe the x-12 partner with that ID (4) is not in the list of x-12 partners. Maybe it was deleted?

Here’s where that array is set up:


This is what that query should return from out system. We have only one x12 partner.
Where are these directories for x12 Partners?
I have not seen any in the documents folder.

That’s weird then. The setup created a ClaimBatchFile object for each x-12 partner returned from that query.

It’s also weird it’s empty because the system appears to generate the x12 file based on your above screenshot.

The directories are set in Practice Settings > x-12 partners. The “direct” implementation is designed to create one x-12 batch file per x-12 partner, and place them in the assigned directories, intended to submit files directly to insurance companies. For office ally, you can uncheck that box in globals. The it will use the GenerateX12 class, not the direct implementation.

From what I gather you’re telling me, it works ok in “continue” mode, but throwing an error in “validate” mode?

Yes that is correct. This is all about validate mode. I set the local directory to
/var/www/html/boss/sites/serenity/documents/edi so there would be no permission issues.
HCFA mode runs fine. It populates the log. But it only creates the first PDF it does not create the rest if more than one is selected.

@stephenwaite help me understand the reason you posted this message, please.

hi @juggernautsei, thought you were wondering why the validate didn’t produce log output?

Ok, @stephenwaite. I get it. Is continue suppose to product validation log?
The next steps would be to call that function?

@stephenwaite @juggernautsei

The billing log was only being written to disk if the generator task set an onLogCompleteCallback. In the case of the X12Direct generator, it doesn’t set a callback, so the log is never written. This change writes the process_bills.log to disk every time.

     * Called when log is done writing
     * @return false|mixed
    public function onLogComplete()
        // If the generator set a callback function for when the log completes, call it here
        if (isset($this->onLogCompleteCallback)) {

        // If the hlog isn't empty, write the log to disk
        if (!empty($this->hlog)) {
            if ($GLOBALS['drive_encryption']) {
                $this->hlog = $this->cryptoGen->encryptStandard($this->hlog, null, 'database');
            file_put_contents($GLOBALS['OE_SITE_DIR'] . "/documents/edi/process_bills.log", $this->hlog);

        return false;