Skip to content
Open
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
27 changes: 15 additions & 12 deletions src/AmoCRM/Models/LeadModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class LeadModel extends BaseApiModel implements
protected $closestTaskAt;

/**
* @var int
* @var int|float|null
*/
protected $price;

Expand Down Expand Up @@ -252,20 +252,20 @@ public function setName(string $name): self
return $this;
}

/**
* @return null|int
*/
public function getPrice(): ?int
{
return $this->price;
return isset($this->price) ? (int)$this->price : null;
}

public function getPriceWithMinorUnits(): ?float
{
return isset($this->price) ? (float)$this->price : null;
}

/**
* @param null|int $price
*
* @return self
* @param int|float|null $price
*/
public function setPrice(?int $price): self
public function setPrice($price): self
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

нужно добавить проверку на типы внутри метода, если убираем тип

{
$this->price = $price;

Expand Down Expand Up @@ -744,7 +744,9 @@ public static function fromArray(array $lead): self
$leadModel->setName($lead['name']);
}

if (array_key_exists('price', $lead) && !is_null($lead['price'])) {
if (array_key_exists('price_with_minor_units', $lead) && !is_null($lead['price_with_minor_units'])) {
$leadModel->setPrice((float)$lead['price_with_minor_units']);
} elseif (array_key_exists('price', $lead) && !is_null($lead['price'])) {
$leadModel->setPrice((int)$lead['price']);
}

Expand Down Expand Up @@ -861,6 +863,7 @@ public function toArray(): array
$result = [
'name' => $this->getName(),
'price' => $this->getPrice(),
'price_with_minor_units' => $this->getPriceWithMinorUnits(),
'responsible_user_id' => $this->getResponsibleUserId(),
'group_id' => $this->getGroupId(),
'status_id' => $this->getStatusId(),
Expand Down Expand Up @@ -932,8 +935,8 @@ public function toApi(?string $requestId = "0"): array
$result['name'] = $this->getName();
}

if (!is_null($this->getPrice())) {
$result['price'] = $this->getPrice();
if (!is_null($this->getPriceWithMinorUnits())) {
$result['price'] = $this->getPriceWithMinorUnits();
}

if (!is_null($this->getResponsibleUserId())) {
Expand Down
194 changes: 194 additions & 0 deletions tests/Cases/Price/LeadPriceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
<?php

declare(strict_types=1);

namespace Cases\Price;

use AmoCRM\Exceptions\InvalidArgumentException;
use AmoCRM\Models\LeadModel;
use PHPUnit\Framework\TestCase;

class LeadPriceTest extends TestCase
{
public function testSetPriceWithIntegerPreservesLegacyBehaviour(): void
{
$lead = (new LeadModel())->setPrice(100);

$this->assertPriceState($lead, 100, 100.0);
}

public function testSetPriceWithFloatExposesMinorUnitsAndTruncatesLegacyGetter(): void
{
$lead = (new LeadModel())->setPrice(100.5);

$this->assertPriceState($lead, 100, 100.5);
}

public function testSetPriceWithSmallFractionKeepsLegacyPriceAtZero(): void
{
$lead = (new LeadModel())->setPrice(0.1);

$this->assertPriceState($lead, 0, 0.1);
$this->assertSame(0, $lead->toArray()['price']);
$this->assertSame(0.1, $lead->toArray()['price_with_minor_units']);
$this->assertSame(0.1, $lead->toApi()['price']);
}

public function testSetPriceWithLargeFractionDoesNotRoundLegacyPriceUp(): void
{
$lead = (new LeadModel())->setPrice(99999999.999);

$this->assertPriceState($lead, 99999999, 99999999.999);
$this->assertNotSame(100000000, $lead->getPrice());
$this->assertSame(99999999, $lead->toArray()['price']);
$this->assertSame(99999999.999, $lead->toArray()['price_with_minor_units']);
$this->assertSame(99999999.999, $lead->toApi()['price']);
}

public function testSetPriceWithNullLeavesBothRepresentationsNull(): void
{
$lead = (new LeadModel())->setPrice(null);

$this->assertPriceState($lead, null, null);
}

/**
* @throws InvalidArgumentException
*/
public function testFromArrayUsesLegacyPriceWhenOnlyPriceIsProvided(): void
{
$this->assertPriceState(
LeadModel::fromArray(['id' => 1, 'price' => 200]),
200,
200.0
);
}

/**
* @throws InvalidArgumentException
*/
public function testFromArrayUsesMinorUnitsPriceWhenProvided(): void
{
$this->assertPriceState(
LeadModel::fromArray(['id' => 1, 'price_with_minor_units' => 200.75]),
200,
200.75
);
}

/**
* @throws InvalidArgumentException
*/
public function testFromArrayWithSmallFractionKeepsLegacyPriceAtZero(): void
{
$this->assertPriceState(
LeadModel::fromArray(['id' => 1, 'price_with_minor_units' => 0.1]),
0,
0.1
);
}

/**
* @throws InvalidArgumentException
*/
public function testFromArrayWithLargeFractionDoesNotRoundLegacyPriceUp(): void
{
$lead = LeadModel::fromArray([
'id' => 1,
'price_with_minor_units' => 99999999.999,
]);

$this->assertPriceState($lead, 99999999, 99999999.999);
$this->assertNotSame(100000000, $lead->getPrice());
}

/**
* @throws InvalidArgumentException
*/
public function testFromArrayPrefersMinorUnitsOverLegacyPrice(): void
{
$lead = LeadModel::fromArray([
'id' => 1,
'price' => 300,
'price_with_minor_units' => 300.99,
]);

$this->assertPriceState($lead, 300, 300.99);
}

/**
* @throws InvalidArgumentException
*/
public function testFromArrayFallsBackToLegacyPriceWhenMinorUnitsIsNull(): void
{
$lead = LeadModel::fromArray([
'id' => 1,
'price' => 400,
'price_with_minor_units' => null,
]);

$this->assertPriceState($lead, 400, 400.0);
}

public function testToArrayIncludesBothPriceRepresentations(): void
{
$this->assertSame(
[
'name' => null,
'price' => 123,
'price_with_minor_units' => 123.45,
'responsible_user_id' => null,
'group_id' => null,
'status_id' => null,
'pipeline_id' => null,
'loss_reason_id' => null,
'source_id' => null,
'created_by' => null,
'updated_by' => null,
'created_at' => null,
'updated_at' => null,
'closed_at' => null,
'closest_task_at' => null,
'is_deleted' => null,
'custom_fields_values' => null,
'score' => null,
'account_id' => null,
'id' => 1,
],
(new LeadModel())
->setId(1)
->setPrice(123.45)
->toArray()
);
}

public function testToApiUsesMinorUnitsInPriceFieldForFloatInput(): void
{
$this->assertSame(
['price' => 100.5, 'request_id' => '0'],
(new LeadModel())->setPrice(100.5)->toApi()
);
}

public function testToApiUsesNumericPriceFieldForIntegerInput(): void
{
$this->assertSame(
['price' => 100.0, 'request_id' => '0'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

добавь тесты, если строку передадут, массив и тд)

(new LeadModel())->setPrice(100)->toApi()
);
}

public function testToApiOmitsPriceWhenItWasNotSet(): void
{
$this->assertSame(['request_id' => '0'], (new LeadModel())->toApi());
}

private function assertPriceState(LeadModel $lead, ?int $legacyPrice, ?float $priceWithMinorUnits): void
{
$this->assertSame($legacyPrice, $lead->getPrice());

is_null($priceWithMinorUnits)
? $this->assertNull($lead->getPriceWithMinorUnits())
: $this->assertSame($priceWithMinorUnits, $lead->getPriceWithMinorUnits());
}
}