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)

5 REPLIES 5

SP22
Giga Sage
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

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), '']; 
}
});
}

kaushal_snow
Mega Sage

Hi @larissaribe ,

 

By writing a catalog onChange client script on date_of_movement that computes todaya date, checks whether the day is ≤ 19 or ≥ 20, and depending on that either restricts the selected date to business days within the current month or only dates from the next month onward (while rejecting weekends), and additionally include a matching onSubmit script to enforce the same logic before submission so invalid dates are blocked even if the onChange check is bypassed...

 

Let me know if you need code for this...!!

 

If you found my response helpful, please mark it as ‘Accept as Solution’ and ‘Helpful’. This helps other community members find the right answer more easily and supports the community.

 

Thanks and Regards,
Kaushal Kumar Jha - ServiceNow Consultant - Lets connect on Linkedin: https://www.linkedin.com/in/kaushalkrjha/

tejas1111
Tera Contributor

Hi @larissaribe ,

 

try this catalgoue client script simple logics

 

function onLoad() {
   // your field name and gets iits control
   var name = 'date_of_movement';
  var control = g_form.getControl(name) || g_form.getControl('variables.'+name);
  //alert("control == "+control);

  var today = new Date();
  var d = today.getDate();

 //checks its weekly
  function isWeekday(dt){ var day = dt.getDay(); return day !== 0 && day !== 6; }

  // get first weekday of month
  var first = new Date(today.getFullYear(), today.getMonth(), 1);
  while(!isWeekday(first)) first.setDate(first.getDate()+1);

//checking date in betn 1 to 19 or not 

  if (d >= 1 && d <= 19) {
    // allow this month's business days only
    var last = new Date(today.getFullYear(), today.getMonth()+1, 0);
    while(!isWeekday(last)) last.setDate(last.getDate()-1);
    control.setAttribute('min', first.toISOString().slice(0,10));
    control.setAttribute('max', last.toISOString().slice(0,10));
    g_form.showFieldMsg(name, 'Allowed: business days this month', 'info', false);
  } else {
    // allow from first business day of next month onwards
    var nextFirst = new Date(today.getFullYear(), today.getMonth()+1, 1);
    while(!isWeekday(nextFirst)) nextFirst.setDate(nextFirst.getDate()+1);
    control.setAttribute('min', nextFirst.toISOString().slice(0,10));
    control.removeAttribute('max');
    g_form.showFieldMsg(name, 'Allowed: business days from next month onwards', 'info', false);
  }
   
}

 

Let me know if this not working or  share sceenshorts of error you facing 

or let me know if you want onchange or onsubmit client scripts. 

tejas1111_0-1758942925509.png