Amirali Yaghoutiمهندس ارشد نرم‌افزار

مطالعه موردی مهندسی

اپ دوربین تا سبد خرید Jeweltimeco

هر ساعت در انبار جوئل‌تایم کد یکتای خودش را دارد؛ نه فقط یک SKU مشترک بین اقلام مشابه. برای همین دوربین گوشی سریع‌ترین راه است تا مشاور فروش، همان‌جا کف فروشگاه، یک قطعه‌ی فیزیکی مشخص را روی فاکتور یک مشتری مشخص بگذارد.

مسئله تجاری

مشاوری که کنار مشتری ایستاده باید قلم را در چند ثانیه توی سبد داشته باشد. آن قلم هم یک قطعه‌ی فیزیکی مشخص با کد خودش است، نه فقط یک مدل. تایپ کردن کد هم کند است هم خطاخیز. سؤال اصلی هم اصلاً از فیلد موجودی ووکامرس درنمی‌آید: همین قطعه هنوز هست، یا رزرو شده، یا قبلاً فاکتور شده؟

آنچه تحویل دادم

  • یک اسکنر در نمای کاتالوگ و برند اپلیکیشن، روی دکمه‌ای شناور که با یک دست هم در دسترس است.
  • BarcodeDetector بومی هرجا مرورگر داشته باشد، و فالبک ZXing هرجا نداشته باشد، تا این مسیر روی همان گوشی‌هایی که تیم دستش است کار کند.
  • رسیدن از کد یکتای اسکن‌شده به کد سفارش و محصول، و بعد افزودن به سبد با بررسی رزرو، نه صرفاً بررسی موجودی.
  • مدیریت صریح حالت‌هایی که در فروشگاه واقعی پیش می‌آید: قطعه از قبل به مشتری دیگری خورده، کد اسکن‌شده با محصول مورد انتظار نمی‌خواند، یا موجودی کم است.
  • یک مسیر دستیِ بدون کد، برای وقتی همه‌ی قطعات رزرو شده‌اند و مشاور تأیید می‌کند که با این حال ادامه می‌دهد.
  • ابزار ردیابی محصول: یک کد یکتا می‌گیرد و می‌گوید موجود است، رزرو شده یا فاکتور شده؛ اگر مصرف شده باشد، فاکتور و مشتری مربوط را هم نشان می‌دهد.
  • بارگذاری موجودی با CSV یا XLSX بر اساس کد سفارش و کد یکتا: کدهای فعال upsert می‌شوند، کدهای غایب غیرفعال، و اگر هیچ کد فعالی نماند محصول ناموجود می‌شود.

رویکرد فنی

  • حقیقت موجودی در جدول کد یکتا نگهداری می‌شود، نه در فیلد موجودی ووکامرس. همین است که وضعیت رزرو را به یک جواب واقعی تبدیل می‌کند، نه یک عدد.
  • اسکنر به‌جای الزام یک مرورگر خاص، پله‌پله پایین می‌آید: BarcodeDetector وقتی هست، ZXing وقتی نیست، و مسیر دستی وقتی هیچ‌کدام جواب نمی‌دهند.
  • هر حالت شکست اسم دارد و جدا مدیریت می‌شود. توی فروشگاه، اسکنی که بی‌صدا هیچ کاری نمی‌کند بدتر از اسکنی است که می‌گوید این قطعه روی فاکتور کس دیگری رفته.
  • هر بارگذاری یک گزارش قابل دانلود از کدهای سفارشی می‌دهد که به هیچ محصولی نخورده‌اند؛ مشکل ایمپورت دیده می‌شود، نه اینکه بی‌صدا بلعیده شود.
  • اسکن در مدل نقش‌ها به مشاور فروش و بالاتر محدود است؛ نشست مهمان یا مشتری هیچ‌وقت به آن نمی‌رسد.

نتیجه و شواهد

مشاور با گرفتن گوشی روبه‌روی یک قلم، همان قطعه‌ی مشخص را به فاکتور اضافه می‌کند و وضعیت رزرو هم در همان لحظه بررسی می‌شود، نه بعداً موقع تحویل. ردیابی محصول هم مستقیم جواب می‌دهد این قطعه کجاست؛ سؤالی که قبلاً یک گفت‌وگوی سه‌نفره بود.

اهمیت برای کارفرما

فروش جواهر قلم‌به‌قلم است، نه SKU به SKU، و گم شدن ردِ اینکه کدام قطعه کجا رفته هزینه‌ی عملیاتی سنگینی دارد. گره زدن دوربین به جدول کد یکتا همان چیزی است که بقیه‌ی گردش کار فاکتور را قابل اعتماد می‌کند.

خلاصه-اجرایی-پروژه

خلاصه اجرایی خوانا

خلاصه_اجرایی {
  پروژه: "JewelTime Camera-to-Cart"
  پشته: "اندپوینت‌های PHP + SPA جاوااسکریپت خالص، PWA"
  اسکنر: "BarcodeDetector، فالبک ZXing، مسیر دستی"
  resolve: "کد یکتا ← کد سفارش ← محصول"
  حقیقت: "جدول موجودی کد یکتا، نه فیلد موجودی ووکامرس"
  وضعیت‌ها: "از قبل تخصیص‌یافته، ناهماهنگی محصول، موجودی کم،
             کاملاً رزروشده (عبور دستی با تأیید)"
  ردیابی: "کد یکتا ← موجود / رزروشده / فاکتورشده،
           همراه فاکتور و مشتری مرتبط"
  ورود_داده: "upsert با CSV/XLSX، غیرفعال‌کردن کدهای غایب،
              گزارش کدهای سفارش بی‌تطبیق"
  دسترسی: "نقش مشاور فروش و بالاتر"
}

ارزش حرفه‌ای این پروژه

بخش جالب ماجرا اسکنر نیست؛ چیزی است که اسکن بر اساس آن resolve می‌شود. اول ساختن جدول موجودی کد یکتا بود که یک فیچر دوربین را ارزشمند کرد.

شمردن صریح حالت‌های شکست — تخصیص‌یافته، ناهماهنگ، کم، کاملاً رزرو — فرق یک دموی اسکن‌کننده است با ابزاری که یک فروشگاه بتواند روز شلوغ با آن کار کند.