306 lines
13 KiB
PHP
306 lines
13 KiB
PHP
<?php
|
|
|
|
namespace Modules\AssetExchange\Console;
|
|
|
|
use App\Business;
|
|
use App\Contact;
|
|
use App\User;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Modules\AssetExchange\Models\AppraisalLine;
|
|
use Modules\AssetExchange\Models\Listing;
|
|
use Modules\AssetExchange\Models\PriceInquiry;
|
|
use Modules\AssetExchange\Models\PriceInquiryRecipient;
|
|
use Modules\AssetExchange\Models\ResearchCase;
|
|
use Modules\AssetExchange\Models\ResearchTask;
|
|
use Modules\AssetExchange\Services\AppraisalService;
|
|
use Modules\AssetExchange\Services\DealService;
|
|
use Modules\AssetExchange\Services\ListingService;
|
|
use Modules\AssetExchange\Services\PriceInquiryService;
|
|
use Modules\AssetExchange\Services\ResearchCaseService;
|
|
|
|
class AssetExchangeSeedDemo extends Command
|
|
{
|
|
protected $signature = 'pos:assetexchangeSeedDemo {business_id?} {--fresh : Remove previous demo records first}';
|
|
|
|
protected $description = 'Seed demo Listing, Appraisal and Inquiry data for AssetExchange E2E checks';
|
|
|
|
protected const DEMO_TITLE = '[DEMO-AEX] خط تولید بستهبندی دستدوم';
|
|
|
|
public function __construct(
|
|
protected ListingService $listingService,
|
|
protected AppraisalService $appraisalService,
|
|
protected PriceInquiryService $inquiryService,
|
|
protected ResearchCaseService $researchCaseService,
|
|
protected DealService $dealService
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
public function handle(): int
|
|
{
|
|
$businessId = (int) ($this->argument('business_id') ?: Business::query()->value('id') ?: 0);
|
|
if ($businessId <= 0) {
|
|
$this->error('No business found.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$business = Business::find($businessId);
|
|
if (! $business) {
|
|
$this->error("Business {$businessId} not found.");
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user = User::where('business_id', $businessId)->orderBy('id')->first();
|
|
if (! $user) {
|
|
$this->error("No user found for business {$businessId}.");
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
if ($this->option('fresh')) {
|
|
$this->purgeDemo($businessId);
|
|
} elseif (Listing::where('business_id', $businessId)->where('title', self::DEMO_TITLE)->exists()) {
|
|
$this->warn('Demo data already exists. Use --fresh to recreate.');
|
|
$this->printSummary($businessId);
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$supplierId = Contact::where('business_id', $businessId)
|
|
->whereIn('type', ['supplier', 'both'])
|
|
->orderBy('id')
|
|
->value('id');
|
|
|
|
if (! $supplierId) {
|
|
$supplierId = Contact::create([
|
|
'business_id' => $businessId,
|
|
'type' => 'supplier',
|
|
'supplier_business_name' => 'تأمینکننده دمو AEX',
|
|
'name' => 'تأمینکننده دمو AEX',
|
|
'mobile' => '09000000000',
|
|
'created_by' => $user->id,
|
|
'contact_status' => 'active',
|
|
])->id;
|
|
$this->line('Created demo supplier contact.');
|
|
}
|
|
|
|
$this->info("Seeding AssetExchange demo for business #{$businessId}...");
|
|
|
|
try {
|
|
DB::transaction(function () use ($business, $user, $supplierId) {
|
|
$listing = $this->listingService->create($business, [
|
|
'title' => self::DEMO_TITLE,
|
|
'description' => 'داده تستی خودکار برای smoke/E2E ماژول AssetExchange.',
|
|
'listing_type' => 'machine_used',
|
|
'scope_type' => 'whole',
|
|
'manufacturer' => 'Krones',
|
|
'model' => 'PET-Line 24K',
|
|
'serial_number' => 'DEMO-SN-'.now()->format('Ymd'),
|
|
'year_manufactured' => 2018,
|
|
'working_hours' => 12500,
|
|
'asking_price' => 8500000000,
|
|
'location_text' => 'تهران — انبار نمایشی',
|
|
'condition_grade' => 'B',
|
|
'intake_source' => 'internal_demo',
|
|
], $user);
|
|
|
|
$listing = $this->listingService->submit($business, $listing, $user);
|
|
$listing = $this->listingService->assignBroker($business, $listing, $user->id, $user);
|
|
|
|
$appraisal = $this->appraisalService->startAppraisal($business, $listing, $user, [
|
|
'methodology' => 'hybrid',
|
|
'field_visit_date' => now()->toDateString(),
|
|
'appraisal_fee' => 15000000,
|
|
'auto_import' => false,
|
|
]);
|
|
|
|
AppraisalLine::create([
|
|
'business_id' => $business->id,
|
|
'appraisal_id' => $appraisal->id,
|
|
'line_kind' => 'machine',
|
|
'name' => 'خط اصلی بستهبندی',
|
|
'manufacturer' => 'Krones',
|
|
'model' => 'PET-Line 24K',
|
|
'health_percentage' => 72,
|
|
'age_years' => 7,
|
|
'replacement_cost' => 12000000000,
|
|
'renovation_cost' => 1800000000,
|
|
'line_as_is_value' => 7200000000,
|
|
'line_post_renovation_value' => 9000000000,
|
|
'renovation_need' => 'moderate',
|
|
'keep_in_line' => true,
|
|
'sort_order' => 0,
|
|
]);
|
|
|
|
AppraisalLine::create([
|
|
'business_id' => $business->id,
|
|
'appraisal_id' => $appraisal->id,
|
|
'line_kind' => 'part',
|
|
'name' => 'درایور موتور اصلی',
|
|
'health_percentage' => 55,
|
|
'age_years' => 7,
|
|
'replacement_cost' => 450000000,
|
|
'renovation_cost' => 120000000,
|
|
'line_as_is_value' => 250000000,
|
|
'line_post_renovation_value' => 370000000,
|
|
'renovation_need' => 'high',
|
|
'keep_in_line' => true,
|
|
'sort_order' => 1,
|
|
]);
|
|
|
|
$appraisal = $this->appraisalService->recalculate($appraisal);
|
|
$appraisal = $this->appraisalService->approve(
|
|
$business,
|
|
$appraisal,
|
|
$user,
|
|
'گزارش دمو: تجهیز قابل خرید با نوسازی محدود درایور و بازرسی هیدرولیک.'
|
|
);
|
|
|
|
$inquiryData = [
|
|
'title' => 'استعلام دمو — قطعات و سرویس خط',
|
|
'inquiry_type' => 'supplier_rfq',
|
|
'appraisal_id' => $appraisal->id,
|
|
'from_appraisal' => true,
|
|
'due_date' => now()->addDays(3)->format('Y-m-d'),
|
|
'internal_user_ids' => [$user->id],
|
|
];
|
|
if ($supplierId) {
|
|
$inquiryData['supplier_contact_ids'] = [$supplierId];
|
|
}
|
|
|
|
$inquiry = $this->inquiryService->create($business, $listing, $inquiryData, $user);
|
|
$inquiry = $this->inquiryService->send($inquiry, $user);
|
|
|
|
$slaInquiry = $this->inquiryService->create($business, $listing, [
|
|
'title' => 'استعلام دمو SLA — معوق',
|
|
'inquiry_type' => 'supplier_rfq',
|
|
'due_date' => now()->subDay()->format('Y-m-d'),
|
|
'lines' => [[
|
|
'part_name' => 'سنسور فشار',
|
|
'description' => 'نمونه SLA معوق',
|
|
'target_condition' => 'new',
|
|
'reference_price' => 35000000,
|
|
]],
|
|
'supplier_contact_ids' => [$supplierId],
|
|
], $user);
|
|
|
|
$slaInquiry = $this->inquiryService->send($slaInquiry, $user);
|
|
PriceInquiryRecipient::where('price_inquiry_id', $slaInquiry->id)
|
|
->where('recipient_type', 'supplier')
|
|
->where('status', 'pending')
|
|
->update(['sent_at' => Carbon::now()->subHours(60)]);
|
|
|
|
$this->researchCaseService->openCase($business, $listing->fresh(), [
|
|
'title' => 'پرونده تحقیق دمو — '.$listing->title,
|
|
'spawn_templates' => true,
|
|
'lead_researcher_id' => $user->id,
|
|
], $user);
|
|
|
|
$listing = $listing->fresh();
|
|
$deal = $this->dealService->createDeal($business, $listing, 'brokerage', [
|
|
'appraisal_id' => $appraisal->id,
|
|
'agreed_price' => $appraisal->recommended_buy_price,
|
|
'commission_percent' => 3,
|
|
'notes' => 'معامله دمو — کارگزاری',
|
|
], $user);
|
|
|
|
try {
|
|
$this->dealService->completeDeal($business, $deal, $user);
|
|
} catch (\Throwable) {
|
|
// ERP/CMMS bridges may be unavailable in demo environments.
|
|
}
|
|
});
|
|
} catch (\Throwable $e) {
|
|
$this->error('Seed failed: '.$e->getMessage());
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$this->info('Demo data seeded successfully.');
|
|
$this->printSummary($businessId);
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
protected function purgeDemo(int $businessId): void
|
|
{
|
|
$listingIds = Listing::withTrashed()
|
|
->where('business_id', $businessId)
|
|
->where('title', self::DEMO_TITLE)
|
|
->pluck('id');
|
|
|
|
if ($listingIds->isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
$caseIds = ResearchCase::where('business_id', $businessId)
|
|
->whereIn('listing_id', $listingIds)
|
|
->pluck('id');
|
|
if ($caseIds->isNotEmpty()) {
|
|
ResearchTask::whereIn('research_case_id', $caseIds)->delete();
|
|
ResearchCase::whereIn('id', $caseIds)->delete();
|
|
}
|
|
|
|
if (\Illuminate\Support\Facades\Schema::hasTable('aex_commissions')) {
|
|
$dealIds = \Modules\AssetExchange\Models\Deal::withTrashed()
|
|
->whereIn('listing_id', $listingIds)
|
|
->pluck('id');
|
|
if ($dealIds->isNotEmpty()) {
|
|
\Modules\AssetExchange\Models\Commission::whereIn('deal_id', $dealIds)->delete();
|
|
\Modules\AssetExchange\Models\Deal::withTrashed()->whereIn('id', $dealIds)->forceDelete();
|
|
}
|
|
}
|
|
|
|
$inquiryIds = PriceInquiry::where('business_id', $businessId)
|
|
->whereIn('listing_id', $listingIds)
|
|
->pluck('id');
|
|
|
|
if ($inquiryIds->isNotEmpty()) {
|
|
PriceInquiryRecipient::whereIn('price_inquiry_id', $inquiryIds)->delete();
|
|
PriceInquiry::whereIn('id', $inquiryIds)->delete();
|
|
}
|
|
|
|
foreach ($listingIds as $listingId) {
|
|
$appraisalIds = \Modules\AssetExchange\Models\Appraisal::withTrashed()
|
|
->where('listing_id', $listingId)
|
|
->pluck('id');
|
|
if ($appraisalIds->isNotEmpty()) {
|
|
AppraisalLine::whereIn('appraisal_id', $appraisalIds)->delete();
|
|
\Modules\AssetExchange\Models\Appraisal::withTrashed()->whereIn('id', $appraisalIds)->forceDelete();
|
|
}
|
|
}
|
|
|
|
Listing::withTrashed()->whereIn('id', $listingIds)->forceDelete();
|
|
$this->line('Previous demo records removed.');
|
|
}
|
|
|
|
protected function printSummary(int $businessId): void
|
|
{
|
|
$listing = Listing::where('business_id', $businessId)->where('title', self::DEMO_TITLE)->first();
|
|
if (! $listing) {
|
|
return;
|
|
}
|
|
|
|
$appraisal = $listing->appraisals()->latest('id')->first();
|
|
$inquiries = $listing->priceInquiries()->orderBy('id')->get();
|
|
$rfq = $inquiries->first(fn ($i) => str_contains($i->title, 'قطعات'));
|
|
$sla = $inquiries->first(fn ($i) => str_contains($i->title, 'SLA'));
|
|
$research = $listing->researchCases()->latest('id')->first();
|
|
$deal = $listing->deals()->latest('id')->first();
|
|
|
|
$this->table(['Entity', 'Code', 'Status'], [
|
|
['Listing', $listing->listing_code, $listing->status],
|
|
['Appraisal', $appraisal?->appraisal_number ?? '—', $appraisal?->status ?? '—'],
|
|
['Research', $research?->case_code ?? '—', $research?->status ?? '—'],
|
|
['Deal', $deal?->deal_code ?? '—', $deal?->status ?? '—'],
|
|
['Inquiry (RFQ)', $rfq?->inquiry_code ?? '—', $rfq?->status ?? '—'],
|
|
['Inquiry (SLA)', $sla?->inquiry_code ?? '—', $sla?->status ?? '—'],
|
|
['Appraisal PDF', $appraisal?->report_pdf_path ? 'stored' : '—', ''],
|
|
]);
|
|
}
|
|
}
|