Files
tehran_tala/docs/migration-precheck-3.sql
s.esmaeiliandClaude Opus 5.5 92831ed33e docs: migration map — verified data facts, corrections, import tool
DATA-MIGRATION-MAP.md:
- §10.7 is rewritten from the full dump loaded into MySQL. The legacy
  debt formula is confirmed (1,590/1,591 balances). The earlier claims
  that new_city is a cities5 id, that birthdays are clean and that
  types 3/4/5 are unknown were wrong and are corrected in a table.
  Favourites come from major_favorites, not fav. The role-number clash
  (legacy 86 «حسابدار» vs target 86 «کارشناس فروش») is recorded.
- §10.8 adds the tool's usage, safety rules, test result, and what it
  deliberately does not migrate.
- §11 and §5.5 are brought up to date. The rejected count is 7, not 14.

migration-precheck-3.sql: two bugs that would have failed on the server
are fixed: the reserved word `both` and a collation clash between
cities.title and customers.new_city.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 19:35:19 +03:30

66 lines
3.8 KiB
SQL

-- ============================================================================
-- پیش‌بررسی سوم — فقط دو سؤال باقی‌مانده
-- ============================================================================
--
-- ⚠️ فقط SELECT COUNT. صفر INSERT/UPDATE/DELETE. هیچ ستون متنی در خروجی.
--
-- اجرا:
-- mysql -u USER -p -h HOST -P 3305 oapi < migration-precheck-3.sql > out3.txt
--
-- مرجع: docs/DATA-MIGRATION-MAP.md §۵.۹
-- ============================================================================
-- ---------------------------------------------------------------------------
-- سؤال: new_city باید به cityId نگاشت شود یا ستون جدا بگیرد؟
--
-- تصمیم مالک: «یا در فیلد شهر بنشیند یا در یک فیلد آدرس متنی مپ شود».
-- کدام‌یک، به این بستگی دارد که آیا این ۱۷۶ ردیف city_id هم دارند یا نه:
--
-- فقط new_city (city_id تهی) → ستون متنی لازم است، چون شهر در جدول cities نیست
-- هر دو را دارند → new_city تکراری است، می‌توان رهایش کرد
-- ---------------------------------------------------------------------------
SELECT '=== new_city vs city_id ===' AS section;
SELECT
SUM(new_city IS NOT NULL AND new_city <> '' AND city_id IS NULL) AS only_new_city,
SUM(new_city IS NOT NULL AND new_city <> '' AND city_id IS NOT NULL) AS both_set,
SUM((new_city IS NULL OR new_city = '') AND city_id IS NOT NULL) AS only_city_id,
SUM((new_city IS NULL OR new_city = '') AND city_id IS NULL) AS neither
FROM customers WHERE deleted_at IS NULL;
-- از آن ۱۷۶ ردیف، چندتا متنی‌شان با عنوان یک شهر موجود در `cities` یکی است؟
-- اگر بالا باشد، اکثرشان قابل تبدیل به city_id هستند و ستون متنی لازم نیست.
SELECT 'new_city matches an existing cities.title' AS metric, COUNT(*) AS n
FROM customers c
-- The two columns have different collations (unicode_ci vs general_ci), so
-- both sides are pinned to one; without it MySQL refuses the comparison.
JOIN cities ci ON TRIM(ci.title) COLLATE utf8mb4_general_ci = TRIM(c.new_city) COLLATE utf8mb4_general_ci
WHERE c.deleted_at IS NULL AND c.new_city IS NOT NULL AND c.new_city <> ''
AND c.city_id IS NULL;
-- چند مقدار متمایز؟ (عدد است، نه متن — اگر کم باشد نگاشت دستی ممکن است)
SELECT 'distinct_new_city_values' AS metric, COUNT(DISTINCT TRIM(new_city)) AS n
FROM customers WHERE deleted_at IS NULL AND new_city IS NOT NULL AND new_city <> '';
-- ---------------------------------------------------------------------------
-- سؤال: birth_date — آیا تاریخ‌ها معتبرند؟
--
-- ستون timestamp است. ولی اگر تاریخ جلالی به‌اشتباه به‌عنوان میلادی
-- ذخیره شده باشد، سال‌ها ۱۳xx می‌شوند که در timestamp جا نمی‌شوند،
-- یا به مقادیر عجیب تبدیل شده‌اند.
-- ---------------------------------------------------------------------------
SELECT '=== birth_date sanity ===' AS section;
SELECT
COUNT(birth_date) AS total_set,
SUM(YEAR(birth_date) < 1900) AS year_before_1900,
SUM(YEAR(birth_date) BETWEEN 1900 AND 1950) AS year_1900_1950,
SUM(YEAR(birth_date) BETWEEN 1951 AND 2010) AS year_1951_2010,
SUM(YEAR(birth_date) > 2010) AS year_after_2010,
CAST(MIN(YEAR(birth_date)) AS CHAR) AS min_year,
CAST(MAX(YEAR(birth_date)) AS CHAR) AS max_year
FROM customers WHERE deleted_at IS NULL;
SELECT '=== END ===' AS section;