fix bug
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Database\Console\Migrations\MigrateCommand as BaseMigrateCommand;
|
||||
|
||||
class MigrateCommand extends BaseMigrateCommand
|
||||
{
|
||||
/**
|
||||
* Never auto-load database/schema/*.sql — it DROP TABLEs and wipes production data
|
||||
* when the migrations table is empty. Use baseline_migrations.sql on existing DBs.
|
||||
*/
|
||||
protected function prepareDatabase()
|
||||
{
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
$this->call('migrate:install', array_filter([
|
||||
'--database' => $this->option('database'),
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,11 @@ class SyncProductPrices extends Command
|
||||
{
|
||||
protected $signature = 'product:sync-prices';
|
||||
|
||||
protected $description = 'Sync variable product prices from external feeds (every ~30s via scheduler)';
|
||||
protected $description = 'Fetch zaarbox price board + sync product DB (scheduler: every 30s)';
|
||||
|
||||
public function handle(ProductPriceSyncService $syncService): int
|
||||
{
|
||||
// کران: همیشه فید تازه از zaarbox
|
||||
// کران: GET https://price.zaarbox.ir/api/free (یا zaarbox_api_url) → کش + UPDATE محصولات
|
||||
$syncService->syncAll(true);
|
||||
|
||||
return self::SUCCESS;
|
||||
|
||||
@@ -152,12 +152,9 @@ class ProductController extends SuperController
|
||||
|
||||
public function listProduct()
|
||||
{
|
||||
// لیست کاربر: فقط zaarbox با کش — فید legacy در کران (product:sync-prices)
|
||||
$syncService = app(\App\Services\ProductPriceSyncService::class);
|
||||
if (str_contains(request()->path(), '/customer/')) {
|
||||
$syncService->syncForProductList();
|
||||
} else {
|
||||
$syncService->syncAll(false);
|
||||
// ادمین: sync اختیاری از کش — کاربر: فقط enrich از کش کران (بدون HTTP / بدون UPDATE)
|
||||
if (!str_contains(request()->path(), '/customer/')) {
|
||||
app(\App\Services\ProductPriceSyncService::class)->syncAll(false);
|
||||
}
|
||||
|
||||
$products = Product::with(['file'])->where('active', 1)->get();
|
||||
|
||||
@@ -13,7 +13,12 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
$this->app->extend('command.migrate', function ($command, $app) {
|
||||
return new \App\Console\Commands\MigrateCommand(
|
||||
$app['migrator'],
|
||||
$app['events']
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,15 +6,19 @@ use App\Models\Price;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* قیمت نمایشی محصولات آبشده با منبع «قیمت اپ» — در DB صفر است، برای API پر میشود.
|
||||
* قیمت نمایشی محصولات برای API — فقط از کش/تنظیمات (بدون HTTP روی list).
|
||||
*
|
||||
* • آبشده با «قیمت اپ» → montzar_live_price / کش /api/price/last
|
||||
* • محصول با reading_method → ردیف فید zaarbox از کش کران (۳۰ث)
|
||||
*/
|
||||
class ProductDisplayPriceService
|
||||
{
|
||||
public const LIVE_PRICE_CACHE_KEY = 'live_price_api_payload';
|
||||
|
||||
public const LIVE_PRICE_CACHE_SECONDS = 15;
|
||||
public const LIVE_PRICE_CACHE_SECONDS = 45;
|
||||
|
||||
public function usesAppPrice(Product $product): bool
|
||||
{
|
||||
@@ -29,44 +33,81 @@ class ProductDisplayPriceService
|
||||
return $this->isMeltedTradeProduct($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* پر کردن price روی مدلها برای پاسخ JSON — بدون UPDATE دیتابیس
|
||||
*/
|
||||
public function enrichForApi(Collection|iterable $products): void
|
||||
{
|
||||
$needsLivePrice = false;
|
||||
$collection = collect($products);
|
||||
$zaarbox = app(ZaarboxPriceService::class);
|
||||
$zaarboxFeed = $zaarbox->getCachedPriceListOnly();
|
||||
|
||||
foreach ($products as $product) {
|
||||
if ($product instanceof Product && $this->usesAppPrice($product)) {
|
||||
$needsLivePrice = true;
|
||||
break;
|
||||
$baseAppPrice = 0;
|
||||
if ($collection->contains(fn ($p) => $p instanceof Product && $this->usesAppPrice($p))) {
|
||||
$baseAppPrice = $this->resolveAppBasePrice();
|
||||
}
|
||||
|
||||
foreach ($collection as $product) {
|
||||
if (!$product instanceof Product) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->usesAppPrice($product)) {
|
||||
$this->applyAppPrice($product, $baseAppPrice);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($product->reading_method && is_array($zaarboxFeed)) {
|
||||
$this->applyReferenceFeedPrice($product, $zaarboxFeed, $zaarbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$needsLivePrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
$basePrice = $this->resolveAppBasePrice();
|
||||
private function applyAppPrice(Product $product, int $basePrice): void
|
||||
{
|
||||
if ($basePrice <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($products as $product) {
|
||||
if (!$product instanceof Product || !$this->usesAppPrice($product)) {
|
||||
continue;
|
||||
$offset = Product::hasPriceOffsetColumn()
|
||||
? (float) ($product->price_offset_percent ?? 0)
|
||||
: 0.0;
|
||||
|
||||
$computed = ProductPriceService::adjustedTotal($basePrice, 0, $offset);
|
||||
if ($computed <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product->setAttribute('price', $computed);
|
||||
if (Schema::hasColumn($product->getTable(), 'price_profit')) {
|
||||
$product->setAttribute('price_profit', 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param array<int, array<string, mixed>> $feed */
|
||||
private function applyReferenceFeedPrice(Product $product, array $feed, ZaarboxPriceService $zaarbox): void
|
||||
{
|
||||
$row = $zaarbox->findFeedRow($feed, (string) $product->reading_method);
|
||||
if ($row === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$computed = $zaarbox->computeAdjustedProductPrice($product, $row);
|
||||
if ($computed <= 0) {
|
||||
if (
|
||||
Product::hasUseLastPriceIfZeroColumn()
|
||||
&& ($product->use_last_price_if_zero ?? false)
|
||||
&& (int) ($product->price ?? 0) > 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$offset = Product::hasPriceOffsetColumn()
|
||||
? (float) ($product->price_offset_percent ?? 0)
|
||||
: 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
$computed = ProductPriceService::adjustedTotal($basePrice, 0, $offset);
|
||||
if ($computed <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$product->setAttribute('price', $computed);
|
||||
if (\Illuminate\Support\Facades\Schema::hasColumn($product->getTable(), 'price_profit')) {
|
||||
$product->setAttribute('price_profit', 0);
|
||||
}
|
||||
$product->setAttribute('price', $computed);
|
||||
if (Schema::hasColumn($product->getTable(), 'price_profit')) {
|
||||
$product->setAttribute('price_profit', 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +124,12 @@ class ProductDisplayPriceService
|
||||
|
||||
public function resolveAppBasePrice(): int
|
||||
{
|
||||
$payload = $this->livePricePayload();
|
||||
return $this->extractBaseFromPayload($this->livePricePayload());
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $payload */
|
||||
private function extractBaseFromPayload(array $payload): int
|
||||
{
|
||||
$price = (int) ($payload['price'] ?? 0);
|
||||
if ($price > 0) {
|
||||
return $price;
|
||||
@@ -96,7 +141,12 @@ class ProductDisplayPriceService
|
||||
return (int) round(($buy + $sell) / 2);
|
||||
}
|
||||
|
||||
return (int) ($payload['price_last'] ?? 0);
|
||||
$priceLast = (int) ($payload['price_last'] ?? 0);
|
||||
if ($priceLast > 0) {
|
||||
return $priceLast;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @return array{price: int, buy: int, sell: int, price_last: int} */
|
||||
@@ -120,8 +170,7 @@ class ProductDisplayPriceService
|
||||
if ($provider === 'montzar') {
|
||||
$price = $config->getInt('montzar_live_price', 0);
|
||||
} elseif ($provider === 'zaarbox') {
|
||||
$zaarbox = app(ZaarboxPriceService::class)->fetchPrice();
|
||||
$price = (int) ($zaarbox['order_price'] ?? 0);
|
||||
$price = $this->resolveZaarboxBoardPriceFromCache($config);
|
||||
} elseif ($provider === 'main_product') {
|
||||
$main = $config->mainProduct();
|
||||
if ($main) {
|
||||
@@ -131,7 +180,7 @@ class ProductDisplayPriceService
|
||||
$price = $config->getInt('taban_gohar_live_price', 0);
|
||||
}
|
||||
|
||||
if ($price <= 0) {
|
||||
if ($price <= 0 && $config->getBool('show_last_price', false)) {
|
||||
$last = Price::orderByDesc('id')->first();
|
||||
if ($last && (float) $last->price > 0) {
|
||||
$price = (int) $last->price;
|
||||
@@ -141,12 +190,40 @@ class ProductDisplayPriceService
|
||||
$diffBuy = (int) $config->displayBuySpreadRial();
|
||||
$diffSell = (int) $config->displaySellSpreadRial();
|
||||
|
||||
return [
|
||||
$payload = [
|
||||
'price' => $price,
|
||||
'buy' => $price > 0 ? $price + $diffBuy : 0,
|
||||
'sell' => $price > 0 ? max(0, $price - $diffSell) : 0,
|
||||
'price_last' => $price > 0 ? $price + $diffBuy : 0,
|
||||
];
|
||||
|
||||
if ($this->extractBaseFromPayload($payload) > 0) {
|
||||
$this->cacheLivePricePayload($payload);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
private function resolveZaarboxBoardPriceFromCache(ConfigService $config): int
|
||||
{
|
||||
$identifier = trim($config->getString('zaarbox_price_key', ''));
|
||||
if ($identifier === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$feed = app(ZaarboxPriceService::class)->getCachedPriceListOnly();
|
||||
if (!is_array($feed)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$row = app(ZaarboxPriceService::class)->findFeedRow($feed, $identifier);
|
||||
if ($row === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$row = app(ZaarboxPriceService::class)->normalizeFeedRow($row);
|
||||
|
||||
return (int) round((float) ($row['price'] ?? 0) + (float) ($row['profit'] ?? 0));
|
||||
}
|
||||
|
||||
private function isMeltedTradeProduct(Product $product): bool
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Http\Controllers\Site\ReportController;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@@ -23,32 +22,6 @@ class ProductPriceSyncService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* sync سبک برای /customer/product/list — فقط zaarbox با کش کوتاه.
|
||||
* فید legacy (تا ۴۰ث timeout) فقط در کران اجرا میشود.
|
||||
*/
|
||||
public function syncForProductList(): bool
|
||||
{
|
||||
if (!$this->configService->getBool('product_update_price_on_list', true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!Product::hasStoredPriceColumns()
|
||||
|| !Product::query()->whereNotNull('reading_method')->exists()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->zaarboxPriceService->syncProductsFromApi(false);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('Zaarbox product list sync failed', ['message' => $e->getMessage()]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param bool $forceRefresh درخواست تازه از https://price.zaarbox.ir/api/free (کران) */
|
||||
public function syncAll(bool $forceRefresh = false): bool
|
||||
{
|
||||
@@ -104,11 +77,10 @@ class ProductPriceSyncService
|
||||
$synced = true;
|
||||
|
||||
if ($product->bubble == 1) {
|
||||
$reportController = new ReportController();
|
||||
$liquidGold = $reportController->lastPrice();
|
||||
$liquidGoldPrice = app(ProductDisplayPriceService::class)->resolveAppBasePrice();
|
||||
$p = Product::find($product->id);
|
||||
if ($p && ($liquidGold['price'] ?? 0) > 0) {
|
||||
$p->amount = $RPrice['price'] / $liquidGold['price'];
|
||||
if ($p && $liquidGoldPrice > 0) {
|
||||
$p->amount = $RPrice['price'] / $liquidGoldPrice;
|
||||
$p->show = $show;
|
||||
$p->save();
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ class ZaarboxPriceService
|
||||
|
||||
private const CACHE_TTL_MINUTES = 35;
|
||||
|
||||
/** حداکثر فاصلهٔ استفاده مجدد از فید بدون درخواست جدید (ثانیه) */
|
||||
private const PRICE_LIST_CACHE_SECONDS = 25;
|
||||
/** TTL کش فید — کران هر ۳۰ث refresh میکند؛ list فقط از همین میخواند */
|
||||
private const PRICE_LIST_CACHE_SECONDS = 45;
|
||||
|
||||
private const DEFAULT_HISTORY_ID = 'ca3800a0-1f57-3528-b963-178f9168e04f';
|
||||
|
||||
@@ -135,8 +135,8 @@ class ZaarboxPriceService
|
||||
return $empty;
|
||||
}
|
||||
|
||||
$row = $this->findRow(collect($prices), $identifier);
|
||||
if (empty($row)) {
|
||||
$row = $this->findFeedRow($prices, $identifier);
|
||||
if ($row === null) {
|
||||
Log::warning('Zaarbox price row not found', [
|
||||
'identifier' => $identifier,
|
||||
'api' => $this->apiUrl(),
|
||||
@@ -192,12 +192,26 @@ class ZaarboxPriceService
|
||||
|
||||
$prices = $this->fetchPriceList();
|
||||
if ($prices !== null) {
|
||||
Cache::put(self::PRICE_LIST_CACHE_KEY, $prices, now()->addSeconds(self::PRICE_LIST_CACHE_SECONDS));
|
||||
$this->storePriceListCache($prices);
|
||||
}
|
||||
|
||||
return $prices;
|
||||
}
|
||||
|
||||
/** فقط کش — برای /customer/product/list (بدون HTTP) */
|
||||
public function getCachedPriceListOnly(): ?array
|
||||
{
|
||||
$cached = Cache::get(self::PRICE_LIST_CACHE_KEY);
|
||||
|
||||
return is_array($cached) ? $cached : null;
|
||||
}
|
||||
|
||||
/** @param array<int, array<string, mixed>> $prices */
|
||||
public function storePriceListCache(array $prices): void
|
||||
{
|
||||
Cache::put(self::PRICE_LIST_CACHE_KEY, $prices, now()->addSeconds(self::PRICE_LIST_CACHE_SECONDS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array{key: string, name: string, id: string, category: string, active: bool}>
|
||||
*/
|
||||
@@ -244,8 +258,8 @@ class ZaarboxPriceService
|
||||
return $empty;
|
||||
}
|
||||
|
||||
$row = $this->findRow(collect($prices), $readingMethod);
|
||||
if (empty($row)) {
|
||||
$row = $this->findFeedRow($prices, $readingMethod);
|
||||
if ($row === null) {
|
||||
return $empty;
|
||||
}
|
||||
|
||||
@@ -283,7 +297,6 @@ class ZaarboxPriceService
|
||||
$config = $this->config;
|
||||
$mainProductId = $config->mainProductId();
|
||||
$hasExtremeKeys = Setting::whereIn('key', ['up_price', 'down_price'])->count() === 2;
|
||||
$collection = collect($prices);
|
||||
$copper = null;
|
||||
$dollar = null;
|
||||
|
||||
@@ -291,8 +304,8 @@ class ZaarboxPriceService
|
||||
$currentTime = now()->format('H:i:s');
|
||||
|
||||
foreach ($products as $product) {
|
||||
$RPrice = $collection->firstWhere('key', $product->reading_method);
|
||||
if (empty($RPrice)) {
|
||||
$RPrice = $this->findFeedRow($prices, (string) $product->reading_method);
|
||||
if ($RPrice === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -326,11 +339,11 @@ class ZaarboxPriceService
|
||||
}
|
||||
|
||||
if ((int) ($product->bubble ?? 0) === 1) {
|
||||
$liquidGold = app(\App\Http\Controllers\Site\ReportController::class)->lastPrice();
|
||||
$liquidGoldPrice = app(ProductDisplayPriceService::class)->resolveAppBasePrice();
|
||||
$p = Product::find($product->id);
|
||||
if ($p && ($liquidGold['price'] ?? 0) > 0) {
|
||||
if ($p && $liquidGoldPrice > 0) {
|
||||
$show = ($currentTime >= $product->auto_open_at && $currentTime <= $product->auto_close_at);
|
||||
$p->amount = $row['price'] / $liquidGold['price'];
|
||||
$p->amount = $row['price'] / $liquidGoldPrice;
|
||||
$p->show = $show;
|
||||
$p->save();
|
||||
}
|
||||
@@ -363,8 +376,49 @@ class ZaarboxPriceService
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* جستجو در فید zaarbox — key / id / name (همان reading_method ادمین)
|
||||
*
|
||||
* @param array<int, array<string, mixed>> $prices
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function findFeedRow(array $prices, string $identifier): ?array
|
||||
{
|
||||
$identifier = trim($identifier);
|
||||
if ($identifier === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$collection = collect($prices);
|
||||
|
||||
foreach (['key', 'id', 'name'] as $field) {
|
||||
$row = $collection->firstWhere($field, $identifier);
|
||||
if (!empty($row)) {
|
||||
return is_array($row) ? $row : (array) $row;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* قیمت نمایشی محصول از یک ردیف فید + offset درصد — بدون نوشتن DB
|
||||
*
|
||||
* @param array<string, mixed> $row
|
||||
*/
|
||||
public function computeAdjustedProductPrice(Product $product, array $row): int
|
||||
{
|
||||
$normalized = $this->normalizeFeedRow($row);
|
||||
|
||||
return ProductPriceService::adjustedTotal(
|
||||
(int) ($normalized['price'] ?? 0),
|
||||
(int) ($normalized['profit'] ?? 0),
|
||||
ProductPriceService::offsetPercent($product)
|
||||
);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $row */
|
||||
private function normalizeFeedRow(array $row): array
|
||||
public function normalizeFeedRow(array $row): array
|
||||
{
|
||||
if (($row['name'] ?? '') === 'گلد دات ای از آبشده - رسمی - نقد فردا') {
|
||||
$row['price'] = ($row['price'] ?? 0) / 4.3318;
|
||||
@@ -388,8 +442,8 @@ class ZaarboxPriceService
|
||||
return false;
|
||||
}
|
||||
|
||||
$RPrice = collect($prices)->firstWhere('key', $product->reading_method);
|
||||
if (empty($RPrice)) {
|
||||
$RPrice = $this->findFeedRow($prices, (string) $product->reading_method);
|
||||
if ($RPrice === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -531,22 +585,4 @@ class ZaarboxPriceService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, array<string, mixed>> $collection
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function findRow(Collection $collection, string $identifier): ?array
|
||||
{
|
||||
$row = $collection->firstWhere('key', $identifier);
|
||||
if (!empty($row)) {
|
||||
return $row;
|
||||
}
|
||||
|
||||
$row = $collection->firstWhere('id', $identifier);
|
||||
if (!empty($row)) {
|
||||
return $row;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Schema reference — دستی import کنید
|
||||
|
||||
`mysql-schema.sql.reference` فقط مرجع است. Laravel دیگر آن را با `php artisan migrate` load **نمیکند**.
|
||||
|
||||
## DB خالی
|
||||
|
||||
```bash
|
||||
mysql -h HOST -P PORT -u USER -p DATABASE < database/schema/mysql-schema.sql.reference
|
||||
mysql ... < database/sql/baseline_migrations.sql
|
||||
php artisan migrate
|
||||
mysql ... < database/sql/deploy_settings_const.sql
|
||||
```
|
||||
|
||||
## DB موجود
|
||||
|
||||
`mysql-schema.sql.reference` **نزنید** — فقط `baseline_migrations.sql` + `migrate`.
|
||||
@@ -1,5 +1,8 @@
|
||||
# چکلیست Deploy — برنچ ماژولار
|
||||
|
||||
> **ایمنی:** `php artisan migrate` دیگر `mysql-schema.sql` را auto-load نمیکند (DROP TABLE نمیزند).
|
||||
> فایل schema فقط دستی: `database/schema/mysql-schema.sql.reference`
|
||||
|
||||
## قبل از شروع
|
||||
|
||||
- [ ] بکاپ DB
|
||||
@@ -23,16 +26,12 @@ DB_PASSWORD=$(grep ^DB_PASSWORD= .env | cut -d= -f2- | tr -d '\r"')
|
||||
# ۱ baseline
|
||||
mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USERNAME" -p"$DB_PASSWORD" "$DB_DATABASE" \
|
||||
< database/sql/baseline_migrations.sql
|
||||
|
||||
#mysql -h 127.0.0.1 -P 3030 -u root -p soroushgold < database/sql/baseline_migrations.sql
|
||||
|
||||
# باید ۱۱ ردیف چاپ شود (شامل 2019 و 2021)
|
||||
|
||||
# ۲ چک DB — اگر کمتر از ۲ بود baseline قدیمی است
|
||||
mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USERNAME" -p"$DB_PASSWORD" "$DB_DATABASE" -N -e \
|
||||
"SELECT COUNT(*) FROM migrations WHERE migration LIKE '2019%' OR migration LIKE '2021%';"
|
||||
|
||||
#mysql -h "127.0.0.1" -P "3030" -u "root" -p"1ipqLRRMC7qS8s3WkuwXiS7P" "soroushgold" -N -e \"SELECT COUNT(*) FROM migrations WHERE migration LIKE '2019%' OR migration LIKE '2021%';"
|
||||
|
||||
# باید: 2
|
||||
|
||||
@@ -45,8 +44,6 @@ php artisan migrate
|
||||
# ۵ settings
|
||||
mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USERNAME" -p"$DB_PASSWORD" "$DB_DATABASE" \
|
||||
< database/sql/deploy_settings_const.sql
|
||||
|
||||
#mysql -h "127.0.0.1" -P "3030" -u "root" -p"1ipqLRRMC7qS8s3WkuwXiS7P" "soroushgold" \ < database/sql/deploy_settings_const.sql
|
||||
```
|
||||
|
||||
**یا:** `bash database/sql/run_deploy_existing_db.sh`
|
||||
@@ -87,12 +84,12 @@ mysql -h 127.0.0.1 -P 3030 -u root -p soroushgold \
|
||||
## DB خالی
|
||||
|
||||
```bash
|
||||
mysql ... < database/schema/mysql-schema.sql.reference
|
||||
mysql ... < database/sql/baseline_migrations.sql
|
||||
php artisan migrate
|
||||
mysql ... < database/sql/deploy_settings_const.sql
|
||||
```
|
||||
|
||||
`baseline_migrations.sql` **نزنید**.
|
||||
|
||||
---
|
||||
|
||||
## خطاها
|
||||
@@ -100,7 +97,7 @@ mysql ... < database/sql/deploy_settings_const.sql
|
||||
| خطا | فیکس |
|
||||
|-----|------|
|
||||
| `Table already exists` | `fake_package_migrations.sql` → `migrate` |
|
||||
| `Loading stored database schema` | restore بکاپ → `baseline` قبل از `migrate` |
|
||||
| `Loading stored database schema` | کد قدیمی — `git pull` (دیگر رخ نمیدهد). اگر شد: restore بکاپ |
|
||||
| `2019`/`2021` No بعد از baseline | baseline قدیمی → `fake_package_migrations.sql` |
|
||||
| `Unknown host HOST` | از `.env` بخوان نه placeholder |
|
||||
| `Unknown column 'is_exist'` | `git pull` + دوباره `deploy_settings_const.sql` (نسخه جدید ستون را اضافه میکند) |
|
||||
|
||||
Reference in New Issue
Block a user