feat(invoice): 添加创建发票功能

- 新增 CreateInvoiceCmd 类作为创建发票的命令对象
- 创建 Address 类表示发票地址信息
- 实现 Invoice 类作为发票的领域模型
- 添加 InvoiceRepoInterface 接口和 InvoiceRepo 实现类,用于处理发票创建逻辑
- 编写 CreateInvoiceTest测试用例验证发票创建功能
This commit is contained in:
李东云
2025-08-29 01:42:10 +08:00
parent 66a468e702
commit b3317c5f8d
7 changed files with 281 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
<?php
/**
* CreateInvoiceCmd.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/29
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Application\Command;
final readonly class CreateInvoiceCmd {
public function __construct(
public string $uid,
public string $caseId,
public bool $setFreqInvAddr,
public string $receiver,
public string $patientName,
public string $address,
public string $city,
public string $state,
public string $country,
public string $zipCode,
) {}
}

View File

@@ -9,11 +9,13 @@ use Hyperf\Framework\Logger\StdoutLogger;
use Singularity\HDK\Pay\Domain\Account\Repository\AccountRepoInterface;
use Singularity\HDK\Pay\Domain\Account\Repository\PointLogRepoInterface;
use Singularity\HDK\Pay\Domain\Invoice\Repository\InvoiceProductRepoInterface;
use Singularity\HDK\Pay\Domain\Invoice\Repository\InvoiceRepoInterface;
use Singularity\HDK\Pay\Domain\Product\Repository\ExchangeRepoInterface;
use Singularity\HDK\Pay\Domain\Product\Repository\RechargeProductRepoInterface;
use Singularity\HDK\Pay\Domain\Transaction\Repository\OrderRepoInterface;
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\InvoiceProductRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\InvoiceRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\OrderRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\PointLogRepo;
use Singularity\HDK\Pay\Infrastructure\Repository\ProductRepo;
@@ -48,6 +50,7 @@ class ConfigProvider
// invoice
InvoiceProductRepoInterface::class => InvoiceProductRepo::class,
InvoiceRepoInterface::class => InvoiceRepo::class,
],
// 合并到 config/autoload/annotations.php 文件
'annotations' => [

View File

@@ -0,0 +1,82 @@
<?php
/**
* InvoiceDto.php@LuxPay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/28
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Domain\Invoice\Aggregate;
use Singularity\HDK\Pay\Domain\AggregateRoot;
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\ValueObject\Address;
final class Invoice extends AggregateRoot
{
public function __construct(
private readonly string $invoiceNo,
private readonly string $uid,
private readonly string $caseId,
private readonly Address $address,
private readonly bool $setFreqInvAddr,
private readonly string $receiver,
) {}
public function getInvoiceNo(): string
{
return $this->invoiceNo;
}
public function getUid(): string
{
return $this->uid;
}
public function getCaseId(): string
{
return $this->caseId;
}
public function isSetFreqInvAddr(): bool
{
return $this->setFreqInvAddr;
}
public function getReceiver(): string
{
return $this->receiver;
}
public function getPatientName(): string
{
return $this->address->getPatientName();
}
public function getAddress(): string
{
return $this->address->getAddress();
}
public function getCity(): string
{
return $this->address->getCity();
}
public function getState(): string
{
return $this->address->getState();
}
public function getCountry(): string
{
return $this->address->getCountry();
}
public function getZipCode(): string
{
return $this->address->getZipCode();
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Address.php@LuxPay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/28
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Domain\Invoice\Aggregate\ValueObject;
final readonly class Address {
public function __construct(
private string $patientName,
private string $address,
private string $city,
private string $state,
private string $country,
private string $zipCode,
) {}
public function getPatientName(): string
{
return $this->patientName;
}
public function getAddress(): string
{
return $this->address;
}
public function getCity(): string
{
return $this->city;
}
public function getState(): string
{
return $this->state;
}
public function getCountry(): string
{
return $this->country;
}
public function getZipCode(): string
{
return $this->zipCode;
}
}

View File

@@ -0,0 +1,22 @@
<?php
/**
* InvoiceRepoInterface.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/29
*/
namespace Singularity\HDK\Pay\Domain\Invoice\Repository;
use Singularity\HDK\Pay\Application\Command\CreateInvoiceCmd;
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice;
interface InvoiceRepoInterface
{
/**
* @param CreateInvoiceCmd $cmd
* @return Invoice
*/
public function create(CreateInvoiceCmd $cmd): Invoice;
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* InvoiceRepo.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/29
*/
declare(strict_types=1);
namespace Singularity\HDK\Pay\Infrastructure\Repository;
use Hyperf\Codec\Json;
use Singularity\HDK\Pay\Application\Command\CreateInvoiceCmd;
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice;
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\ValueObject\Address;
use Singularity\HDK\Pay\Domain\Invoice\Repository\InvoiceRepoInterface;
final class InvoiceRepo extends AbstractRepo implements InvoiceRepoInterface
{
public function create(CreateInvoiceCmd $cmd): Invoice
{
$response = $this->requestService->requestPost(
url: "/rpc/v2/account/$cmd->uid/logs/points/$cmd->caseId/invoices",
data: [
'set_freq_addr' => $cmd->setFreqInvAddr,
'receiver' => $cmd->receiver,
'patient_name' => $cmd->patientName,
'address' => $cmd->address,
'city' => $cmd->city,
'state' => $cmd->state,
'country' => $cmd->country,
'zip' => $cmd->zipCode,
],
);
$content = $response->getBody()->getContents();
$result = Json::decode($content);
return new Invoice(
invoiceNo: $result['invoice_no'],
uid: $result['uid'],
caseId: $result['case_id'],
address: new Address(
patientName: $result['patient_name'],
address: $result['address'],
city: $result['city'],
state: $result['state'],
country: $result['country'],
zipCode: $result['zip'],
),
setFreqInvAddr: $result['set_freq_addr'],
receiver: $result['receiver'],
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* CreateInvoiceTest.php@Pay
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2025/8/29
*/
use Singularity\HDK\Pay\Application\Command\CreateInvoiceCmd;
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice;
use Singularity\HDK\Pay\Infrastructure\Repository\InvoiceRepo;
use function Hyperf\Support\make;
it('should can create invoice', function () {
$repo = make(InvoiceRepo::class);
$invoice = $repo->create(
new CreateInvoiceCmd(
uid: '61dbe752d4caa',
caseId: '68affb136c01d',
setFreqInvAddr: true,
receiver: "dongyun.li@luxcreo.ai",
patientName: "Ms. Jennifer Durgan",
address: "12345 Magnolia Boulevard NortheastApartment 5678 Suite 910",
city: "Springfield",
state: "Illinois",
country: "United States",
zipCode: "67890-1234",
),
);
expect($invoice)
->toBeInstanceOf(Invoice::class);
});