Untitled

both fucntions those are calling submissioncheck method
 avatar
unknown
plain_text
a month ago
22 kB
1
Indexable
package Clinical::P4P::Submission;

# Utility (non-model-specific) functions related to QM submission functionality,
# which is comprised of 3 components, generally speaking:
#	1. The creation and maintenance of denormalized measure/program satisfaction
#		information in P4PSUBMISSION/DATA.
#	2. The final attainment by a provider of satisfaction for a program.
#	3. The generation of provider measure/program satisfaction information in XML format
#		and the submission of this to interested or regulating parties.
# See Clinical/P4P/Submission/* for further generic and submission-model-specific functions.

use Athena::Policy;

use constant ALLPROVIDERID => -1;
use constant ALLFEDERALIDNUMBER => 'ALL';
use constant LOG_SEPARATOR => '=' x 90 . "\n";

use Athena::P4P::Entity::Result::ResultReportConfiguration;
use Athena::P4P::App::PerformanceData;
use Athena::P4P::Persistence::PerformanceData;
use Athena::P4P::Persistence::Result::ResultReport;
use Athena::RolloutToggle;
use Athena::ServiceBus::Dispatcher qw( P4P::GetProgramDefinition );
use Athena::ServiceBus;
use Athena::Util::Assert;
use Athena::Util::Database;
use Athena::Util::Hash;
use Athena::Util::Text;
use Athena::Util::SQL;
use AthenaDate;
use Athena::DateTime;
use DateTime;
use AthenaUtils;
use Athena::ServiceBus::Attributes;
use Cache;
use Clinical::P4P::Attestation;
use Clinical::P4P::LegacyEHR;
use Clinical::P4P::Log;
use Clinical::P4P::Measure;
use Clinical::P4P::Persistence::MultiProviderSubmission;
use Clinical::P4P::Persistence::ProgramSubmission;
use Clinical::P4P::Provider;
use Clinical::P4P::ReportingPeriod;
use Clinical::P4P::Result;
use Clinical::P4P::Tech::Data;
use Clinical::P4P::Utils;
use Enrollment::P4P;
use Global;
use List::MoreUtils;
use List::Util qw( first );
use List::Compare;
use PageCache;
use Proc;
use Provider;
use SQL::Select;
use SQL;
use Time::HiRes qw( gettimeofday tv_interval );
use Try::Tiny;
use WorkUnit::AthenaDB;
use Athena::Conf::AthenaNet;
use Athena::Util::Database;
use Athena::Util::List;
use Clinical::P4P::Attestation::ProgramTaskAttestationDetails;
use Athena::Util::Carp qw(
	carp
	cluck
	confess
	croak
	reconfess
);

# SC stands for Submission Check.

our $UserName = 'ATHENASCRUB_SC';

our $LocalDBH;

our %SubStatusMap = (
	ATTESTED => {
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
	},
	ATTESTEDELSEWHERE => {
		MULTITABLESPACE => 1,
	},
	ATTESTINGELSEWHERE => {
		BLACKLISTED => 1,
		COUNTMISMATCH => 1,
		HOSPITAL => 1,
		MULTITABLESPACE => 1,
		NOPHR => 1,
		OUTSIDEATHENA => 1,
		UNSCRUBBEDPATIENTS => 1,
	},
	COMPLETEDBYCLIENT => {
	},
	FAILED => {
		# BADENROLLMENT: Failing reporting requirements due to bad enrollment (e.g. No Cross Cutting measure for PQRS Registry)
		BADENROLLMENT => 1,
		BLACKLISTED => 1,
		COUNTMISMATCH => 1,
		FAILINGBEHAVIORAL => 1,
		FAILINGCOREMEASURES => 1,
		FAILINGMENUMEASURES => 1,
		FAILINGREGISTRYMEASURES => 1,
		HOSPITAL => 1,
		IMMREGENROLLMENTTASK => 1,
		LEGACYNOTENABLED => 1,
		MULTITABLESPACE => 1,
		# INSUFFICIENTDATA: Not meeting minimum reporting requirements
		INSUFFICIENTDATA => 1,
		# INSUFFICIENTTIMEONATHENA: Not meeting minimum time on athenaNet.
		INSUFFICIENTTIMEONATHENA => 1,
		# INVALIDENROLLMENT: Submission includes inappropriate enrollments
		INVALIDENROLLMENT => 1,
		INVALIDLEGACYPORTALDATA => 1,
		# NOPATIENTS: Submission does not have enough patients to satisfy reporting requirements
		NOPATIENTS => 1,
		NOCONTACTINFO => 1,
		NOLEGACYSIGNOFF => 1,
		NOLEGACYDATA => 1,
		NOLEGACYPORTALSIGNOFF => 1,
		NOLEGACYPORTALDATA => 1,
		NOPATIENTLIST => 1,
		NOPHR => 1,
		NOPROXY => 1,
		NOSRA => 1,
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
		OUTSIDEATHENA => 1,
		SRANOTDONE => 1,
		UNSCRUBBEDPATIENTS => 1,
		# ZEROPERFORMANCERATE: Not meeting minimum reporting requirements because at least one measure has a 0 performance rate
		ZEROPERFORMANCERATE => 1,
	},
	NOTSATISFIED => {
		# BADENROLLMENT: Failing reporting requirements due to bad enrollment (e.g. No Cross Cutting measure for PQRS Registry)
		BADENROLLMENT => 1,
		BLACKLISTED => 1,
		COUNTMISMATCH => 1,
		# FAILINGBEHAVIORAL: Indicates the provider is failing their core and/or menu measures
		# and that their failure cannot be corrected by a simple provider or athena action (such as
		# completing their SRA).
		FAILINGBEHAVIORAL => 1,
		# FAILINGCOREMEASURES: Indicates the provider is failing their core measures. Unlike FAILINGBEHAVIORAL,
		# this does not account for potential provider actions.  A provider who has not completed their SRA but
		# is otherwise passing will have FAILINGCOREMEASURES set but not FAILINGBEHAVIORAL.
		FAILINGCOREMEASURES => 1,
		# FAILINGMENUMEASURES: The same as FAILINGCOREMEASURES, except for menu measures.
		FAILINGMENUMEASURES => 1,
		FAILINGREGISTRYMEASURES => 1,
		HOSPITAL => 1,
		IMMREGENROLLMENTTASK => 1,
		LEGACYNOTENABLED => 1,
		MULTITABLESPACE => 1,
		# INSUFFICIENTDATA: Not meeting minimum reporting requirements
		INSUFFICIENTDATA => 1,
		# INSUFFICIENTTIMEONATHENA: Not meeting minimum time on athenaNet.
		INSUFFICIENTTIMEONATHENA => 1,
		# INVALIDENROLLMENT: Submission includes inappropriate enrollments
		INVALIDENROLLMENT => 1,
		INVALIDLEGACYPORTALDATA => 1,
		NOCONTACTINFO => 1,
		# NOCROSSCUTTING: Submission is missing a required cross-cutting measure
		NOCROSSCUTTING => 1,
		NOLEGACYSIGNOFF => 1,
		NOLEGACYDATA => 1,
		NOLEGACYPORTALSIGNOFF => 1,
		NOLEGACYPORTALDATA => 1,
		# NOPATIENTS: Submission does not have enough patients to satisfy reporting requirements
		NOPATIENTS => 1,
		NOPATIENTLIST => 1,
		NOPHR => 1,
		NOPROXY => 1,
		NOSRA => 1,
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
		OUTSIDEATHENA => 1,
		SRANOTDONE => 1,
		UNSCRUBBEDPATIENTS => 1,
		# WAITINGONPROVIDER: Indicates the provider may take some simple action to
		# improve their status, such as completing their SRA.
		WAITINGONPROVIDER => 1,
		# WAITINGONATHENA: Indicates athena may take some simple action to improve their
		# status.
		WAITINGONATHENA => 1,
		# ZEROPERFORMANCERATE: Not meeting minimum reporting requirements because at least one measure has a 0 performance rate
		ZEROPERFORMANCERATE => 1,
		# BADFCED: Not having first encounter dater for program, provider, federalid combination inside the program's reporting period
		BADFCED => 1,
		# MINPERFORMANCEPERIODNOTMET: Not having minimum performance period to for given program to get snapshotted and complete submission
		MINPERFORMANCEPERIODNOTMET => 1,
		# POINTSLESSTHANFIFTY : Not having minimum score for Hospital PI 
		POINTSLESSTHANFIFTY => 1,
		REPORTINGPERIOD_NC => 1,
	},
	OPTOUTMU => {
	},
	PAYMENTRECEIVED => {
	},
	READYTOATTEST => {
		MULTITABLESPACE => 1,
		NOCONTACTINFO => 1,
		NOPROXY => 1,
		OUTSIDEATHENA => 1,
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
	},
	READYTOATTESTELSEWHERE => {
	},
	SATISFIED_WAITINGONPROVIDER => {
		HOSPITAL => 1,
		IMMREGENROLLMENTTASK => 1,
		MULTITABLESPACE => 1,
		NOCONTACTINFO => 1,
		NOLEGACYSIGNOFF => 1,
		NOLEGACYDATA => 1,
		NOLEGACYPORTALSIGNOFF => 1,
		NOLEGACYPORTALDATA => 1,
		NOPATIENTLIST => 1,
		NOPROXY => 1,
		NOSRA => 1,
		OUTSIDEATHENA => 1,
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
		INVALIDLEGACYPORTALDATA => 1,
	},
	SATISFIED_WAITINGONATHENA => {
		BLACKLISTED => 1,
		BLOCKEDBYCONTRIBUTINGTABLESPACE => 1,
		COUNTMISMATCH => 1,
		FAILINGREGISTRYMEASURES => 1,
		HOSPITAL => 1,
		IMMREGENROLLMENTTASK => 1,
		# INVALIDENROLLMENT: Submission includes inappropriate enrollments
		INVALIDENROLLMENT => 1,
		# INSUFFICIENTTIMEONATHENA: Not meeting minimum time on athenaNet.
		INSUFFICIENTTIMEONATHENA => 1,
		LEGACYNOTENABLED => 1,
		MULTITABLESPACE => 1,
		NOCONTACTINFO => 1,
		NOLEGACYSIGNOFF => 1,
		NOLEGACYDATA => 1,
		NOLEGACYPORTALSIGNOFF => 1,
		NOLEGACYPORTALDATA => 1,
		NOPATIENTLIST => 1,
		NOPHR => 1,
		NOPROXY => 1,
		NOSRA => 1,
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
		OUTSIDEATHENA => 1,
		SNAPSHOTBUFFER => 1,
		UNSCRUBBEDPATIENTS => 1,
		BEGINSNAPSHOTTING_IS_N => 1,
	},
	SUBMITTED => {
		# NOQCS: Unable to calculate a Quality Composite Score based on the Submission's available data
		NOQCS => 1,
	},
);

our @AttestationTaskSubStatuses = (
	'NOCONTACTINFO',
	'NOPROXY',
);

# We sometimes connect to the standbys to access load the
# result data (to reduce database load).

my %StandbyDBHCache;

################################################################################
# UpdateAndRetrieveAdditionalData
#
# Description:
# 	Updates measure counts and then returns the new measure counts.
#
# Parameters:
# 	Required:
# 		P4PPROGRAMID		Integer.
# 		At least one of
# 			PROVIDERID		Integer.
# 			FEDERALIDNUMBER		Integer.
# 		SUBMISSIONNUMBER	Integer.
# 	Optional:
# 		INCLUDECHARTIDS		Boolean. Used when retrieving submission measure data
# 		INCLUDEPATIENTIDS		Boolean. Used when retrieving submission measure data
# 		USERNAME		String.
#
# Returns:
# 	MEASUREDATA	Arrayref of Hashrefs:
# 		DENOMEX				Integer.
# 		DENOMINATOR			Integer.
# 		ENROLLED			Boolean. 1 or 0.
# 		EXCLUDED			Integer.
# 		GROUPORDERING			Integer.
#		INTERFACEVENDORID	String.
# 		IPP				Integer.
# 		NUMERATOR			Integer.
# 		P4PMEASUREID			Integer.
# 		P4PMEASURESUBSCRIPTIONID	Integer.
# 		P4PSUBMISSIONGROUPID		Integer.
# 		PROGRAMKEY			String.
# 		STATUS				String.
# 		SUBMISSIONNUMBER		Integer.
# 	PREVENTSNAPSHOT	Boolean 1/0. If 1, the provider should not be able to snapshot
# 				in the Attesting practice
################################################################################
Expose( 'UpdateAndRetrieveAdditionalData', 'ATHENANETINTERNALWEBSERVICE' );
sub UpdateAndRetrieveAdditionalData {
	my ($dbh, $args) = @_;

	Athena::Util::Assert::AssertFields($args,
		[
			qw(
				P4PPROGRAMID
				SUBMISSIONNUMBER
			),
			{
				ONEPLUS => [qw(
					PROVIDERID
					FEDERALIDNUMBER
				)],
			},
		],
		[qw(
			INCLUDECHARTIDS
			INCLUDEPATIENTIDS
			USERNAME
			MULTITABLESPACEDATA
		)],
	);
	my $federalidnumber = $args->{FEDERALIDNUMBER};
	my $p4pprogramid = $args->{P4PPROGRAMID};
	my $providerid = $args->{PROVIDERID};
	my $submissionnumber = $args->{SUBMISSIONNUMBER};
	my $username = $args->{USERNAME} || $Global::session{USERNAME};

	my $includechartids = $args->{INCLUDECHARTIDS};
	my $includepatientids = $args->{INCLUDEPATIENTIDS};
	
	my $multitablespacedata = $args->{MULTITABLESPACEDATA};

	my $measuresatisfactionrules = Clinical::P4P::Submission::GetMeasureSatisfactionRules($dbh, {
		P4PPROGRAMID => $p4pprogramid,
	});

	my $npiprovidermap = Clinical::P4P::Provider::GetNPIProviderMap($dbh, {
		ALLDUPLICATES => 1,
	});

	my $duplicateproviderids = $npiprovidermap->{ $providerid };

	if (
		$providerid
	) {
		$providerid = Clinical::P4P::Provider::GetRepresentativeProviderID($dbh, {
			PROVIDERID => $providerid,
			FEDERALIDNUMBER => $federalidnumber,
			PROVIDERENTITYTYPEFLAG => 1,
		});
	}
	my $quproconf = Athena::Conf::AthenaNet::InternalServices('qupro');
	my @mtsimprovement_contexts  = (380,1438,2183,4290,7598,8042,8209,9582,9954,10170,11541,12833,13122);
	if (defined $quproconf->{mtsimprovement_contexts}){
		@mtsimprovement_contexts = split (<,>, $quproconf->{mtsimprovement_contexts});
	}
	my $mtsimprovements = (AthenaUtils::InList(Athena::Util::Database::SessionInfo($dbh)->{context}, @mtsimprovement_contexts)) ? 1 : 0;

	my $resultdata = GetResultData($dbh, {
		FEDERALIDNUMBER => $federalidnumber,
		P4PPROGRAMID => $p4pprogramid,
		PROVIDERID => $providerid,
		SUBMISSIONNUMBER => $submissionnumber,
		SUBMISSIONCHECKIMPROVEMENTS => 1,
		CALLFROMMTS => $mtsimprovements, 
	});

	my $submissioncheckresult;

	AthenaUtils::DBTransaction(sub {
		$submissioncheckresult = Clinical::P4P::Submission::SubmissionCheck($dbh, {
			ALLOWCONTRIBUTINGPROVIDERS => 1,
			DUPLICATEPROVIDERIDS => $duplicateproviderids,
			FEDERALIDNUMBER => $federalidnumber,
			MEASURESATISFACTIONRULES => $measuresatisfactionrules,
			P4PPROGRAMID => $p4pprogramid,
			PROVIDERID => $providerid,
			RESULTDATA => $resultdata,
			RUNALLOVERRIDES => 1,
			SUBMISSIONNUMBER => $submissionnumber,
			USERNAME => $username,
			MULTITABLESPACEDATA => $multitablespacedata,
		});
	}, $dbh);
			
	my $submissionobject = Clinical::P4P::Submission::MaybeCreateResult($dbh, {
		FEDERALIDNUMBER => $federalidnumber,
		P4PPROGRAMID => $p4pprogramid,
		PROVIDERID => $providerid,
		SUBMISSIONNUMBER => $submissionnumber,
	});

	my $measuredata = $submissionobject->GetMeasureData({
		KEYS => [qw(
			DENOMEX
			DENOMINATOR
			ENROLLED
			EXCLUDED
			IPP
			NUMERATOR
			STATUS
			INTERFACEVENDORID
		)],
		INCLUDECHARTIDS => $includechartids,
		INCLUDEPATIENTIDS => $includepatientids,
	});

	my $submissionmodule = Clinical::P4P::Utils::GetProgramModule($dbh, {
		P4PPROGRAMID => $p4pprogramid,
		TYPE => 'Submission',
	});

	my $rp = $submissionobject->ReportingPeriod();

	my $preventsnapshot;

	my $submissionperiodcomplete = $rp->RequiredSubmissionSizeAttained({
		SUBMISSIONNUMBER => $submissionnumber,
	});

	if (
		! $submissionperiodcomplete
	) {
		$preventsnapshot = 1;
	}
	else {
		my $substatuses = $submissionobject->GetSubStatusesBySubmissionNumber({
			SUBMISSIONNUMBER => $submissionnumber,
		}) || {};

		$preventsnapshot = $submissionmodule->ShouldAdditionalSubStatusesPreventSnapshot($dbh, {
			SUBSTATUSES => [ keys %{ $substatuses->{SUBSTATUSES} || {} } ],
		});
	}
	return {
		MEASUREDATA => $measuredata,
		PREVENTSNAPSHOT => $preventsnapshot,
	};
}


###############################################################################
# MaybeCreateResult
#
# Description:
#	Returns the ID of the row in P4PSUBMISSION corresponding to the specified TIN/provider and program, incorporating 'duplicate provider' logic to find the P4PSUBMISSION
#	for the 'representative' provider of the specified one, when applicable.
#	If such a P4PSUBMISSION does not already exist, one will be instantiated, and the SubmissionCheck() executed on it, unless DONOTINSTANTIATE is specified.
#
# Parameters:
#	Required
#		P4PPROGRAMID
#		PROVIDERID and/or FEDERALIDNUMBER
#		SUBMISSIONNUMBER
#	Optional
#		DONOTINSTANTIATE		Boolean.  If the provider/program combination specified is not associated with a submission (P4PSUBMISSION row)
#							do not create one, and return the empty string.
#		DUPLICATEPROVIDERIDS		Listref.  The IDs of the PROVIDERs in the specified provider's 'duplicate set'.  Will be computed if not provided.
#		SUBMISSIONNUMBER.		Integer.	The submission number to find the
#			corresponding p4psubmission for.  If not specified, defaults to
#			the current submission number for the program, or 1 if we're before
#			the beginning of the reporting period.
#
# Return Value:
#	Integer.  The ID of the P4PSUBMISSION row located or created, or the empty string, if no P4PSUBMISSION exists and DONOTINSTANTIATE is specified.
###############################################################################
sub MaybeCreateResult  : CoveredByAPI("Athena::P4P::API::Submission::MaybeCreateResult") {

	my ($dbh, $args) = @_;

	AssertFields(
		$args,
		[
			qw(
				P4PPROGRAMID
			),
			{
				ONEPLUS => [qw(
					PROVIDERID
					FEDERALIDNUMBER
				)],
			},
		],
		[qw(
			DONOTINSTANTIATE
			DUPLICATEPROVIDERIDS
			SUBMISSIONNUMBER
		)],
	);

	my $p4pprogramid = $args->{P4PPROGRAMID};
	my $providerid = $args->{PROVIDERID};
	my $federalidnumber = $args->{FEDERALIDNUMBER};

	my $donotinstantiate = $args->{DONOTINSTANTIATE};
	my $duplicateproviderids = $args->{DUPLICATEPROVIDERIDS};
	my $submissionnumber = $args->{SUBMISSIONNUMBER};

	my $contextid = Athena::Util::Database::SessionInfo($dbh)->{context};

	my $submissionobject;

	DBTransaction( sub {

		# in case of multiple providers having the same NPI, use the primary one and get a list of the rest
		if (
			! $duplicateproviderids
			&& $providerid
		) {
			$duplicateproviderids = Clinical::P4P::Provider::GetDuplicateProviderIDs($dbh, {
				PROVIDERID => $providerid,
				FEDERALIDNUMBER => $federalidnumber,
			});
		}

		my $representativeproviderid;
		if (
			$providerid
		) {
			$representativeproviderid = Clinical::P4P::Provider::GetRepresentativeProviderID($dbh, {
				PROVIDERID => $providerid,
				FEDERALIDNUMBER => $federalidnumber,
				PROVIDERENTITYTYPEFLAG => 1,
			});

			if (
				$representativeproviderid != $providerid
			) {

				# This function should never be called with a non-primary provider ID, but if it is,
				# we want to catch and correct those cases.

				Clinical::P4P::Log::Log($dbh, {
					LEVEL => 'error',
					MESSAGE => "MaybeCreateResult called with non-primary duplicate NPI providerid.",
					SCRIBEIDENTIFIER => 'p4psubmissionlogs',
					TAGS => {
						CONTEXTID => $contextid,
						P4PPROGRAMID => $p4pprogramid,
						PROVIDERID => $providerid,
						FEDERALIDNUMBER => $federalidnumber,
						SUBMISSIONNUMBER => $submissionnumber,
					},
				});
			}
		}

		if (
			!$submissionnumber
		) {
			my $reportingperiod = Clinical::P4P::ReportingPeriod::Get($dbh, {
				P4PPROGRAMID => $p4pprogramid,
				PROVIDERID => $representativeproviderid,
			});

			$submissionnumber = $reportingperiod->CurrentSubmissionNumber();
		}

		$submissionobject = Clinical::P4P::Persistence::ProgramSubmission->new({
			DBH => $dbh,
			P4PPROGRAMID => $p4pprogramid,
			PROVIDERID => $representativeproviderid,
			FEDERALIDNUMBER => $federalidnumber,
			SUBMISSIONNUMBER => $submissionnumber,
		});

		if (
			$submissionobject->NoDenormalizedData({
				SUBMISSIONNUMBER => $submissionnumber,
			})
			&& ! $donotinstantiate
		) {
			my $submissionmodule = Clinical::P4P::Utils::GetProgramModule($dbh, {
				P4PPROGRAMID => $p4pprogramid,
				TYPE => 'Submission',
			});

			my $enrollmentsql = SQL::Select->new(
				)->Select(
					'distinct p4pmeasuresubscriptionid',
					'1',
				)->From(
					'vp4penrollment',
				)->Where(
					['vp4penrollment.p4pprogramid = ?', $p4pprogramid],
				);

			if (
				$duplicateproviderids
			) {
				$enrollmentsql->Where(
					['vp4penrollment.providerid in (??)', $duplicateproviderids],
				);
			}
			elsif (
				$federalidnumber
			) {
				# We only want to look for TIN level enrollments if
				# we are not creating a provider level submission.

				$enrollmentsql->Where(
					['vp4penrollment.federalidnumber = ?', $federalidnumber],
				);
			}

			my %enrollment = $enrollmentsql->ColumnValues($dbh);


			if (!$submissionmodule) {

				# create a stub if the we do not have denormalization logic
				# for this program or the provider is not enrolled in this program
				$submissionobject = _CreateResult($dbh, {
					ENROLLMENTDATA => \%enrollment,
					SUBMISSIONOBJECT => $submissionobject,
					SUBMISSIONNUMBER => $submissionnumber,
				});

				# We shouldn't be calling MaybeCreateResult on a program with no submissionmodule
				# but will be better off cleaning it up later than not returning with a p4psubmissionid

				Clinical::P4P::Log::Log($dbh, {
					LEVEL => 'error',
					MESSAGE => "Stub P4PSUBMISSION row created for program when it shouldn't be.",
					SCRIBEIDENTIFIER => 'p4psubmissionlogs',
					TAGS => {
						CONTEXTID => $contextid,
						P4PPROGRAMID => $p4pprogramid,
						PROVIDERID => $providerid,
						FEDERALIDNUMBER => $federalidnumber,
						SUBMISSIONNUMBER => $submissionnumber,
					},
				});
			}
			else {
				# get initial denormalized data
				my $programdefinition = BusCall::P4P::GetProgramDefinition($dbh, {
					P4PPROGRAMID => $p4pprogramid,
				});

				$submissionobject = _CreateResult($dbh, {
					PROGRAMDEFINITION => $programdefinition,
					ENROLLMENTDATA => \%enrollment,
					SUBMISSIONOBJECT => $submissionobject,
					SUBMISSIONMODULE => $submissionmodule,
					SUBMISSIONNUMBER => $submissionnumber,
				});

				# Get Program-specific measure satisfaction rules
				my $satisfactionrules = GetMeasureSatisfactionRules($dbh, {
					P4PPROGRAMID => $p4pprogramid,
				});
				# Get Provider Results
				my $results = GetResultData($dbh, {
					P4PPROGRAMID => $p4pprogramid,
					PROVIDERID => $representativeproviderid,
					FEDERALIDNUMBER => $federalidnumber,
					SUBMISSIONNUMBER => $submissionnumber,
					SUBMISSIONCHECKIMPROVEMENTS => 1,
				});

				SubmissionCheck($dbh, {
					DUPLICATEPROVIDERIDS => $duplicateproviderids,
					MEASURESATISFACTIONRULES => $satisfactionrules,
					P4PMEASURESUBSCRIPTIONIDS => [keys %enrollment],
					P4PPROGRAMID => $p4pprogramid,
					PROVIDERID => $representativeproviderid,
					FEDERALIDNUMBER => $federalidnumber,
					RESULTDATA => $results,
					SUBMISSIONNUMBER => $submissionnumber,
					UPDATECOUNTSONLY => 1,
					USERNAME => 'MAYBECREATERESULT',
				});

				# This function is susceptible to 'Out of Memory!' errors, when run successively on multiple providers, in large practices.
				# We combat this here by freeing up the memory used by the large '$results' data structure, and by its
				# page-cached representation, following each submission check.

				undef $results;

				PageCache::Clear($dbh, {
					FILTER => 'Clinical::P4P::Submission::GetResultData',
				});
			}
		}
	});

	if (
		!$submissionobject
	) {
		return;
	}

	return $submissionobject;
}
Leave a Comment