311 lines
10 KiB
PHP
311 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Enums\ApprovalStatus;
|
|
use App\Enums\CooperationStatus;
|
|
use App\Models\Cooperation;
|
|
use App\Models\CooperationProposal;
|
|
use App\Models\PartnerMedia;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
|
|
class MigrateMediaCooperationCommand extends Command
|
|
{
|
|
/**
|
|
* The name and signature of the console command.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $signature = 'migrate:media-cooperation';
|
|
|
|
/**
|
|
* The console command description.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $description = 'Migrate media_cooperation from legacy database → cooperations and cooperation_proposals';
|
|
|
|
/**
|
|
* Cache for migrated cooperation titles to avoid redundant processing.
|
|
*/
|
|
private array $migratedTitles = [];
|
|
|
|
/**
|
|
* Cache for proposal media to avoid re-importing files.
|
|
*/
|
|
private array $migratedProposalIds = [];
|
|
|
|
/**
|
|
* Cache for User ID to Partner Media ID mapping.
|
|
*/
|
|
private array $userToMediaMap = [];
|
|
|
|
/**
|
|
* Execute the console command.
|
|
*/
|
|
public function handle(): void
|
|
{
|
|
$this->info('Starting migration: media_cooperation → cooperations...');
|
|
|
|
$legacyConn = DB::connection('mysql_second');
|
|
$query = $legacyConn->table('media_cooperation')->whereNull('deleted_at');
|
|
|
|
try {
|
|
$totalCount = $query->count();
|
|
} catch (\Exception $e) {
|
|
$this->error('Table media_cooperation not found or error accessing legacy database.');
|
|
$this->error($e->getMessage());
|
|
|
|
return;
|
|
}
|
|
|
|
if ($totalCount === 0) {
|
|
$this->warn('No media_cooperation found in legacy database.');
|
|
|
|
return;
|
|
}
|
|
|
|
$this->info("Found {$totalCount} legacy media_cooperation records.");
|
|
|
|
// Pre-cache migrated cooperation titles
|
|
$this->migratedTitles = DB::table('cooperations')
|
|
->pluck('title')
|
|
->map(fn ($t) => strtolower(trim($t)))
|
|
->flip()
|
|
->all();
|
|
|
|
// Pre-cache proposal media
|
|
$this->migratedProposalIds = DB::table('media')
|
|
->where('model_type', CooperationProposal::class)
|
|
->where('collection_name', 'proposals')
|
|
->pluck('model_id')
|
|
->flip()
|
|
->all();
|
|
|
|
// Pre-load User to Partner Media mapping
|
|
$this->loadUserToMediaMap();
|
|
|
|
// Load all records and group by name
|
|
$all = $query->orderBy('id')->get();
|
|
$groups = $all->groupBy(fn ($item) => strtolower(trim($item->name)));
|
|
|
|
$this->info("Grouped into {$groups->count()} unique cooperation group(s).");
|
|
|
|
foreach ($groups as $groupKey => $group) {
|
|
$this->processGroup($groupKey, $group);
|
|
}
|
|
|
|
$this->newLine();
|
|
$this->info('media_cooperation migration completed successfully!');
|
|
}
|
|
|
|
/**
|
|
* Load mapping from User ID to Partner Media ID.
|
|
* Path: User -> Company -> PartnerMedia
|
|
*/
|
|
private function loadUserToMediaMap(): void
|
|
{
|
|
$this->userToMediaMap = DB::table('partner_media')
|
|
->join('companies', 'partner_media.company_id', '=', 'companies.id')
|
|
->whereNotNull('companies.user_id')
|
|
->pluck('partner_media.id', 'companies.user_id')
|
|
->all();
|
|
}
|
|
|
|
/**
|
|
* Process a single group of media_cooperation records.
|
|
*/
|
|
private function processGroup(string $groupKey, Collection $group): void
|
|
{
|
|
$first = $group->first();
|
|
$label = Str::limit($first->name, 40);
|
|
$this->output->write("<info>[group]</info> Processing: <comment>{$label}</comment>... ");
|
|
|
|
try {
|
|
// Check if cooperation already exists by title
|
|
$existingCooperation = DB::table('cooperations')
|
|
->whereRaw('LOWER(TRIM(title)) = ?', [$groupKey])
|
|
->first();
|
|
|
|
if ($existingCooperation) {
|
|
$cooperationId = $existingCooperation->id;
|
|
$this->output->write('<info>JOINING EXISTING</info>... ');
|
|
} else {
|
|
$cooperationId = $this->insertCooperation(
|
|
name: $first->name,
|
|
description: $first->description,
|
|
initialDate: $group->min('begin'),
|
|
finalDate: $group->max('end'),
|
|
status: CooperationStatus::COMPLETED->value,
|
|
);
|
|
$this->output->write('<info>CREATED NEW</info>... ');
|
|
}
|
|
|
|
// Optional: insert cooperation_media if the legacy table has a 'media' column with IDs
|
|
if (isset($first->media)) {
|
|
$this->insertCooperationMedia($group, $cooperationId);
|
|
}
|
|
|
|
// Migrate proposals belonging to this group's media_cooperation
|
|
$this->migrateProposals(
|
|
group: $group,
|
|
cooperationId: $cooperationId
|
|
);
|
|
|
|
$this->output->writeln('<info>DONE</info>');
|
|
} catch (\Exception $e) {
|
|
$this->output->writeln('<error>FAILED: '.$e->getMessage().'</error>');
|
|
}
|
|
}
|
|
|
|
private function insertCooperation(
|
|
string $name,
|
|
?string $description,
|
|
?string $initialDate,
|
|
?string $finalDate,
|
|
string $status
|
|
): int {
|
|
DB::table('cooperations')->insert([
|
|
'title' => $name,
|
|
'initial_submission_date' => $initialDate,
|
|
'final_submission_date' => $finalDate,
|
|
'description' => $description ?? '',
|
|
'status' => $status,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
return (int) DB::getPdo()->lastInsertId();
|
|
}
|
|
|
|
private function insertCooperationMedia(Collection $group, int $cooperationId): void
|
|
{
|
|
$validMediaIds = DB::table('partner_media')->pluck('id')->toArray();
|
|
$mediaStatusMap = [];
|
|
|
|
foreach ($group as $item) {
|
|
if (empty($item->media)) {
|
|
continue;
|
|
}
|
|
|
|
$ids = array_map('trim', explode(',', $item->media));
|
|
$statuses = array_map('trim', explode(',', $item->status ?? ''));
|
|
|
|
foreach ($ids as $index => $rawId) {
|
|
$mediaId = (int) $rawId;
|
|
if (! in_array($mediaId, $validMediaIds)) {
|
|
continue;
|
|
}
|
|
|
|
$legacyStatus = $statuses[$index] ?? '1';
|
|
$mediaStatusMap[$mediaId] = $this->mapApprovalStatus($legacyStatus);
|
|
}
|
|
}
|
|
|
|
foreach ($mediaStatusMap as $mediaId => $approvalStatus) {
|
|
DB::table('cooperation_media')->insert([
|
|
'cooperation_id' => $cooperationId,
|
|
'partner_media_id' => $mediaId,
|
|
'status' => $approvalStatus,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function migrateProposals(Collection $group, int $cooperationId): void
|
|
{
|
|
$legacyConn = DB::connection('mysql_second');
|
|
$legacyIds = $group->pluck('id')->toArray();
|
|
|
|
$legacyProposals = $legacyConn->table('propose_media_cooperation')
|
|
->whereIn('media_cooperation_id', $legacyIds)
|
|
->whereNull('deleted_at')
|
|
->get();
|
|
|
|
foreach ($legacyProposals as $legacyProposal) {
|
|
$this->processProposal($legacyProposal, $cooperationId);
|
|
}
|
|
}
|
|
|
|
private function processProposal(object $legacy, int $cooperationId): void
|
|
{
|
|
$userId = $legacy->enhancer;
|
|
$partnerMediaId = $this->userToMediaMap[$userId] ?? null;
|
|
|
|
if (! $partnerMediaId) {
|
|
// Fallback or skip if media not found
|
|
return;
|
|
}
|
|
|
|
// Check if this proposal already exists to avoid duplication
|
|
$exists = DB::table('cooperation_proposals')
|
|
->where('cooperation_id', $cooperationId)
|
|
->where('partner_media_id', $partnerMediaId)
|
|
->exists();
|
|
|
|
if ($exists) {
|
|
return;
|
|
}
|
|
|
|
DB::table('cooperation_proposals')->insert([
|
|
'cooperation_id' => $cooperationId,
|
|
'partner_media_id' => $partnerMediaId,
|
|
'status' => $this->mapApprovalStatus((string) $legacy->status),
|
|
'submitted_at' => $legacy->created_at ?? now(),
|
|
'created_at' => $legacy->created_at ?? now(),
|
|
'updated_at' => $legacy->updated_at ?? now(),
|
|
]);
|
|
|
|
$proposalId = (int) DB::getPdo()->lastInsertId();
|
|
|
|
// Migrate offer_file if exists and not already migrated
|
|
if (! empty($legacy->offer_file) && ! isset($this->migratedProposalIds[$proposalId])) {
|
|
$this->importOfferFile($proposalId, $legacy);
|
|
}
|
|
}
|
|
|
|
private function importOfferFile(int $proposalId, object $legacy): void
|
|
{
|
|
$legacyPath = trim($legacy->offer_file);
|
|
if (empty($legacyPath) || $legacyPath === '-' || $legacyPath === 'no-image.png') {
|
|
return;
|
|
}
|
|
|
|
// Adjust path based on where these files are stored in S3
|
|
$sourcePath = 'old-data/proposals/'.$legacyPath;
|
|
|
|
try {
|
|
if (Storage::disk('s3')->exists($sourcePath)) {
|
|
$proposal = CooperationProposal::find($proposalId);
|
|
if ($proposal) {
|
|
$proposal->addMediaFromDisk($sourcePath, 's3')
|
|
->withCustomProperties([
|
|
'feature' => 'proposals',
|
|
'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(),
|
|
])
|
|
->preservingOriginal()
|
|
->toMediaCollection('proposals', 's3');
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
// Log silently
|
|
}
|
|
}
|
|
|
|
private function mapApprovalStatus(string $legacyStatus): int
|
|
{
|
|
return match ($legacyStatus) {
|
|
'0' => ApprovalStatus::PENDING->value,
|
|
'1' => ApprovalStatus::ACCEPTED->value,
|
|
'2' => ApprovalStatus::REJECTED->value,
|
|
default => ApprovalStatus::ACCEPTED->value,
|
|
};
|
|
}
|
|
}
|