• בלוג
  • סיקור באג - הארכת מנוי שלא עבדה

סיקור באג - הארכת מנוי שלא עבדה

חשבתי שאני בונה את הפיצ'ר הכי קל בעולם, אבל כמו שקורה הרבה פעמים במערכות תוכנה, כשפיצ'ר חדש פוגש קוד קיים הוא עלול לדחוף את הקוד בכיוונים לא צפויים. כך קרה עם פיצ'ר הארכת מנוי בתשלום מראש.

המנגנון של מנוי בתשלום מראש אומר שאתם יכולים לקנות מנוי לתקופה לבחירתכם, פשוט משלמים מראש על כל החודשים ואז לא צריך לשלם פעם בחודש. אבל אנשים יכולים לטעות ולפעמים אנחנו קונים מנוי לחודשיים ואז אחרי חודש מגלים שייקח לנו יותר זמן לסיים את הקורס ורוצים להאריך. במצב של הארכה אם אני משלם מראש על חודשיים אני רוצה שהחודשיים האלה יצטרפו לתקופת המנוי הקיים שלי, כלומר בן אדם שקנה מנוי לשלושה חודשים, ואז אחרי חודש קנה עוד חודשיים מצפה שהחודשיים הנוספים יתחילו מהרגע שהשלושה חודשים הראשונים נגמרו (ולא מרגע שהוא קונה אותם). זה מצב חדש שקודם לא נדרשנו להתמודד איתו.

הפונקציה שטיפלה בעדכון פרטי משתמש אחרי רכישה נראתה במקור כך:

def subscribe(duration)
    self.subscription_end_date = (Time.zone.now + duration)
end

אבל ברגע שאנחנו מוסיפים אפשרות למשתמש "להאריך" מנוי יש לשנות את הפונקציה. צריך לבדוק אם לאותו משתמש יש כבר מנוי קיים, ואם כן להאריך את המנוי. קל? לא לגמרי. זה היה הניסיון הראשון עם הטעות:

def subscribe(duration)
    self.subscription_end_date = ((subscription_end_date || Time.zone.now) + duration)
end

כל בדיקות היחידה ובדיקות המערכת שהרצתי לא עלו על הבעיה, ואולי זה הלקח כאן. בדיקות עוזרות בבדיקת מצבים שאפשר לחשוב עליהם, אבל באגים נוטים להופיע באזורים שאנחנו לא חושבים עליהם. לפחות עד שהם מגיעים.

במקרה שלנו הבאג מתגלה כשמשתמש שכבר היה לו מנוי בעבר מנסה לרכוש מנוי חדש. במצב כזה ה subscription_end_date הוא תאריך בעבר, ו"תוספת" הזמן למנוי מצטרפת למועד המקורי בו המנוי פג תוקף, כך שגם אחרי תשלום לאותו משתמש עדיין אין מנוי בתוקף.

וכמו הרבה באגים, גם כאן אחרי שרואים את הבעיה הפיתרון הוא פשוט טיפול במקרה הנוסף. הקוד ב Ruby לתיקון היה:

def subscribe(duration)
    existing_subscription_period = if subscription_end_date.present? && Time.zone.now < subscription_end_date
      subscription_end_date
    else
      Time.zone.now
    end

    self.subscription_end_date = (existing_subscription_period + duration)
end

וכמו תמיד בפוסטים כאלה אני מזכיר שאם אתם נתקלים בדברים באתר שלא עובדים כמו שאתם חושבים שצריכים לעבוד, בבקשה אל תקחו ללב ועדכנו בטופס צור קשר. אנחנו עדיין בריקושטים מה Rewrite אבל לאט לאט נסדר את כל הבעיות.