<commit_before>import { computed, action } from 'mobx';
import {
  BaseModel, identifiedBy, field, identifier, belongsTo,
} from '../base';
import { TimeStore } from '../../flux/time';
import moment from 'moment';
import { pick } from 'lodash';
import Payments from '../payments';

@identifiedBy('course/student')
export default class CourseStudent extends BaseModel {
  @identifier id;

  @field name;
  @field uuid;
  @field first_name;
  @field last_name;
  @field is_active;
  @field is_comped;
  @field is_paid;
  @field is_refund_allowed;
  @field is_refund_pending;
  @field({ type: 'date' }) payment_due_at;
  @field prompt_student_to_pay;

  @field period_id;
  @field role_id;
  @field student_identifier;

  @belongsTo course;
  @belongsTo({ model: 'course/roster' }) roster;

  @computed get courseId() {
    return this.course ? this.courseId : this.roster.course.id;
  }

  get mustPayImmediately() {
    return Boolean(this.needsPayment && moment(this.payment_due_at).isBefore(TimeStore.getNow()));
  }

  get trialDaysRemaining() {
    return moment(this.payment_due_at).diff(TimeStore.getNow(), 'days');
  }

  onSaved({ data }) {
    this.update(data);
  }

  // corresponds to how the BE sets the "prompt_student_to_pay" flag
  // We calculate it ourself so that it can change when payments is enabled/disabled
  // https://github.com/openstax/tutor-server/blob/master/app/representers/api/v1/student_representer.rb#L68-L84
  @computed get needsPayment() {
    return Boolean(
      Payments.config.is_enabled && this.isUnPaid
    );
  }

  @computed get isUnPaid() {
    return Boolean(<commit_msg>Don't return a negative # for days remaining<commit_after>import { computed, action } from 'mobx';
import {
  BaseModel, identifiedBy, field, identifier, belongsTo,
} from '../base';
import { TimeStore } from '../../flux/time';
import moment from 'moment';
import { pick } from 'lodash';
import Payments from '../payments';

@identifiedBy('course/student')
export default class CourseStudent extends BaseModel {
  @identifier id;

  @field name;
  @field uuid;
  @field first_name;
  @field last_name;
  @field is_active;
  @field is_comped;
  @field is_paid;
  @field is_refund_allowed;
  @field is_refund_pending;
  @field({ type: 'date' }) payment_due_at;
  @field prompt_student_to_pay;

  @field period_id;
  @field role_id;
  @field student_identifier;

  @belongsTo course;
  @belongsTo({ model: 'course/roster' }) roster;

  @computed get courseId() {
    return this.course ? this.courseId : this.roster.course.id;
  }

  get mustPayImmediately() {
    return Boolean(this.needsPayment && moment(this.payment_due_at).isBefore(TimeStore.getNow()));
  }

  get trialDaysRemaining() {
    return Math.max(moment(this.payment_due_at).diff(TimeStore.getNow(), 'days'), 0);
  }

  onSaved({ data }) {
    this.update(data);
  }

  // corresponds to how the BE sets the "prompt_student_to_pay" flag
  // We calculate it ourself so that it can change when payments is enabled/disabled
  // https://github.com/openstax/tutor-server/blob/master/app/representers/api/v1/student_representer.rb#L68-L84
  @computed get needsPayment() {
    return Boolean(
      Payments.config.is_enabled && this.isUnPaid
    );
  }

  @computed get isUnPaid() {
    return Boolean(
{'fraction_non_alphanumeric': 0.12804878048780488, 'fraction_numerical': 0.003353658536585366, 'mean_word_length': 4.047692307692308, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3379563', 'n_tokens_mistral': 1121, 'n_tokens_neox': 1077, 'n_words': 264}