Files
shipping-portal/tests/Feature/Companies/ControllersLogic/UpdateCompanyEInvoiceInfoLogicTest.php
T
2026-04-06 11:26:16 +08:00

319 lines
11 KiB
PHP

<?php
namespace Tests\Feature\Companies\ControllersLogic;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Companies\ControllersLogic\UpdateCompanyEInvoiceInfoLogic;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceInfo;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanPassEInvoicePromptedRule;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Response\RuleEvaluationResult;
use App\Models\Address;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\District;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Mockery;
use Tests\TestCaseChild;
use PHPUnit\Framework\Attributes\Group;
#[Group('feature')]
#[Group('companies')]
#[Group('controllers_logic')]
#[Group('ok_to_run')]
class UpdateCompanyEInvoiceInfoLogicTest extends TestCaseChild
{
protected const TIN = '123456789';
protected const MSIC_CODE = '12345';
protected $canCreateAddressMock;
protected $fetchesDistrictMock;
protected $fetchesCompanyModuleMock;
protected $createsAddressMock;
protected $ruleEvaluatorMock;
protected $updatesCompanyEInvoiceInfoMock;
protected $canPassEInvoicePromptedRuleMock;
protected $updateCompanyEInvoiceInfoLogic;
public function setUp(): void
{
parent::setUp();
$this->canCreateAddressMock = Mockery::mock(CanCreateAddress::class);
$this->fetchesDistrictMock = Mockery::mock(FetchesDistrict::class);
$this->fetchesCompanyModuleMock = Mockery::mock(FetchesCompanyModule::class);
$this->createsAddressMock = Mockery::mock(CreatesAddress::class);
$this->ruleEvaluatorMock = Mockery::mock(RuleEvaluator::class);
$this->updatesCompanyEInvoiceInfoMock = Mockery::mock(UpdatesCompanyEInvoiceInfo::class);
$this->canPassEInvoicePromptedRuleMock = Mockery::mock(CanPassEInvoicePromptedRule::class);
$this->updateCompanyEInvoiceInfoLogic = new UpdateCompanyEInvoiceInfoLogic(
$this->canCreateAddressMock,
$this->fetchesDistrictMock,
$this->fetchesCompanyModuleMock,
$this->createsAddressMock,
$this->ruleEvaluatorMock,
$this->updatesCompanyEInvoiceInfoMock,
$this->canPassEInvoicePromptedRuleMock
);
}
public function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
public function test_logic_successfully_updates_einvoice_info_with_new_billing_address()
{
// A R R A N G E
$requestData = [
'tin' => self::TIN,
'msic_code' => self::MSIC_CODE,
'district_id' => 1,
'state_id' => 1,
'company_module_id' => 1,
'street_one' => '123 Main Street',
'street_two' => 'Suite 100',
'post_code' => '50000',
];
$mockDistrict = Mockery::mock(District::class)->makePartial();
$mockDistrict->id = 1;
$mockDistrict->country_id = 1;
$mockCompany = Mockery::mock(Company::class)->makePartial();
$mockCompany->id = 1;
$mockCompanyModule = Mockery::mock(CompanyModule::class)->makePartial();
$mockCompanyModule->id = 1;
$mockCompanyModule->company = $mockCompany;
// Mock addresses collection with no billing address
$addressesCollection = new Collection([]);
$mockCompanyModule->addresses = $addressesCollection;
// Mock rule evaluation - success
$this->ruleEvaluatorMock->shouldReceive('evaluate')
->once()
->andReturn(new RuleEvaluationResult(true, []));
$this->fetchesDistrictMock->shouldReceive('execute')
->once()
->with(['id' => 1])
->andReturn($mockDistrict);
$this->canCreateAddressMock->shouldReceive('passes')
->once() // Only once for E-Invoice address, not for billing address
->with(Mockery::type(AddressObject::class))
->andReturn(true);
//CompanyModule for checking billing address
$this->fetchesCompanyModuleMock->shouldReceive('execute')
->once()
->with(['id' => 1])
->andReturn($mockCompanyModule);
$this->createsAddressMock->shouldReceive('execute')
->twice() // Once for E-Invoice address, once for billing address
->andReturn(Mockery::mock(Address::class));
//Update tin, msic code
$this->updatesCompanyEInvoiceInfoMock->shouldReceive('execute')
->once()
->with($mockCompany, self::TIN, self::MSIC_CODE)
->andReturn($mockCompany);
$request = Request::create('/company/einvoice', 'POST', $requestData);
// A C T
$response = $this->updateCompanyEInvoiceInfoLogic->logic($request);
// A S S E R T
$this->assertInstanceOf(JsonResponse::class, $response);
$this->assertEquals(200, $response->getStatusCode());
}
public function test_logic_successfully_updates_einvoice_info_with_existing_billing_address()
{
// A R R A N G E
$requestData = [
'tin' => self::TIN,
'msic_code' => self::MSIC_CODE,
'district_id' => 2,
'state_id' => 2,
'company_module_id' => 2,
'street_one' => '456 Second Street',
'street_two' => 'Floor 2',
'post_code' => '60000',
];
$mockDistrict = Mockery::mock(District::class)->makePartial();
$mockDistrict->id = 2;
$mockDistrict->country_id = 1;
$mockCompany = Mockery::mock(Company::class)->makePartial();
$mockCompany->id = 2;
$mockBillingAddress = Mockery::mock(Address::class)->makePartial();
$mockBillingAddress->id = 1;
$mockBillingAddress->type = AddressType::BILLING;
$mockBillingAddress->status = ApprovalStatus::APPROVED;
$mockCompanyModule = Mockery::mock(CompanyModule::class)->makePartial();
$mockCompanyModule->id = 2;
$mockCompanyModule->company = $mockCompany;
// Mock addresses collection with existing billing address
$addressesCollection = new Collection([$mockBillingAddress]);
$mockCompanyModule->addresses = $addressesCollection;
// Mock rule evaluation - success
$this->ruleEvaluatorMock->shouldReceive('evaluate')
->once()
->andReturn(new RuleEvaluationResult(true, []));
$this->fetchesDistrictMock->shouldReceive('execute')
->once()
->with(['id' => 2])
->andReturn($mockDistrict);
$this->canCreateAddressMock->shouldReceive('passes')
->once() // Only once for E-Invoice address, not for billing
->with(Mockery::type(AddressObject::class))
->andReturn(true);
$this->fetchesCompanyModuleMock->shouldReceive('execute')
->once()
->with(['id' => 2])
->andReturn($mockCompanyModule);
$this->createsAddressMock->shouldReceive('execute')
->once() // Only once for E-Invoice address
->andReturn(Mockery::mock(Address::class));
//Update tin, msic code
$this->updatesCompanyEInvoiceInfoMock->shouldReceive('execute')
->once()
->with($mockCompany, self::TIN, self::MSIC_CODE)
->andReturn($mockCompany);
$request = Request::create('/company/einvoice', 'POST', $requestData);
// A C T
$response = $this->updateCompanyEInvoiceInfoLogic->logic($request);
// A S S E R T
$this->assertInstanceOf(JsonResponse::class, $response);
$this->assertEquals(200, $response->getStatusCode());
}
public function test_logic_throws_exception_when_rule_evaluation_fails()
{
// A R R A N G E
$requestData = [
'tin' => 'invalid',
'msic_code' => 'invalid',
'district_id' => 1,
'state_id' => 1,
'company_module_id' => 1,
'street_one' => 'Test Street',
'street_two' => '',
'post_code' => '12345',
];
// Mock rule evaluation - failure
$this->ruleEvaluatorMock->shouldReceive('evaluate')
->once()
->andReturn(new RuleEvaluationResult(false, ['Invalid TIN format', 'Invalid MSIC code']));
$request = Request::create('/company/einvoice', 'POST', $requestData);
// A S S E R T
$this->expectException(CriteriaNotFulfilledException::class);
$this->expectExceptionMessage('- Invalid TIN format<br>- Invalid MSIC code');
// A C T
$this->updateCompanyEInvoiceInfoLogic->logic($request);
}
public function test_logic_validates_address_creation()
{
// A R R A N G E
$requestData = [
'tin' => self::TIN,
'msic_code' => self::MSIC_CODE,
'district_id' => 3,
'state_id' => 3,
'company_module_id' => 3,
'street_one' => '789 Third Avenue',
'street_two' => 'Unit 5',
'post_code' => '70000',
];
$mockDistrict = Mockery::mock(District::class)->makePartial();
$mockDistrict->id = 3;
$mockDistrict->country_id = 1;
$mockCompany = Mockery::mock(Company::class)->makePartial();
$mockCompany->id = 3;
$mockCompanyModule = Mockery::mock(CompanyModule::class)->makePartial();
$mockCompanyModule->id = 3;
$mockCompanyModule->company = $mockCompany;
// Mock addresses collection with no billing address
$addressesCollection = new Collection([]);
$mockCompanyModule->addresses = $addressesCollection;
// Mock rule evaluation - success
$this->ruleEvaluatorMock->shouldReceive('evaluate')
->once()
->andReturn(new RuleEvaluationResult(true, []));
$this->fetchesDistrictMock->shouldReceive('execute')
->once()
->with(['id' => 3])
->andReturn($mockDistrict);
// Verify that passes() is called with AddressObject
$this->canCreateAddressMock->shouldReceive('passes')
->once() // Only once for E-Invoice address, not for billing address
->with(Mockery::type(AddressObject::class))
->andReturn(true);
$this->fetchesCompanyModuleMock->shouldReceive('execute')
->once()
->with(['id' => 3])
->andReturn($mockCompanyModule);
$this->createsAddressMock->shouldReceive('execute')
->twice()
->andReturn(Mockery::mock(Address::class));
//Update tin, msic code
$this->updatesCompanyEInvoiceInfoMock->shouldReceive('execute')
->once()
->with($mockCompany, self::TIN, self::MSIC_CODE)
->andReturn($mockCompany);
$request = Request::create('/company/einvoice', 'POST', $requestData);
// A C T
$response = $this->updateCompanyEInvoiceInfoLogic->logic($request);
// A S S E R T
$this->assertInstanceOf(JsonResponse::class, $response);
}
}