اگر مارکت‌پلیس می‌سازید، سبد خرید و کاتالوگ سخت‌ترین بخش نیستند. سخت‌ترین بخش پول است: پولی که از مشتری گرفته شده، بین چند فروشنده تقسیم می‌شود، مدتی نگه داشته می‌شود، و در نهایت پرداخت.

و آزمون واقعی این است: وقتی فروشنده می‌پرسد «چرا مانده‌ی من این عدد است و نه آن عدد»، آیا جوابی دارید که سطر به سطر قابل نشان دادن باشد؟

اشتباه رایج: مانده به‌عنوان یک ستون

مدل ساده این است که برای هر فروشنده یک ستون «مانده» نگه دارید و با هر فروش زیادش کنید و با هر پرداخت کمش.

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

مدل درست: دفتر ثبت رویداد

به‌جای نگه داشتن مانده، رویدادها را ثبت کنید:

  • فروش یک قلم از فروشنده، با مبلغ و کمیسیون
  • مرجوعی و بازپرداخت
  • کسر بابت جریمه یا هزینه
  • پرداخت تسویه

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

این ساختار یک ویژگی مهم دارد: وقتی قاعده‌ی کمیسیون وسط سال عوض می‌شود، می‌توانید محاسبه را با قاعده‌ی جدید برای همان دوره دوباره اجرا کنید و هر دو عدد را کنار هم نشان دهید.

در مارکت‌پلیسی که برای بازار آلمان ساختیم، دفتر تسویه در سطح پایگاه داده UPDATE و DELETE را رد می‌کند. اصلاح فقط با سند متقابل انجام می‌شود، یعنی حتی یک باگ در کد هم نمی‌تواند تاریخچه را بازنویسی کند. این الزام قانون آلمان بود، ولی برای هر مارکت‌پلیسی تصمیم درستی است.

نگهداشت ذخیره: پولی که هنوز مال فروشنده نیست

مشتری امروز خرید کرده و مهلت مرجوعی چهارده روز است. اگر امروز به فروشنده پرداخت کنید و مشتری روز دهم مرجوع کند، پول را از کجا برمی‌گردانید؟

راه‌حل نگهداشت ذخیره است: بخشی از مبلغ تا پایان مهلت مرجوعی نگه داشته می‌شود و بعد آزاد می‌شود. این باید:

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

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

سه چیز که باید قفل بگیرند

هرچه درباره‌ی پول تصمیم می‌گیرد، باید در یک تراکنش صریح و با قفل سطر انجام شود:

مصرف کوپن. کوپنی که سقف صد بار دارد نباید صد و ده بار مصرف شود. شماره‌گذاری فاکتور. شماره‌ی فاکتور نباید حفره داشته باشد و نباید تکراری باشد. پرداخت تسویه. یک مانده نباید دو بار پرداخت شود.

و هر سه باید تستی داشته باشند که درخواست‌های موازی واقعی را روی پایگاه داده‌ی واقعی اجرا کند. این نقص‌ها جای دیگری دیده نمی‌شوند.

اگر می‌خواهید ببینید این ساختار در عمل چه شکلی است، بستر مارکت‌پلیس ما روی همین مدل ساخته شده.