The CreatorCon Call for Content is officially open! Get started here.

Catalog client script

larissaribe
Tera Contributor

I need help creating a catalog client script with these functions:

 

The field name is date_of_movement

 

If the current date is between the 1st and the 19th, the transaction date can be any date within the current month. (Limited to business days)

 

If the current date is greater than or equal to the 20th, the transaction date can only be from the month following the current month onwards. (Limiting to business days)

 

Translated with DeepL.com (free version)

8 REPLIES 8

SP22
Giga Sage

Hello @larissaribe,

1) onLoad Catalog Client Script (sets the allowed date range)
Type: onLoad
Applies to: the Catalog Item that contains the date_of_movement variable

(function onLoad() {
  var VAR = 'date_of_movement';

  // --- Helpers ---
  function pad(n) { return ('0' + n).slice(-2); }

  function ymd(d) {
    return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
  }

  function gdtFromYMD(y, m, d) {
    var gdt = new GlideDateTime(); // client-side GlideDateTime
    gdt.setValue(y + '-' + pad(m) + '-' + pad(d) + ' 00:00:00');
    return gdt;
  }

  function getFirstBusinessDay(year, monthZeroBased) {
    var d = new Date(year, monthZeroBased, 1);
    while (d.getDay() === 0 || d.getDay() === 6) {
      d.setDate(d.getDate() + 1);
    }
    return d;
  }

  function getLastBusinessDay(year, monthZeroBased) {
    // last calendar day of the month
    var d = new Date(year, monthZeroBased + 1, 0);
    while (d.getDay() === 0 || d.getDay() === 6) {
      d.setDate(d.getDate() - 1);
    }
    return d;
  }

  function gdtToYMD(gdt) {
    if (!gdt) return '';
    // gdt.getValue() returns 'YYYY-MM-DD HH:mm:ss'
    return gdt.getValue().substring(0, 10);
  }

  // --- Compute min/max based on today's date ---
  var now = new Date();
  var day = now.getDate();
  var y = now.getFullYear();
  var m = now.getMonth(); // 0-based

  var minGdt, maxGdt;

  if (day <= 19) {
    // Current month: from first business day to last business day
    var firstBiz = getFirstBusinessDay(y, m);
    var lastBiz  = getLastBusinessDay(y, m);

    minGdt = gdtFromYMD(firstBiz.getFullYear(), firstBiz.getMonth() + 1, firstBiz.getDate());
    maxGdt = gdtFromYMD(lastBiz.getFullYear(),  lastBiz.getMonth()  + 1, lastBiz.getDate());
  } else {
    // 20th or later: from first business day of NEXT month onwards (no max)
    var nextMonthFirst = new Date(y, m + 1, 1);
    var firstNextBiz = getFirstBusinessDay(nextMonthFirst.getFullYear(), nextMonthFirst.getMonth());

    minGdt = gdtFromYMD(firstNextBiz.getFullYear(), firstNextBiz.getMonth() + 1, firstNextBiz.getDate());
    maxGdt = null; // open-ended
  }

  // --- Enforce range with platform API ---
  if (typeof g_form.setDateRange === 'function') {
    // For catalog 'Date' variable, pass GlideDateTime objects; use null/'' for no bound
    g_form.setDateRange(VAR, minGdt, maxGdt || '');
  }

  // --- Fallback: enforce range in Service Portal via HTML5 min/max ---
  var ctrl = g_form.getControl(VAR);
  if (ctrl && typeof ctrl.setAttribute === 'function') {
    var minStr = gdtToYMD(minGdt);
    var maxStr = gdtToYMD(maxGdt);

    if (minStr) ctrl.setAttribute('min', minStr);
    if (maxStr) ctrl.setAttribute('max', maxStr);
    else ctrl.removeAttribute('max'); // open-ended
  }

  // Optional: clear value if it violates the new constraints
  var currentVal = g_form.getValue(VAR);
  if (currentVal) {
    // Trigger the onChange script to revalidate
    g_form.setValue(VAR, currentVal);
  }
})();

 

2) onChange Catalog Client Script (validates business day + range)
Type: onChange
Variable name: date_of_movement

function onChange(control, oldValue, newValue, isLoading) {
  if (isLoading) return;

  var VAR = 'date_of_movement';

  // --- Helpers ---
  function pad(n) { return ('0' + n).slice(-2); }

  function parseYMD(val) {
    // Expect 'YYYY-MM-DD...' (internal value). If format differs, Date(...) fallback.
    var m = /^(\d{4})-(\d{2})-(\d{2})/.exec(val || '');
    if (m) return new Date(parseInt(m[1],10), parseInt(m[2],10) - 1, parseInt(m[3],10));
    var d = new Date(val);
    return isNaN(d.getTime()) ? null : d;
  }

  function stripTime(d) { return new Date(d.getFullYear(), d.getMonth(), d.getDate()); }

  function getFirstBusinessDay(year, monthZeroBased) {
    var d = new Date(year, monthZeroBased, 1);
    while (d.getDay() === 0 || d.getDay() === 6) d.setDate(d.getDate() + 1);
    return d;
  }

  function getLastBusinessDay(year, monthZeroBased) {
    var d = new Date(year, monthZeroBased + 1, 0);
    while (d.getDay() === 0 || d.getDay() === 6) d.setDate(d.getDate() - 1);
    return d;
  }

  function error(msg) {
    g_form.showFieldMsg(VAR, msg, 'error', true);
    g_form.setValue(VAR, '');
  }

  if (!newValue) return; // ignore clears

  var selected = parseYMD(newValue);
  if (!selected) {
    error('Please choose a valid date.');
    return;
  }

  // 1) Business day check (Mon–Fri)
  var dow = selected.getDay(); // 0=Sun, 6=Sat
  if (dow === 0 || dow === 6) {
    error('Please choose a business day (Monday–Friday).');
    return;
  }

  // 2) Enforce month rules based on TODAY
  var today = new Date();
  var dayOfMonth = today.getDate();
  var y = today.getFullYear();
  var m = today.getMonth();

  var sel = stripTime(selected);

  if (dayOfMonth <= 19) {
    // Only business days within the CURRENT month
    var min = getFirstBusinessDay(y, m);
    var max = getLastBusinessDay(y, m);

    if (sel < stripTime(min) || sel > stripTime(max)) {
      error("Between the 1st and 19th, pick a business day within this month's dates.");
      return;
    }
  } else {
    // Only business days from NEXT month onwards
    var firstNextBiz = getFirstBusinessDay(y, m + 1);
    if (sel < stripTime(firstNextBiz)) {
      error('From the 20th onwards, pick a business day in next month or later.');
      return;
    }
  }
}

If this helped to answer your query, please mark it helpful & accept the solution.

Thanks
Santosh.P

larissaribe
Tera Contributor

Your code is showing this error in the console log "[SCRIPT:EXEC] Error while running Client Script "Date of movimention onLoad": ReferenceError: GlideDateTime is not defined". What should I do?

Onload client script:

could you please try below script and let me know the error your receiving.

// onLoad Catalog Client Script
(function onLoad() {
  var VAR = 'date_of_movement';

  // --- Helpers ---
  function pad(n) { return ('0' + n).slice(-2); }
  function ymd(d) { return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()); }

  function getFirstBusinessDay(year, monthZeroBased) {
    var d = new Date(year, monthZeroBased, 1);
    while (d.getDay() === 0 || d.getDay() === 6) { // Sun(0) or Sat(6)
      d.setDate(d.getDate() + 1);
    }
    return d;
  }

  function getLastBusinessDay(year, monthZeroBased) {
    var d = new Date(year, monthZeroBased + 1, 0); // last calendar day
    while (d.getDay() === 0 || d.getDay() === 6) {
      d.setDate(d.getDate() - 1);
    }
    return d;
  }

  // --- Compute min/max based on today's date ---
  var now = new Date();
  var day = now.getDate();
  var y = now.getFullYear();
  var m = now.getMonth(); // 0-based

  var minStr = '', maxStr = '';

  if (day <= 19) {
    // Current month: from first business day to last business day
    minStr = ymd(getFirstBusinessDay(y, m));
    maxStr = ymd(getLastBusinessDay(y, m));
  } else {
    // 20th or later: from first business day of NEXT month onwards (no max)
    minStr = ymd(getFirstBusinessDay(y, m + 1));
    maxStr = ''; // open-ended
  }

  // --- Enforce range with platform API (works in Catalog UI and SP) ---
  if (typeof g_form.setDateRange === 'function') {
    // Pass ISO date strings for a Date variable
    g_form.setDateRange(VAR, minStr || null, maxStr || null);
  }

  // --- Fallback: HTML5 min/max (especially for Service Portal) ---
  var ctrl = g_form.getControl(VAR);
  if (ctrl && typeof ctrl.setAttribute === 'function') {
    if (minStr) ctrl.setAttribute('min', minStr);
    if (maxStr) ctrl.setAttribute('max', maxStr);
    else ctrl.removeAttribute('max');
  }

  // Optional: re-trigger onChange to revalidate with new bounds
  var currentVal = g_form.getValue(VAR);
  if (currentVal) g_form.setValue(VAR, currentVal);
})();

 

 

Rafael Batistot
Kilo Patron

Hi @larissaribe 

 

See the onLoad script 

 

function onLoad() {
var dateField = g_form.getControl('date_of_movement');
if (!dateField) return;

var today = new Date();
var day = today.getDate();
var month = today.getMonth(); // 0-11
var year = today.getFullYear();

// Define minDate and maxDate
var minDate, maxDate;

if (day >= 1 && day <= 19) {
// Transaction date can be any business day in current month
minDate = new Date(year, month, 1); // 1st day of current month
maxDate = new Date(year, month + 1, 0); // Last day of current month
} else {
// Transaction date must be in next month onwards
minDate = new Date(year, month + 1, 1); // 1st day of next month
maxDate = new Date(year + 5, 11, 31); // optional far-future max
}

// Disable non-business days
g_form.setDatePicker('date_of_movement', {
minDate: minDate,
maxDate: maxDate,
beforeShowDay: function(date) {
var day = date.getDay();
return [(day != 0 && day != 6), '']; 
}
});
}

If you found this response helpful, please mark it as Helpful. If it fully answered your question, consider marking it as Correct. Doing so helps other users find accurate and useful information more easily.