first commit
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\service\pharmacy;
|
||||
|
||||
use Closure;
|
||||
use DomainException;
|
||||
use think\facade\Db;
|
||||
|
||||
final class LockedPharmacySnapshotMutation
|
||||
{
|
||||
/**
|
||||
* @param callable():array<string,mixed> $lockOrder
|
||||
* @param callable(array<string,mixed>):?array<string,mixed> $lockClaim
|
||||
* @param callable(array<string,mixed>,?array<string,mixed>):mixed $mutation
|
||||
*/
|
||||
public static function run(
|
||||
callable $lockOrder,
|
||||
callable $lockClaim,
|
||||
callable $mutation,
|
||||
bool $assertMutable = true
|
||||
): mixed {
|
||||
$order = Closure::fromCallable($lockOrder)();
|
||||
if ($order === []) {
|
||||
throw new DomainException('订单不存在');
|
||||
}
|
||||
$claim = Closure::fromCallable($lockClaim)($order);
|
||||
if ($assertMutable) {
|
||||
PharmacyRemoteSnapshotPolicy::assertMutable($order, $claim);
|
||||
}
|
||||
|
||||
$result = Closure::fromCallable($mutation)($order, $claim);
|
||||
if ($result === false) {
|
||||
throw new DomainException('受保护变更未完成,事务已回滚');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @param callable(array<string,mixed>,?array<string,mixed>):mixed $mutation */
|
||||
public static function execute(
|
||||
int $orderId,
|
||||
callable $mutation,
|
||||
bool $assertMutable = true,
|
||||
int $revision = 1
|
||||
): mixed {
|
||||
return Db::transaction(static fn (): mixed => self::run(
|
||||
static fn (): array => (array) (Db::name('tcm_prescription_order')
|
||||
->where('id', $orderId)
|
||||
->whereNull('delete_time')
|
||||
->lock(true)
|
||||
->find() ?: []),
|
||||
static fn (): ?array => Db::name('pharmacy_submission_claim')
|
||||
->where('prescription_order_id', $orderId)
|
||||
->where('source_revision', max($revision, 1))
|
||||
->lock(true)
|
||||
->find() ?: null,
|
||||
$mutation,
|
||||
$assertMutable
|
||||
));
|
||||
}
|
||||
|
||||
/** @param callable(array<int,array<string,mixed>>):mixed $mutation */
|
||||
public static function executeForPrescription(int $prescriptionId, callable $mutation): mixed
|
||||
{
|
||||
return Db::transaction(static function () use ($prescriptionId, $mutation): mixed {
|
||||
$orders = Db::name('tcm_prescription_order')
|
||||
->where('prescription_id', $prescriptionId)
|
||||
->whereNull('delete_time')
|
||||
->order('id', 'asc')
|
||||
->lock(true)
|
||||
->select()
|
||||
->toArray();
|
||||
foreach ($orders as $order) {
|
||||
$claim = Db::name('pharmacy_submission_claim')
|
||||
->where('prescription_order_id', (int) $order['id'])
|
||||
->where('source_revision', 1)
|
||||
->lock(true)
|
||||
->find();
|
||||
PharmacyRemoteSnapshotPolicy::assertMutable($order, $claim ?: null);
|
||||
}
|
||||
|
||||
$result = Closure::fromCallable($mutation)($orders);
|
||||
if ($result === false) {
|
||||
throw new DomainException('受保护变更未完成,事务已回滚');
|
||||
}
|
||||
|
||||
return $result;
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user