Google app maker 使用Project Tracker模板发送电子邮件更改通知时出错

Google app maker 使用Project Tracker模板发送电子邮件更改通知时出错,google-app-maker,Google App Maker,短版: 我正在使用Project Tracker模板中的代码发送电子邮件,显示某个字段状态的更改(联系人姓名从:Billy->Susan更改) 当我有一个字段是日期而不是字符串时,一切都能正常工作。如果代码中有日期字段,则会出现以下错误: 模型“SystemOrdersHistory”中的“NewValue”字段应为“string”值,但找到了对象。错误:“SystemOrdersHistory”模型中的“NewValue”字段应为“string”值,但找到了对象。at onSystemOrde

短版:

我正在使用Project Tracker模板中的代码发送电子邮件,显示某个字段状态的更改(联系人姓名从:Billy->Susan更改)

当我有一个字段是日期而不是字符串时,一切都能正常工作。如果代码中有日期字段,则会出现以下错误:

模型“SystemOrdersHistory”中的“NewValue”字段应为“string”值,但找到了对象。错误:“SystemOrdersHistory”模型中的“NewValue”字段应为“string”值,但找到了对象。at onSystemOrdersSave(数据源:218)at models.SystemOrders.onSaveEvent:1

修改记录:(错误):“SystemOrdersHistory”模型中的“NewValue”字段需要“string”值,但找到了对象。

(错误):“SystemOrdersHistory”模型中的“NewValue”字段应为“string”值,但找到了对象。

任何帮助都将不胜感激


长版本

我正在使用下面的代码(根据模型和字段的名称进行调整)

每当我向函数“notifyAboutItemChanges”和“onSystemOrdersSave”添加日期字段(例如:DeliveryDate)时,我都会收到关于“需要字符串,但找到对象”的错误

注意:“历史”模型中的OldValue和NewValue字段都是字符串

通知服务器脚本:

/**
 * Sends email.
 * @param {!string} to - email address of a recipient.
 * @param {!string} subject - subject of email message.
 * @param {!string} body - body of email message.
 */
function sendEmail_(to, subject, body) {
  try {
    MailApp.sendEmail({
      to: to,
      subject: subject,
      htmlBody: body,
      noReply: true
    });
   } catch (e) {
    // Suppressing errors in email sending because email notifications
    //   are not critical for the functioning of the app.
    console.error(JSON.stringify(e));
  }
}


/**
 * Sends email notification about recent project item changes to item owner
 *     and assignee.
 * @param {!Array<ItemHistory>} changes - list of recent project item changes.
 */
function notifyAboutItemChanges_(changes) {
  if (!changes || changes.length < 2) {
    return;
  }

  var settings = getAppSettingsRecord_()[0];

  if (!settings.EnableEmailNotifications) {
    return;
  }

  var data = {
    appUrl: settings.AppUrl,
    itemShowName: changes[0].ShowName,
    itemUsersPosition: changes[0].UsersPosition,
    itemDeliveryInfo: changes[0].DeliveryInfo,
    itemDeliveryDate: changes[0].DeliveryDate,
    itemKey: changes[0]._key,
    itemName: changes[0].Name,
    modifiedBy: changes[0].ModifiedBy,
    changes: changes
  };

  // Email subject.
  var subjectTemplate =
      HtmlService.createTemplate(settings.NotificationEmailSubject);

  subjectTemplate.data = data;

  var subject = subjectTemplate.evaluate().getContent();

  // Email body.
  var emailTemplate =
      HtmlService.createTemplate(settings.NotificationEmailBody);

  emailTemplate.data = data;

  var htmlBody = emailTemplate.evaluate().getContent();

  sendEmail_('user@gmail.com', subject, htmlBody);
/**
*发送电子邮件。
*@param{!string}收件人的电子邮件地址。
*@param{!string}subject-电子邮件的主题。
*@param{!string}body-电子邮件正文。
*/
功能发送电子邮件(收件人、主题、正文){
试一试{
MailApp.sendmail({
致:致,,
主题:主题,,
htmlBody:body,
诺雷普利:是的
});
}捕获(e){
//抑制电子邮件发送中的错误,因为电子邮件通知
//对于应用程序的功能来说并不重要。
console.error(JSON.stringify(e));
}
}
/**
*向项目所有者发送有关最近项目项更改的电子邮件通知
*和受让人。
*@param{!Array}更改-最近项目项更改的列表。
*/
函数notifyAboutItemChanges(更改){
如果(!changes | | changes.length<2){
返回;
}
var settings=getAppSettingsRecord([0];
如果(!settings.enableMailNotifications){
返回;
}
风险值数据={
appUrl:settings.appUrl,
itemShowName:更改[0]。ShowName,
itemUsersPosition:更改[0]。UsersPosition,
itemDeliveryInfo:更改[0]。DeliveryInfo,
itemDeliveryDate:更改[0]。DeliveryDate,
itemKey:更改[0]。\u键,
itemName:更改[0]。名称,
modifiedBy:更改[0]。modifiedBy,
变化:变化
};
//电子邮件主题。
var主题模板=
HtmlService.createTemplate(settings.NotificationEmailSubject);
subjectTemplate.data=数据;
var subject=subjectTemplate.evaluate().getContent();
//电子邮件正文。
var电子邮件模板=
HtmlService.createTemplate(settings.NotificationEmailBody);
emailTemplate.data=数据;
var htmlBody=emailTemplate.evaluate().getContent();
发送电子邮件user@gmail.com,主题,正文);
数据源服务器脚本:

/**
 * Item key URL parameter.
 */
var ITEM_KEY = 'itemKey';


/**
 * Checks that Application Settings record already exists.
 *     Otherwise creates a new one.
 * @return {!Array<AppSettings>} app settings record as an array.
 */
function getAppSettingsRecord_() {
  var newQuery = app.models.AppSettings.newQuery();
  var settingsRecords = newQuery.run();

  if (settingsRecords.length > 1) {
    console.warn('There is more than one(%s) App Settings entries' + 
                 'in the database', settingsRecords.length);
  }

  if (settingsRecords.length === 0) {
    var settingsRecord = app.models.AppSettings.newRecord();

    settingsRecord.AppUrl = ScriptApp.getService().getUrl();
    settingsRecord.NotificationEmailSubject =
      'A change has been made to <?= data.itemShowName?>: <?= data.itemUsersPosition?>';

    settingsRecord.NotificationEmailBody =
      'Hello!\n<br/>\n<p><b><?= data.modifiedBy ?></b> ' +
      'made the following changes: </p>\n' +
      '<? for (var i = 1; i < data.changes.length; i++) {\n' +
      '\tvar change = data.changes[i]; ?>\n' +
      '\t<b><?= change.FieldName ?>: </b>\n' +
      '\t<? if (change.FieldName === "Comment") { ?>\n' +
      '\t\t<div style="white-space: pre-line;"><?= change.NewValue ?></div>' +
      '\n\t<? } else { ?>\n ' +
      '\t\t<?= change.OldValue ?> &#8594; <?= change.NewValue ?>' +
      '\n\t<? } ?>\n\t<br/>\n' +
      '<? } ?>\n<br/>\n' +
      '<a href="<?= data.appUrl ?>?' + ITEM_KEY + '=<?= data.itemKey ?>' +
      '#EditItem" target="_blank">Go to the project item</a>';

    app.saveRecords([settingsRecord]);

    return [settingsRecord];
  } else {
    return settingsRecords;
  }
}

/**
 * Populates project record with required data on project create event.
 * @param {!Project} project - project being created.
 */
function onProjectCreate_(project) {
  var date = new Date();

  project.CreatedDate = date;
  project.ModifiedDate = date;
  project.ModifiedBy = currentUserEmail_();
}


/**
 * Audits project on changes.
 * @param {!Project} project - project being modified.
 */
function onProjectSave_(project) {
  project.ModifiedDate = new Date();
  project.ModifiedBy = currentUserEmail_();
}


/**
 * Populates project item with required data on item create event, adds
 *     comment entry to the project item history.
 * @param {!SystemOrders} SystemOrders - project item being created.
 */
function onSystemOrdersCreate_(SystemOrders) {
  var date = new Date();
  var editor = currentUserEmail_();

  if (SystemOrders.Comment) {
    SystemOrders.Comment = SystemOrders.Comment.trim();
  }

  SystemOrders.CreatedDate = date;
  SystemOrders.Owner = editor;
  SystemOrders.ModifiedDate = date;
  SystemOrders.ModifiedBy = editor;

  if (SystemOrders.Comment) {
    var history = app.models.SystemOrdersHistory.newRecord();

    history.CreatedBy = currentUserEmail_();
    history.CreatedDate = new Date();
    history.FieldName = 'Comment';
    history.NewValue = SystemOrders.Comment;

    app.saveRecords([history]);

    SystemOrders.History.push(history);
  }

}


/**
 * Calculates history entries sum for {Array<SystemOrders>}.
 * @param {!number} historySum - the accumulated number of history entries
 *     previously returned in the last invocation of the callback, or
 *     initialValue, if supplied.
 * @param {!SystemOrders} SystemOrders - the current {SystemOrders} being
 *     processed in the array.
 * @return {!number} history entries sum.
 */
function sumHistory_(historySum, SystemOrders) {
  return historySum + SystemOrders.History.length;
}


/**
 * Calculates potential project deletion impact.
 * Throws an error if there is no project with the key provided.
 * @param {!string} projectKey - project key to calculate deletion impact.
 */
function getDeleteProjectImpact(projectKey) {
  var projectQuery = app.models.Project.newQuery();

  projectQuery.prefetch.Items._add();
  projectQuery.prefetch.Items.History._add();
  projectQuery.filters._key._equals = projectKey;

  var projects = projectQuery.run();

  if (projects.length === 0) {
    throw new Error('Project with key ' + projectKey + ' was not found.');
  }

  var SystemOrderss = projects[0].Items;

  return {
    affectedItems: SystemOrderss.length,
    affectedHistory: SystemOrderss.reduce(sumHistory_, 0)
  };
}


/**
 * Checks that project item readonly fields were not modified.
 * Throws an error if user attempts to modify read only fields.
 * @param {!SystemOrders} record - modified project item.
 * @param {!SystemOrders} oldRecord - project item before modification.
 */
function validateItemChange_(record, oldRecord) {
  var readonlyFields = [
    'CreatedDate',
    'ModifiedBy',
    'ModifiedDate',
    'Owner'
  ];

  for (var i = 0; i < readonlyFields.length; i++) {
    var field = readonlyFields[i];
    var newValue = record[field];
    var oldValue = oldRecord[field];
    var isDate = newValue instanceof Date && oldValue instanceof Date;

    if (isDate === true) {
      newValue = record[field].getDate();
      oldValue = oldRecord[field].getDate();
    }

    if (newValue === oldValue) {
      continue;
    }

    throw new Error(field + ' field is read only');
  }
}


/**
 * Handles project item change event, creates history entries for each changed
 *     field.
 * @param {!SystemOrders} record - modified project item.
 * @param {!SystemOrders} oldRecord - project item before modification.
 */
function onSystemOrdersSave_(record, oldRecord) {
  validateItemChange_(record, oldRecord);

  var editableFields = [
    'ShowName',
    'UsersPosition',
    'DeliveryInfo',
    'DeliveryDate'
    ];

  var editor = currentUserEmail_();
  var date = new Date();
  var changes = [record];

  record.ModifiedBy = editor;
  record.ModifiedDate = date;

  for (var i = 0; i < editableFields.length; i++) {
    var field = editableFields[i];
    var newValue = record[field];
    var oldValue = oldRecord[field];

    if (newValue !== oldValue) {
      var history = app.models.SystemOrdersHistory.newRecord();

      history.Item = record;
      history.CreatedBy = editor;
      history.CreatedDate = date;
      history.FieldName = field;
      history.NewValue = newValue;
      history.OldValue = oldValue;

      changes.push(history);
    }
  }

  app.saveRecords(changes);

  notifyAboutItemChanges_(changes);
}


/**
 * Counts project items by some grouping criteria(field).
 * @param {!string} projectKey - project key to calculate stats.
 * @param {!string} grouping - project item field to group items by.
 * @param {!Array<string>} groupingValues - possible field values.
 * @return {!Array<SystemOrderssBreakdown>} grouped project items counts.
 */
function getSystemOrderssBreakdown_(projectKey, grouping, groupingValues) {
  if (!grouping || !groupingValues || groupingValues.length === 0) {
    return [];
  }

  var itemsQuery = app.models.SystemOrders.newQuery();

  itemsQuery.prefetch.Project._add();
  itemsQuery.filters.Project._key._equals = projectKey;

  var items = itemsQuery.run();

  if (items.length === 0) {
    return [];
  }

  var records = [];
  var map = {};

  for (var i = 0; i < items.length; i++) {
    var itemGrouping = items[i][grouping];

    if (!map[itemGrouping]) {
      map[itemGrouping] = 0;
    }

    map[itemGrouping]++;
  }

  for (i = 0; i < groupingValues.length; i++) {
    var breakdownRecord = app.models.SystemOrderssBreakdown.newRecord();
    var groupingValue = groupingValues[i];

    breakdownRecord.Grouping = groupingValue;
    breakdownRecord.ItemsCount = map[groupingValue] || 0;

    records.push(breakdownRecord);
  }

  return records;
}
/**
*项目键URL参数。
*/
var ITEM_KEY='itemKey';
/**
*检查应用程序设置记录是否已存在。
*否则将创建一个新的。
*@return{!Array';
应用程序保存记录([settingsRecord]);
返回[设置记录];
}否则{
返回设置记录;
}
}
/**
*使用项目创建事件上的必需数据填充项目记录。
*@param{!Project}Project-正在创建项目。
*/
函数onProjectCreate(项目){
变量日期=新日期();
project.CreatedDate=日期;
project.ModifiedDate=日期;
project.ModifiedBy=currentUserEmail_u2;();
}
/**
*审核项目变更。
*@param{!Project}Project-正在修改项目。
*/
函数onProjectSave(项目){
project.ModifiedDate=新日期();
project.ModifiedBy=currentUserEmail_u2;();
}
/**
*在项目创建事件中使用所需数据填充项目项目,添加
*项目项历史记录的注释条目。
*@param{!SystemOrders}SystemOrders-正在创建项目项。
*/
函数onSystemOrdersCreate(系统订单){
变量日期=新日期();
var editor=currentUserEmail_();
if(SystemOrders.Comment){
SystemOrders.Comment=SystemOrders.Comment.trim();
}
SystemOrders.CreatedDate=日期;
SystemOrders.Owner=editor;
SystemOrders.ModifiedDate=日期;
SystemOrders.ModifiedBy=编辑器;
if(SystemOrders.Comment){
var history=app.models.SystemOrdersHistory.newRecord();
history.CreatedBy=currentUserEmail_u2;();
history.CreatedDate=新日期();
history.FieldName='Comment';
history.NewValue=SystemOrders.Comment;
应用程序保存记录([历史]);
SystemOrders.History.push(历史);
}
}
/**
*计算{Array}的历史记录项总和。
*@param{!number}historySum-历史记录条目的累积数量
*以前在最后一次调用回调时返回的,或
*初始值(如果提供)。
*@param{!SystemOrders}SystemOrders-当前{SystemOrders}为
*在数组中处理。
*@return{!number}历史记录项总和。
*/
函数sumHistory(历史总和,系统订单){
返回historySum+SystemOrders.History.length;
}
/**
*计算潜在的项目删除影响。
*如果没有提供密钥的项目,则引发错误。
*@param{!string}projectKey-用于计算删除影响的项目密钥。
*/
函数getDeleteProjectImpact(projectKey){
var projectQuery=app.models.Project.newQuery();
projectQuery.prefetch.Items._add();
projectQuery.prefetch.Items.History._add();
projectQuery.filters.\u key.\u=projectKey;
var projects=projectQuery.run();
如果(projects.length==0){
抛出新错误('Project with key'+projectKe