feat(migrations): add ownership fields to doctors table for IRIMC import

- Introduced new columns: owner_status, source, source_ref, managed_by, and claimed_at to the doctors table.
- Created indexes for owner_status and source to optimize queries related to unclaimed doctors.

feat(auth): implement SystemOwnerCommand for managing system-owner user

- Added command to create, activate, and deactivate a system-owner user for IRIMC crawler.
- Ensured the user has ROLE_ADMIN to access import endpoints.
- Handled password setting and user status management within the command.
This commit is contained in:
hamed
2026-07-11 08:59:36 +03:30
parent f30bf5dfbd
commit 9f56f4aa08
28 changed files with 3694 additions and 989 deletions
+84
View File
@@ -77,6 +77,26 @@ class Doctor
#[ORM\Column(name: 'notification_mobile', type: 'string', length: 15, nullable: true)]
private ?string $notificationMobile = null;
// ── Profile ownership (IRIMC import) ───────────────────────────────────────
// owner_status: claimed | unclaimed | pending_transfer
#[ORM\Column(name: 'owner_status', type: 'string', length: 20)]
private string $ownerStatus = 'claimed';
// source: manual | irimc
#[ORM\Column(type: 'string', length: 20)]
private string $source = 'manual';
// شناسه رکورد مبدأ (profile_url یا کد نظام پزشکی) برای idempotency و ممیزی
#[ORM\Column(name: 'source_ref', type: 'string', length: 100, nullable: true)]
private ?string $sourceRef = null;
// شناسه کاربری که این پروفایلِ بدون‌مالک را وارد/مدیریت کرده (مثلاً کاربر سیستمی)
#[ORM\Column(name: 'managed_by', type: 'integer', nullable: true)]
private ?int $managedBy = null;
#[ORM\Column(name: 'claimed_at', type: 'integer', nullable: true)]
private ?int $claimedAt = null;
#[ORM\Column(name: 'created_at', type: 'integer')]
private int $createdAt;
@@ -200,6 +220,26 @@ class Doctor
{
return $this->notificationMobile;
}
public function getOwnerStatus(): string
{
return $this->ownerStatus;
}
public function getSource(): string
{
return $this->source;
}
public function getSourceRef(): ?string
{
return $this->sourceRef;
}
public function getManagedBy(): ?int
{
return $this->managedBy;
}
public function getClaimedAt(): ?int
{
return $this->claimedAt;
}
public function getCreatedAt(): int
{
return $this->createdAt;
@@ -312,6 +352,50 @@ class Doctor
$this->touch();
return $this;
}
public function setOwnerStatus(string $v): self
{
$this->ownerStatus = $v;
$this->touch();
return $this;
}
public function setSource(string $v): self
{
$this->source = $v;
$this->touch();
return $this;
}
public function setSourceRef(?string $v): self
{
$this->sourceRef = $v;
$this->touch();
return $this;
}
public function setManagedBy(?int $v): self
{
$this->managedBy = $v;
$this->touch();
return $this;
}
public function setClaimedAt(?int $v): self
{
$this->claimedAt = $v;
$this->touch();
return $this;
}
/**
* انتقال مالکیت پروفایلِ بدون‌مالک به کاربر واقعی پزشک.
* user_id را پر می‌کند، مدیریت سیستمی را برمی‌دارد و وضعیت را claimed می‌کند.
*/
public function transferOwnershipTo(User $user): self
{
$this->user = $user;
$this->managedBy = null;
$this->ownerStatus = 'claimed';
$this->claimedAt = time();
$this->touch();
return $this;
}
private function touch(): void
{