Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/Traits/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,39 @@ public function bulkCreateContacts(array $data = [], string $version = 'v1'): mi
return $this->execute();
}

/**
* Bulk creates or updates contacts, with their nested records, for a specified API version.
*
* Each contact is identified by its `contact_number`: one the platform does not hold is
* created, one it holds is updated. Nested products and bank accounts are matched by `id`,
* then by the caller's own `local_identifier` scoped to that contact, and created when
* neither matches — which is what makes this usable before the caller knows any platform
* ids at all. `bulkUpdateContact` cannot do that: it skips any nested record with no `id`.
*
* A product may name a bank account created in the same request through
* `contact_bank_account_local_identifier`, since that account has no id yet.
*
* @param array $data (Optional) An associative array with a `contacts` key holding the contacts
* to upsert. Keys and values match the contact model's attributes.
* @param string $version (Optional) The version of the API to target. Defaults to 'v1'.
* @return mixed The response from the API, shaped as `success` and `errors` keyed by the index
* each contact was sent at — the same shape the other bulk endpoints return.
*
* @throws \Exception
*/
public function bulkUpsertContacts(array $data = [], string $version = 'v1'): mixed
{
$this->init();
$this->setVersion($version);
$this->setData([
'json' => $data,
]);
$this->setEndpoint('contacts/bulkUpsert');
$this->setRequestType('PUT');

return $this->execute();
}

/**
* Retrieves the allowed statuses for contacts.
*
Expand Down
37 changes: 37 additions & 0 deletions tests/Traits/ContactTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,43 @@
expect($result)->toBe($expectedResult);
});

test('bulkUpsertContacts calls expected methods and returns result', function () {
$mock = $this->getMockBuilder(PaymentPlatformAPI::class)
->onlyMethods(['init', 'setVersion', 'setData', 'setEndpoint', 'setRequestType', 'execute'])
->getMock();

$data = ['contacts' => [['contact_number' => '0000000005012']]];
$version = 'v3.0';

$mock->expects($this->once())->method('init')->willReturnSelf();
$mock->expects($this->once())->method('setVersion')->with($version)->willReturnSelf();
$mock->expects($this->once())->method('setData')->with(['json' => $data])->willReturnSelf();
$mock->expects($this->once())->method('setEndpoint')->with('contacts/bulkUpsert')->willReturnSelf();
// PUT, not POST: an upsert is idempotent, so it matches bulkUpdate rather than bulkCreate.
$mock->expects($this->once())->method('setRequestType')->with('PUT')->willReturnSelf();

$expectedResult = 'upsert-contacts-result';
$mock->expects($this->once())->method('execute')->willReturn($expectedResult);

$result = $mock->bulkUpsertContacts($data, $version);
expect($result)->toBe($expectedResult);
});

test('bulkUpsertContacts defaults to v1', function () {
$mock = $this->getMockBuilder(PaymentPlatformAPI::class)
->onlyMethods(['init', 'setVersion', 'setData', 'setEndpoint', 'setRequestType', 'execute'])
->getMock();

$mock->expects($this->once())->method('setVersion')->with('v1')->willReturnSelf();
$mock->method('init')->willReturnSelf();
$mock->method('setData')->willReturnSelf();
$mock->method('setEndpoint')->willReturnSelf();
$mock->method('setRequestType')->willReturnSelf();
$mock->method('execute')->willReturn(null);

$mock->bulkUpsertContacts([]);
});

test('createContact calls expected methods and returns result', function () {
$mock = $this->getMockBuilder(PaymentPlatformAPI::class)
->onlyMethods(['init', 'setVersion', 'setData', 'setEndpoint', 'setRequestType', 'execute'])
Expand Down
Loading