Skip to content

Commit 4a69e57

Browse files
committed
fix(registration): vet question eligibility before ambiguous-column skip on ticket import
1 parent 970b38a commit 4a69e57

2 files changed

Lines changed: 93 additions & 34 deletions

File tree

app/Services/Model/Imp/SummitOrderService.php

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4785,28 +4785,20 @@ private function resolveExtraQuestionColumns(Summit $summit, SummitAttendee $att
47854785
}
47864786

47874787
// match by name and by label ( the ticket csv export emits question labels as
4788-
// column names ); when the two lookups disagree the column is ambiguous — one
4789-
// question's name is another question's label — skip it rather than silently
4790-
// filing the answer under the wrong question
4791-
$question = $summit->getOrderExtraQuestionByName($question_name);
4792-
$question_by_label = $summit->getOrderExtraQuestionByLabel($question_name);
4793-
if (!is_null($question) && !is_null($question_by_label) && $question_by_label->getId() !== $question->getId()) {
4794-
Log::warning
4795-
(
4796-
sprintf
4797-
(
4798-
"SummitOrderService::resolveExtraQuestionColumns column %s is ambiguous on summit %s ( name of question %s, label of question %s ), skipping it",
4799-
$question_name,
4800-
$summit->getId(),
4801-
$question->getId(),
4802-
$question_by_label->getId()
4803-
)
4804-
);
4805-
continue;
4806-
}
4807-
if (is_null($question))
4808-
$question = $question_by_label;
4809-
if (is_null($question)) {
4788+
// column names ); each candidate is vetted for usage / attendee eligibility
4789+
// before deciding ambiguity, so a question that could never take this answer
4790+
// ( order scoped or not allowed for the attendee ) can not shadow a legitimate
4791+
// match; only when two eligible questions remain — one question's name is
4792+
// another question's label — is the column truly ambiguous and skipped, rather
4793+
// than silently filing the answer under the wrong question
4794+
$candidates = [];
4795+
foreach ([$summit->getOrderExtraQuestionByName($question_name),
4796+
$summit->getOrderExtraQuestionByLabel($question_name)] as $candidate) {
4797+
if (is_null($candidate)) continue;
4798+
$candidates[$candidate->getId()] = $candidate;
4799+
}
4800+
4801+
if (count($candidates) === 0) {
48104802
Log::warning
48114803
(
48124804
sprintf
@@ -4819,31 +4811,55 @@ private function resolveExtraQuestionColumns(Summit $summit, SummitAttendee $att
48194811
continue;
48204812
}
48214813

4822-
if ($question->getUsage() === SummitOrderExtraQuestionTypeConstants::OrderQuestionUsage) {
4823-
Log::warning
4824-
(
4825-
sprintf
4814+
$eligible = [];
4815+
foreach ($candidates as $candidate) {
4816+
if ($candidate->getUsage() === SummitOrderExtraQuestionTypeConstants::OrderQuestionUsage) {
4817+
Log::warning
48264818
(
4827-
"SummitOrderService::resolveExtraQuestionColumns question %s is order scoped, can not be answered per attendee, skipping it",
4828-
$question_name
4829-
)
4830-
);
4831-
continue;
4819+
sprintf
4820+
(
4821+
"SummitOrderService::resolveExtraQuestionColumns question %s ( column %s ) is order scoped, can not be answered per attendee, skipping it",
4822+
$candidate->getId(),
4823+
$question_name
4824+
)
4825+
);
4826+
continue;
4827+
}
4828+
if (!$attendee->isAllowedQuestion($candidate)) {
4829+
Log::warning
4830+
(
4831+
sprintf
4832+
(
4833+
"SummitOrderService::resolveExtraQuestionColumns question %s ( column %s ) is not allowed for attendee %s, skipping it",
4834+
$candidate->getId(),
4835+
$question_name,
4836+
$attendee->getEmail()
4837+
)
4838+
);
4839+
continue;
4840+
}
4841+
$eligible[$candidate->getId()] = $candidate;
48324842
}
48334843

4834-
if (!$attendee->isAllowedQuestion($question)) {
4844+
if (count($eligible) === 0) continue;
4845+
4846+
if (count($eligible) > 1) {
48354847
Log::warning
48364848
(
48374849
sprintf
48384850
(
4839-
"SummitOrderService::resolveExtraQuestionColumns question %s is not allowed for attendee %s, skipping it",
4851+
"SummitOrderService::resolveExtraQuestionColumns column %s is ambiguous on summit %s ( name of question %s, label of question %s ), skipping it",
48404852
$question_name,
4841-
$attendee->getEmail()
4853+
$summit->getId(),
4854+
array_keys($eligible)[0],
4855+
array_keys($eligible)[1]
48424856
)
48434857
);
48444858
continue;
48454859
}
48464860

4861+
$question = reset($eligible);
4862+
48474863
if ($question->allowsValues()) {
48484864
$value = $this->resolveListQuestionValue($question, $value);
48494865
if (is_null($value)) continue;

tests/SummitOrderServiceTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,49 @@ public function testImportTicketDataSkipsAmbiguousExtraQuestionColumn()
993993
$this->assertCount(0, $attendee->getExtraQuestionAnswers());
994994
}
995995

996+
public function testImportTicketDataIneligibleQuestionDoesNotMakeColumnAmbiguous()
997+
{
998+
Queue::fake();
999+
1000+
// question A's NAME equals question B's LABEL, but B is order scoped so it was
1001+
// never a real candidate — the column must resolve to A, not be skipped as
1002+
// ambiguous ( ambiguity is decided among eligible questions only )
1003+
$question_a = $this->insertOrderExtraQuestion
1004+
(
1005+
'Shirt',
1006+
ExtraQuestionTypeConstants::TextQuestionType,
1007+
[],
1008+
SummitOrderExtraQuestionTypeConstants::TicketQuestionUsage,
1009+
'Question A Label'
1010+
);
1011+
$question_b = $this->insertOrderExtraQuestion
1012+
(
1013+
'B_INTERNAL_NAME',
1014+
ExtraQuestionTypeConstants::TextQuestionType,
1015+
[],
1016+
SummitOrderExtraQuestionTypeConstants::OrderQuestionUsage,
1017+
'Shirt'
1018+
);
1019+
1020+
$ticket = $this->getUnassignedTicket();
1021+
1022+
$csv_content = <<<CSV
1023+
number,attendee_email,attendee_first_name,attendee_last_name,extra_question:Shirt
1024+
{$ticket->getNumber()},new.attendee@nowhere.com,New,Attendee,Large
1025+
CSV;
1026+
1027+
$service = $this->buildTicketDataImportService($csv_content);
1028+
$service->processTicketData(self::$summit->getId(), 'tickets.csv');
1029+
1030+
$attendee = App::make(ISummitAttendeeRepository::class)
1031+
->getBySummitAndEmail(self::$summit, 'new.attendee@nowhere.com');
1032+
$this->assertNotNull($attendee);
1033+
$answer = $attendee->getExtraQuestionAnswerByQuestion($question_a);
1034+
$this->assertNotNull($answer);
1035+
$this->assertEquals('Large', $answer->getValue());
1036+
$this->assertNull($attendee->getExtraQuestionAnswerByQuestion($question_b));
1037+
}
1038+
9961039
public function testTicketCSVExportMultiValueAnswerRoundTripsThroughImport()
9971040
{
9981041
Queue::fake();

0 commit comments

Comments
 (0)