<commit_before>import events from 'events';

// Workflow State
export const WORKFLOW_STATE_RUNNING = 'running';
export const WORKFLOW_STATE_PAUSED = 'paused';
export const WORKFLOW_STATE_IDLE = 'idle';

class Workflow extends events.EventEmitter {
    state = WORKFLOW_STATE_IDLE;

    start() {
        if (this.state !== WORKFLOW_STATE_RUNNING) {
            this.state = WORKFLOW_STATE_RUNNING;
            this.emit('start');
        }
    }
    stop() {
        if (this.state !== WORKFLOW_STATE_IDLE) {
            this.state = WORKFLOW_STATE_IDLE;
            this.emit('stop');
        }
    }
    pause() {
        if (this.state === WORKFLOW_STATE_RUNNING) {
            this.state = WORKFLOW_STATE_PAUSED;
            this.emit('pause');
        }
    }
    resume() {
        if (this.state === WORKFLOW_STATE_PAUSED) {
            this.state = WORKFLOW_STATE_RUNNING;
            this.emit('resume');
        }
    }
}

export default Workflow;
<commit_msg>Workflow helper functions: isRunning(), isPaused(), isIdle()<commit_after>import events from 'events';

// Workflow State
export const WORKFLOW_STATE_RUNNING = 'running';
export const WORKFLOW_STATE_PAUSED = 'paused';
export const WORKFLOW_STATE_IDLE = 'idle';

class Workflow extends events.EventEmitter {
    state = WORKFLOW_STATE_IDLE;

    isRunning() {
        return this.state === WORKFLOW_STATE_RUNNING;
    }
    isPaused() {
        return this.state === WORKFLOW_STATE_PAUSED;
    }
    isIdle() {
        return this.state === WORKFLOW_STATE_IDLE;
    }
    start() {
        if (this.state !== WORKFLOW_STATE_RUNNING) {
            this.state = WORKFLOW_STATE_RUNNING;
            this.emit('start');
        }
    }
    stop() {
        if (this.state !== WORKFLOW_STATE_IDLE) {
            this.state = WORKFLOW_STATE_IDLE;
            this.emit('stop');
        }
    }
    pause() {
        if (this.state === WORKFLOW_STATE_RUNNING) {
            this.state = WORKFLOW_STATE_PAUSED;
            this.emit('pause');
        }
    }
    resume() {
        if (this.state === WORKFLOW_STATE_PAUSED) {
            this.state = WORKFLOW_STATE_RUNNING;
            this.emit('resume');
        }
    }
}

export default Workflow;
<|endoftext|>


<commit_before>import Sequelize from "sequelize"
import { orm } from "./../../server/database"

import { inspect } from "util"

export default definition => definition(orm.define.bind(orm), Sequelize)

export const __useDefault = true
<commit_msg>remove extraneous select<commit_after>import Sequelize from "sequelize"
import { orm } from "./../../server/database"

export default definition => definition(orm.define.bind(orm), Sequelize)

export const __useDefault = true
<|endoftext|>


<commit_before>/*!
    Copyright (C) 2015 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: ivan@reciprocitylabs.com
    Maintained By: ivan@reciprocitylabs.com
*/

(function(can, $) {
  "use strict";
  var MapperModel = can.Map({
      type: "",
      contact: {},
      term: "",
      model: {},
      bindings: {},
      isLoading: false,
      allSelected: false,
      selected: new can.List(),
      entries: new can.List(),
      types: can.compute(function () {
        var selector_list = GGRC.Mappings.get_canonical_mappings_for(GGRC.page_model.type),
            groups = {
              "all_objects": {
                name: "All Objects",
                value: "AllObject",
                plural: "allobjects",
                singular: "AllObject",
                models: []
              },
              "entities": {
                name: "People/Groups",
                items: []
              },
              "business": {
                name: "Assets/Business",
                items: []
              },
              "governance": {
                name: "Governance",
                items: []
              }
            };

        can.each(selector_list, function (model, model_name) {
          if (!model_name || ~["workflow"].indexOf(model_name.toLowerCase())) {
            return;
          }
          var cms_model = CMS.Models[model_name],
              group = !groups[cms_model.category] ? "governance" : cms_model.category;

          groups[group]["items"].push({
            name: cms_model.title_plural,
            value: cms_model.shortName,
            singular: cms_model.shortName,
            plural: cms_model.title_plural.toLowerCase().replace(/\s+/, "_"),
            isSelected: cms_model.shortName === this.type
          });
          groups["all_objects"]["models"].push(cms_model.shortName);
        }, this);
        return groups;
      })
    });

  can.Component.extend({
    tag: "modal-mapper",
    template: "<content />",
    scope: function (attrs, parentScope, el) {
      var $el = $(el),
          mapperInst = new MapperModel({
            type: $el.attr("type"),
            join_object_id: $el.attr("join-object-id"),
            object: $el.attr("object"),
          });
      return {
        mapper: mapperInst
      };
    },
    events: {
      "inserted": function () {
        this.setModel();
        this.setBinding();
      },
      ".modal-footer .btn-map click": function (el, ev) {
        ev.preventDefault();
        if (el.hasClass("disabled")) {
          return;
        }
        var instance = GGRC.page_instance(),
            data = {},
            deffer = [];

        data["context"] = null;
        data["source"] = {
          href: instance.href,
          type: instance.type,
          id: instance.id
        };
        this.scope.attr("isLoading", true);
        _.each(this.scope.attr("mapper.selected"), function (desination) {
          data["destination"] = desination;
          var model = new CMS.Models.Relationship(data);

          deffer.push(model.save());
        });
        $.when.apply($, deffer).then(function () {
          this.scope.attr("isLoading", false);
          // TODO: Find proper way to dismiss the modal
          this.element.find(".modal-dismiss").trigger("click");
        }.bind(this));
      },
      "setBinding": function () {
        var selected = CMS.Models.get_instance(this.scope.attr("mapper.object"), this.scope.attr("mapper.join_object_id")),
            binding = selected.get_binding(this.scope.attr("mapper.model.plural").toLowerCase());

        binding.refresh_list().then(function (mappings) {
          can.each(mappings, function (mapping) {
            this.scope.attr("mapper.bindings")[mapping.instance.id] = mapping;
          }, this);
        }.bind(this));
      },
      "setModel": function () {
        var type = this.scope.attr("mapper.type"),
            types = this.scope.attr("mapper.types");
        if (type === "AllObject") {
          return this.scope.attr("mapper.model", types["all_objects"]);
        }
        types = _.reduce(_.values(types), function (memo, val) {
          if (val.items) {
            return memo.concat(val.items);
          }
          return memo;
        }, []);
        this.scope.attr("mapper.model", _.findWhere(types, {value: type}));
      },
      "{mapper.type} change": function () {
        this.scope.attr("mapper.term", "");
        this.scope.attr("mapper.contact", {});
        this.setModel();
        this.setBinding();
      },
      "#search-by-owner autocomplete:select": function (el, ev, data) {
        this.scope.attr("mapper.contact", data.item);
      },
      "#search-by-owner keyup": function (el, ev) {
        if (!el.val()) {
          this.scope.attr("mapper.contact", {});
        }
      },
      "allSelected": function () {
        var selected = this.scope.attr("mapper.selected"),
            entries = this.scope.attr("mapper.entries");

        this.scope.attr("mapper.allSelected", selected.length === entries.length);
      },
      "{mapper.entries} length": "allSelected",
      "{mapper.selected} length": "allSelected"
    }
  });
  can.Component.extend({
    tag: "mapper-results",
    template: "<content />",
    scope: {
      "items-per-page": "@",
      page: 0,
      options: new can.List(),
      select_all: false,
      pageLoading: false
    },
    events: {
      "inserted":  function () {
        this.element.find(".results-wrap").cms_controllers_infinite_scroll();
        this.getResults();
      },
      ".modalSearchButton click": "getResults",
      "{scope} type": "getResults",
      ".results-wrap scrollNext": "drawPage",
      ".tree-item .openclose click": function (el, ev) {
        ev.preventDefault();
        el.openclose();
      },
      ".object-check-all change": function (el, ev) {
        var que = new RefreshQueue(),
            entries = this.scope.attr("entries");

        this.scope.attr("select_all", true);
        this.scope.attr("isloading", true);
        que.enqueue(entries).trigger().then(function (models) {
          this.scope.attr("isloading", false);
          this.scope.attr("selected", _.map(models, function (model) {
            return {
              id: model.id,
              type: model.type,
              href: model.href
            };
          }));
        }.bind(this));
      },
      ".tree-item .object-check-single change": function (el, ev) {
        if (el.hasClass("disabled")) {
          return;
        }

        var uid = el.closest(".tree-item").data("id"),
            isChecked = el.prop("checked"),
            item = _.find(this.scope.attr("options"), function (option) {
                return option.instance.id === uid;
              }),
            selected = this.scope.attr("selected"),
            needle = {id: item.instance.id},
            index;

        if (!_.findWhere(selected, needle)) {
          selected.push({
            id: item.instance.id,
            type: item.instance.type,
            href: item.instance.href
          });
        } else {
          index = _.findIndex(selected, needle);
          selected.splice(index, 1);
        }
      },
      "drawPage": function () {
        if (this.scope.attr("pageLoading") || this.scope.attr("lastPage")) {
          return;
        }
        var que = new RefreshQueue(),
            page = this.scope.attr("page"),
            next_page = page + 1,
            per_page = +this.scope.attr("items-per-page"),
            page_items = this.scope.attr("entries").slice(page * per_page, next_page * per_page),
            options = this.scope.attr("options");

        if (!page_items.length) {
          return;
        }
        this.scope.attr("pageLoading", true);
        que.enqueue(page_items).trigger().then(function (models) {
          this.scope.attr("pageLoading", false);
          this.scope.attr("page", next_page);
          options.push.apply(options, can.map(models, function (model) {
            var selected = CMS.Models.get_instance(this.scope.attr("mapper.object"), this.scope.attr("mapper.join_object_id")),
                binding = selected.get_binding(this.scope.attr("mapper.model.plural").toLowerCase()),
                bindings = this.scope.attr("mapper.bindings");

            if (bindings[model.id]) {
              return _.extend(bindings[model.id], {
                selected_object: selected
              });
            }
            return {
              instance: model,
              selected_object: selected,
              binding: binding,
              mappings: []
            };
          }.bind(this)));
        }.bind(this));
      },
      "getResults": function () {
        var model_name = this.scope.attr("type"),
            contact = this.scope.attr("contact"),
            join_model = GGRC.Mappings.join_model_name_for(CMS.Models[model_name], model_name),
            permission_parms = {
              __permission_type: "read"
            };

        this.scope.attr("page", 0);
        this.scope.attr("entries", []);
        this.scope.attr("selected", []);
        this.scope.attr("options", []);
        this.scope.attr("select_all", false);

        if (join_model !== "TaskGroupObject" && model_name === "Program") {
          permission_parms = {
            __permission_type: "create",
            __permission_model: join_model
          };
        }
        if (model_name === "AllObject") {
          model_name = this.scope.attr("types.all_objects.models");
        }
        if (contact) {
          permission_parms.contact_id = contact.id;
        }

        this.scope.attr("pageLoading", true);
        model_name = _.isString(model_name) ? [model_name] : model_name;
        GGRC.Models.Search
          .search_for_types(this.scope.attr("term") || "", model_name, permission_parms)
          .then(function (response) {
            var entries = _.flatten(_.map(model_name, function (name) {
                            return response.getResultsForType(name);
                          }));

            this.scope.attr("entries", entries);
            this.scope.attr("pageLoading", false);
            this.drawPage();
          }.bind(this));
      }
    }
  });
  can.Component.extend({
    tag: "mapper-filter",
    template: "<content />",
    scope: {
      panels: [],
      menu: can.map(
            Array.prototype.concat.call([],
              "Program Regulation Policy Standard Contract Clause Section Objective Control".split(" "),
              "Person System Process DataAsset Product Project Facility Market".split(" ")
            ), function (key) {
              return CMS.Models[key];
            })
    },
    events: {
      ".add-filter-rule click": function (el, ev) {
        ev.preventDefault();
        this.scope.panels.push({
          value: "",
          filter: new can.Map(),
          model_name: this.scope.menu[0].model_singular
        });
      },
      ".ui-autocomplete-input autocomplete:select": function (el, ev, data) {
        var index = el.data("index"),
            panel = this.scope.attr("panels")[index];

        panel.attr("filter", data.item);
      },
      ".remove_filter click": function (el) {
        this.scope.panels.splice(el.data("index"), 1);
      }
    }
  });

  $("body").on("click",
  '[data-toggle="modal-selector"], \
   [data-toggle="modal-relationship-selector"], \
   [data-toggle="multitype-object-modal-selector"], \
   [data-toggle="multitype-multiselect-modal-selector"], \
   [data-toggle="multitype-modal-selector"]',
  function (ev) {
    ev.preventDefault();
    var btn = $(ev.currentTarget),
        data = btn.data();

    _.each(data, function (val, key) {
      data[can.camelCaseToUnderscore(key)] = val;
      delete data[key];
    });
    GGRC.Controllers.ModalSelector.launch($(this), _.extend({
      "object": btn.data("join-object-type"),
      "type": btn.data("join-option-type"),
      "join-id": btn.data("join-object-id")
    }, data));
  });
})(window.can, window.can.$);

<commit_msg>Fix related biding<commit_after>/*!
    Copyright (C) 2015 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: ivan@reciprocitylabs.com
    Maintained By: ivan@reciprocitylabs.com
*/

(function(can, $) {
  "use strict";
  var MapperModel = can.Map({
      type: "",
      contact: {},
      term: "",
      model: {},
      bindings: {},
      isLoading: false,
      allSelected: false,
      selected: new can.List(),
      entries: new can.List(),
      types: can.compute(function () {
        var selector_list = GGRC.Mappings.get_canonical_mappings_for(GGRC.page_model.type),
            groups = {
              "all_objects": {
                name: "All Objects",
                value: "AllObject",
                plural: "allobjects",
                singular: "AllObject",
                models: []
              },
              "entities": {
                name: "People/Groups",
                items: []
              },
              "business": {
                name: "Assets/Business",
                items: []
              },
              "governance": {
                name: "Governance",
                items: []
              }
            };

        can.each(selector_list, function (model, model_name) {
          if (!model_name || ~["workflow"].indexOf(model_name.toLowerCase())) {
            return;
          }
          var cms_model = CMS.Models[model_name],
              group = !groups[cms_model.category] ? "governance" : cms_model.category;

          groups[group]["items"].push({
            name: cms_model.title_plural,
            value: cms_model.shortName,
            singular: cms_model.shortName,
            plural: cms_model.title_plural.toLowerCase().replace(/\s+/, "_"),
            isSelected: cms_model.shortName === this.type
          });
          groups["all_objects"]["models"].push(cms_model.shortName);
        }, this);
        return groups;
      })
    });

  can.Component.extend({
    tag: "modal-mapper",
    template: "<content />",
    scope: function (attrs, parentScope, el) {
      var $el = $(el),
          mapperInst = new MapperModel({
            type: $el.attr("type"),
            join_object_id: $el.attr("join-object-id"),
            object: $el.attr("object"),
          });
      return {
        mapper: mapperInst
      };
    },
    events: {
      "inserted": function () {
        this.setModel();
        this.setBinding();
      },
      ".modal-footer .btn-map click": function (el, ev) {
        ev.preventDefault();
        if (el.hasClass("disabled")) {
          return;
        }
        var instance = GGRC.page_instance(),
            data = {},
            deffer = [];

        data["context"] = null;
        data["source"] = {
          href: instance.href,
          type: instance.type,
          id: instance.id
        };
        this.scope.attr("isLoading", true);
        _.each(this.scope.attr("mapper.selected"), function (desination) {
          data["destination"] = desination;
          var model = new CMS.Models.Relationship(data);

          deffer.push(model.save());
        });
        $.when.apply($, deffer).then(function () {
          this.scope.attr("isLoading", false);
          // TODO: Find proper way to dismiss the modal
          this.element.find(".modal-dismiss").trigger("click");
        }.bind(this));
      },
      "setBinding": function () {
        var model_name = this.scope.attr("mapper.model.plural").toLowerCase(),
            selected = CMS.Models.get_instance(this.scope.attr("mapper.object"), this.scope.attr("mapper.join_object_id")),
            binding;

        model_name = (selected.has_binding(model_name) ? "" : "related_") + model_name;
        binding = selected.get_binding(model_name);
        binding.refresh_list().then(function (mappings) {
          can.each(mappings, function (mapping) {
            this.scope.attr("mapper.bindings")[mapping.instance.id] = mapping;
          }, this);
        }.bind(this));
      },
      "setModel": function () {
        var type = this.scope.attr("mapper.type"),
            types = this.scope.attr("mapper.types");
        if (type === "AllObject") {
          return this.scope.attr("mapper.model", types["all_objects"]);
        }
        types = _.reduce(_.values(types), function (memo, val) {
          if (val.items) {
            return memo.concat(val.items);
          }
          return memo;
        }, []);
        this.scope.attr("mapper.model", _.findWhere(types, {value: type}));
      },
      "{mapper.type} change": function () {
        this.scope.attr("mapper.term", "");
        this.scope.attr("mapper.contact", {});
        this.setModel();
        this.setBinding();
      },
      "#search-by-owner autocomplete:select": function (el, ev, data) {
        this.scope.attr("mapper.contact", data.item);
      },
      "#search-by-owner keyup": function (el, ev) {
        if (!el.val()) {
          this.scope.attr("mapper.contact", {});
        }
      },
      "allSelected": function () {
        var selected = this.scope.attr("mapper.selected"),
            entries = this.scope.attr("mapper.entries");

        this.scope.attr("mapper.allSelected", selected.length === entries.length);
      },
      "{mapper.entries} length": "allSelected",
      "{mapper.selected} length": "allSelected"
    }
  });
  can.Component.extend({
    tag: "mapper-results",
    template: "<content />",
    scope: {
      "items-per-page": "@",
      page: 0,
      options: new can.List(),
      select_all: false,
      pageLoading: false
    },
    events: {
      "inserted":  function () {
        this.element.find(".results-wrap").cms_controllers_infinite_scroll();
        this.getResults();
      },
      ".modalSearchButton click": "getResults",
      "{scope} type": "getResults",
      ".results-wrap scrollNext": "drawPage",
      ".tree-item .openclose click": function (el, ev) {
        ev.preventDefault();
        el.openclose();
      },
      ".object-check-all change": function (el, ev) {
        var que = new RefreshQueue(),
            entries = this.scope.attr("entries");

        this.scope.attr("select_all", true);
        this.scope.attr("isloading", true);
        que.enqueue(entries).trigger().then(function (models) {
          this.scope.attr("isloading", false);
          this.scope.attr("selected", _.map(models, function (model) {
            return {
              id: model.id,
              type: model.type,
              href: model.href
            };
          }));
        }.bind(this));
      },
      ".tree-item .object-check-single change": function (el, ev) {
        if (el.hasClass("disabled")) {
          return;
        }

        var uid = el.closest(".tree-item").data("id"),
            isChecked = el.prop("checked"),
            item = _.find(this.scope.attr("options"), function (option) {
                return option.instance.id === uid;
              }),
            selected = this.scope.attr("selected"),
            needle = {id: item.instance.id},
            index;

        if (!_.findWhere(selected, needle)) {
          selected.push({
            id: item.instance.id,
            type: item.instance.type,
            href: item.instance.href
          });
        } else {
          index = _.findIndex(selected, needle);
          selected.splice(index, 1);
        }
      },
      "drawPage": function () {
        if (this.scope.attr("pageLoading") || this.scope.attr("lastPage")) {
          return;
        }
        var que = new RefreshQueue(),
            page = this.scope.attr("page"),
            next_page = page + 1,
            per_page = +this.scope.attr("items-per-page"),
            page_items = this.scope.attr("entries").slice(page * per_page, next_page * per_page),
            options = this.scope.attr("options");

        if (!page_items.length) {
          return;
        }
        this.scope.attr("pageLoading", true);
        que.enqueue(page_items).trigger().then(function (models) {
          this.scope.attr("pageLoading", false);
          this.scope.attr("page", next_page);
          options.push.apply(options, can.map(models, function (model) {
            var selected = CMS.Models.get_instance(this.scope.attr("mapper.object"), this.scope.attr("mapper.join_object_id")),
                binding = selected.get_binding(this.scope.attr("mapper.model.plural").toLowerCase()),
                bindings = this.scope.attr("mapper.bindings");

            if (bindings[model.id]) {
              return _.extend(bindings[model.id], {
                selected_object: selected
              });
            }
            return {
              instance: model,
              selected_object: selected,
              binding: binding,
              mappings: []
            };
          }.bind(this)));
        }.bind(this));
      },
      "getResults": function () {
        var model_name = this.scope.attr("type"),
            contact = this.scope.attr("contact"),
            join_model = GGRC.Mappings.join_model_name_for(CMS.Models[model_name], model_name),
            permission_parms = {
              __permission_type: "read"
            };

        this.scope.attr("page", 0);
        this.scope.attr("entries", []);
        this.scope.attr("selected", []);
        this.scope.attr("options", []);
        this.scope.attr("select_all", false);

        if (join_model !== "TaskGroupObject" && model_name === "Program") {
          permission_parms = {
            __permission_type: "create",
            __permission_model: join_model
          };
        }
        if (model_name === "AllObject") {
          model_name = this.scope.attr("types.all_objects.models");
        }
        if (contact) {
          permission_parms.contact_id = contact.id;
        }

        this.scope.attr("pageLoading", true);
        model_name = _.isString(model_name) ? [model_name] : model_name;
        GGRC.Models.Search
          .search_for_types(this.scope.attr("term") || "", model_name, permission_parms)
          .then(function (response) {
            var entries = _.flatten(_.map(model_name, function (name) {
                            return response.getResultsForType(name);
                          }));

            this.scope.attr("entries", entries);
            this.scope.attr("pageLoading", false);
            this.drawPage();
          }.bind(this));
      }
    }
  });
  can.Component.extend({
    tag: "mapper-filter",
    template: "<content />",
    scope: {
      panels: [],
      menu: can.map(
            Array.prototype.concat.call([],
              "Program Regulation Policy Standard Contract Clause Section Objective Control".split(" "),
              "Person System Process DataAsset Product Project Facility Market".split(" ")
            ), function (key) {
              return CMS.Models[key];
            })
    },
    events: {
      ".add-filter-rule click": function (el, ev) {
        ev.preventDefault();
        this.scope.panels.push({
          value: "",
          filter: new can.Map(),
          model_name: this.scope.menu[0].model_singular
        });
      },
      ".ui-autocomplete-input autocomplete:select": function (el, ev, data) {
        var index = el.data("index"),
            panel = this.scope.attr("panels")[index];

        panel.attr("filter", data.item);
      },
      ".remove_filter click": function (el) {
        this.scope.panels.splice(el.data("index"), 1);
      }
    }
  });

  $("body").on("click",
  '[data-toggle="modal-selector"], \
   [data-toggle="modal-relationship-selector"], \
   [data-toggle="multitype-object-modal-selector"], \
   [data-toggle="multitype-multiselect-modal-selector"], \
   [data-toggle="multitype-modal-selector"]',
  function (ev) {
    ev.preventDefault();
    var btn = $(ev.currentTarget),
        data = btn.data();

    _.each(data, function (val, key) {
      data[can.camelCaseToUnderscore(key)] = val;
      delete data[key];
    });
    GGRC.Controllers.ModalSelector.launch($(this), _.extend({
      "object": btn.data("join-object-type"),
      "type": btn.data("join-option-type"),
      "join-id": btn.data("join-object-id")
    }, data));
  });
})(window.can, window.can.$);

<|endoftext|>


<commit_before>"use strict";

var ObjectId = require("mongodb").ObjectId;
require("mongodb-toolkit");
var generateCode = require("../../utils/code-generator");

var ProductManager = require('../master/product-manager');
var StorageManager = require('../master/storage-manager');
var UomManager = require('../master/uom-manager');
var InventorySummaryManager = require('./inventory-summary-manager');

var Models = require("dl-models");
var Map = Models.map;
var InventorySummaryModel = Models.inventory.InventoryMovement;
var InventoryMovementModel = Models.inventory.InventoryMovement;

var BaseManager = require("module-toolkit").BaseManager;
var i18n = require("dl-i18n");
var moment = require("moment");

const PROPERTY_PAIRS = {
    "uom": "quantity",
    "secondUom": "secondQuantity",
    "thirdUom": "thirdQuantity"
}

module.exports = class InventoryMovementManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(Map.inventory.collection.InventoryMovement);
        this.inventoryDocumentCollection = this.db.use(Map.inventory.collection.InventoryDocument);

        this.inventorySummaryManager = new InventorySummaryManager(db, user);
        this.storageManager = new StorageManager(db, user);
        this.productManager = new ProductManager(db, user);
        this.uomManager = new UomManager(db, user);
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false
        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},
            query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var productNameFilter = {
                "productName": {
                    "$regex": regex
                }
            };
            var productCodeFilter = {
                "productCode": {
                    "$regex": regex
                }
            };
            keywordFilter["$or"] = [productNameFilter, productCodeFilter];
        }
        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    _beforeInsert(data) {
        if (!data.code)
            data.code = generateCode();

        return Promise.resolve(data);
    }

    // _afterInsert(id) {
    //     return this.getSingleById(id)
    //         .then((inventoryMovement) => {
    //             var getSum = this.collection.aggregate([{
    //                 '$match': {
    //                     storageId: inventoryMovement.storageId,
    //                     productId: inventoryMovement.productId,
    //                     uomId: inventoryMovement.uomId
    //                 }
    //             }, {
    //                 "$group": {
    //                     _id: null,
    //                     quantity: {
    //                         '$sum': '$quantity'
    //                     }
    //                 }
    //             }]).toArray().then(results => results[0]);

    //             var getSummary = this.inventorySummaryManager.getSert(inventoryMovement.productId, inventoryMovement.storageId, inventoryMovement.uomId);

    //             return Promise.all([getSum, getSummary])
    //                 .then(results => {
    //                     var sum = results[0];
    //                     var summary = results[1];
    //                     summary.quantity = sum.quantity;
    //                     return this.inventorySummaryManager.update(summary)
    //                 })
    //                 .then(sumId => id)
    //         });
    // }

    _afterInsert(id) {
        return this.getSingleById(id)
            .then((inventoryMovement) => {
                var inventoryMovement = inventoryMovement;
                var updateSummary = this.inventorySummaryManager.getSert(inventoryMovement.productId, inventoryMovement.storageId, inventoryMovement.uomId)
                    .then((summary) => {
                        return sumInventory(inventoryMovement, summary)
                            .then((inventorySummary) => {
                                return this.inventorySummaryManager.update(inventorySummary)
                                    .then((summaryId) => Promise.resolve(id))
                            })
                    })
            })
    }

    searchObjectProperty(object, query) {
        for (var key in object) {
            var value = object[key];
            if (value === query) {
                return key
            }
        }
    }

    sumInventory(movement, summary) {
        var inventoryMovement = movement;
        var inventorySummary = summary;
        return new Promise((resolve, reject) => {

            if (movement.uom && movement.uom !== "") {
                property = searchObjectProperty(inventorySummary, movement.uom);
                inventorySummary[PROPERTY_PAIRS[property]] -= movement.quantity;
            }

            if (movement.secondUom && movement.secondUom !== "") {
                property = searchObjectProperty(inventorySummary, movement.secondUom);
                inventorySummary[PROPERTY_PAIRS[property]] -= movement.secondQuantity;
            }

            if (movement.thirdUom && movement.thirdUom !== "") {
                property = searchObjectProperty(inventorySummary, movement.thirdUom);
                inventorySummary[PROPERTY_PAIRS[property]] -= movement.thirdQuantity;
            }

            return Promise.resolve(inventorySummary);
        })
    }

    _validate(inventoryMovement) {
        var errors = {};
        var valid = inventoryMovement;

        var getInventorySummary = this.inventorySummaryManager.getSert(valid.productId, valid.storageId, valid.uomId)

        var getProduct = valid.productId && ObjectId.isValid(valid.productId) ? this.productManager.getSingleByIdOrDefault(valid.productId) : Promise.resolve(null);
        var getStorage = valid.storageId && ObjectId.isValid(valid.storageId) ? this.storageManager.getSingleByIdOrDefault(valid.storageId) : Promise.resolve(null);
        var getUom = valid.uomId && ObjectId.isValid(valid.uomId) ? this.uomManager.getSingleByIdOrDefault(valid.uomId) : Promise.resolve(null);
        var getSecondUom = valid.secondUomId && ObjectId.isValid(valid.secondUomId) ? this.uomManager.getSingleByIdOrDefault(valid.secondUomId) : Promise.resolve(null);
        var getThirdUom = valid.thirdUomId && ObjectId.isValid(valid.thirdUomId) ? this.uomManager.getSingleByIdOrDefault(valid.thirdUomId) : Promise.resolve(null);

        return Promise.all([getInventorySummary, getProduct, getStorage, getUom, getSecondUom, getThirdUom])
            .then(results => {
                var _dbInventorySummary = results[0];
                var _product = results[1];
                var _storage = results[2];
                var _uom = results[3];
                var _secondUom = results[4];
                var _thirdUom = results[5];

                if (_dbInventorySummary)
                    valid.code = _dbInventorySummary.code; // prevent code changes.

                if (!valid.referenceNo || valid.referenceNo === '')
                    errors["referenceNo"] = i18n.__("InventoryMovement.referenceNo.isRequired:%s is required", i18n.__("InventoryMovement.referenceNo._:Reference No"));

                if (!valid.referenceType || valid.referenceType === '')
                    errors["referenceType"] = i18n.__("InventoryMovement.referenceType.isRequired:%s is required", i18n.__("InventoryMovement.referenceType._:Reference Type"));

                if (!valid.productId || valid.productId === '')
                    errors["productId"] = i18n.__("InventoryMovement.productId.isRequired:%s is required", i18n.__("InventoryMovement.productId._:Product")); //"Grade harus diisi";
                else if (!_product)
                    errors["productId"] = i18n.__("InventoryMovement.productId: %s not found", i18n.__("InventoryMovement.productId._:Product"));

                if (!valid.storageId || valid.storageId === '')
                    errors["storageId"] = i18n.__("InventoryMovement.storageId.isRequired:%s is required", i18n.__("InventoryMovement.storageId._:Storage")); //"Grade harus diisi";
                else if (!_storage)
                    errors["storageId"] = i18n.__("InventoryMovement.storageId: %s not found", i18n.__("InventoryMovement.storageId._:Storage"));

                if (!valid.uomId || valid.uomId === '')
                    errors["uomId"] = i18n.__("InventoryMovement.uomId.isRequired:%s is required", i18n.__("InventoryMovement.uomId._:Uom")); //"Grade harus diisi";
                else if (!_uom)
                    errors["uomId"] = i18n.__("InventoryMovement.uomId: %s not found", i18n.__("InventoryMovement.uomId._:Uom"));

                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require('module-toolkit').ValidationError;
                    return Promise.reject(new ValidationError('data does not pass validation', errors));
                }

                valid.productId = _product._id;
                valid.productName = _product.name;
                valid.productCode = _product.code;

                valid.storageId = _storage._id;
                valid.storageName = _storage.name;
                valid.storageCode = _storage.code;

                valid.uomId = _uom._id;
                valid.uom = _uom.unit;

                valid.secondUomId = _secondUom._id;
                valid.secondUom = _secondUom.unit;

                valid.thirdUomId = _thirdUom._id;
                valid.thirdUomId = _thirdUom.unit;

                if (valid.type == "OUT") {
                    valid.quantity = valid.quantity * -1;
                }

                valid.before = _dbInventorySummary.quantity;

                if (valid.type == "ADJ") {
                    valid.after = valid.quantity;
                } else {
                    valid.after = _dbInventorySummary.quantity + valid.quantity;
                }

                if (!valid.stamp) {
                    valid = new InventoryMovementModel(valid);
                }

                valid.stamp(this.user.username, "manager");
                return Promise.resolve(valid);

            })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        }
        var productIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__productId`,
            key: {
                productId: 1
            }
        };
        var storageIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__storageId`,
            key: {
                storageId: 1
            }
        };
        var uomIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__uomId`,
            key: {
                uomId: 1
            }
        };

        return this.collection.createIndexes([dateIndex, productIndex, storageIndex, uomIndex]);
    }

    getReferenceNo(query) {
        return this.inventoryDocumentCollection.find({
            _deleted: false,
            date: query
        }, { "referenceNo": 1 }).toArray()
            .then((data) => {
                var referenceNumbers = data.map((inventoryDocument) => {
                    return inventoryDocument.referenceNo;
                })
                return Promise.resolve(referenceNumbers)
            })
    }

    getMovementReport(info) {
        var _defaultFilter = {
            _deleted: false
        },
            query = {},
            order = info.order || {};

        var dateFrom = info.dateFrom ? (new Date(info.dateFrom)) : (new Date(1900, 1, 1));
        var dateTo = info.dateTo ? (new Date(info.dateTo + "T23:59")) : (new Date());

        var filterMovement = {};

        if (info.storageId)
            filterMovement.storageId = new ObjectId(info.storageId);

        if (info.type && info.type != "")
            filterMovement.type = info.type;

        if (info.productId)
            filterMovement.productId = new ObjectId(info.productId);

        var dateQuery = {
            $gte: dateFrom,
            $lte: dateTo
        }

        return this.getReferenceNo(dateQuery)
            .then((referenceNumbers) => {
                filterMovement.referenceNo = {
                    $in: referenceNumbers
                };
                var data = this._createIndexes()
                    .then((createIndexResults) => {
                        query = { '$and': [_defaultFilter, filterMovement] };
                        return !info.xls ?
                            this.collection
                                .where(query)
                                .order(order)
                                .execute() :
                            this.collection
                                .where(query)
                                .page(info.page, info.size)
                                .order(order)
                                .execute();
                    });
                return Promise.resolve(data);
            })
    }

    getXls(result, filter) {
        var xls = {};
        xls.data = [];
        xls.options = [];
        xls.name = '';

        var index = 0;
        var dateFormat = "DD/MM/YYYY";

        for (var movement of result.data) {
            index++;

            var item = {};
            item["No"] = index;
            item["Storage"] = movement.storageName ? movement.storageName : '';
            item["Nomor Referensi"] = movement.referenceType ? movement.referenceNo : '';
            item["Tipe Referensi"] = movement.referenceType ? movement.referenceType : '';
            item["Tanggal"] = movement.date ? moment(movement.date).format(dateFormat) : '';
            item["Nama Barang"] = movement.productName ? movement.productName : '';
            item["UOM"] = movement.uom ? movement.uom : '';
            item["Before"] = movement.before ? movement.before : 0;
            item["Kuantiti"] = movement.quantity ? movement.quantity : 0;
            item["After"] = movement.after ? movement.after : 0;
            item["Status"] = movement.type ? movement.type : '';

            xls.data.push(item);
        }

        xls.options["No"] = "number";
        xls.options["Storage"] = "string";
        xls.options["Nomor Referensi"] = "string";
        xls.options["Tipe Referensi"] = "string";
        xls.options["Tanggal"] = "string";
        xls.options["Nama Barang"] = "string";
        xls.options["UOM"] = "string";
        xls.options["Before"] = "number";
        xls.options["Kuantiti"] = "number";
        xls.options["After"] = "number";
        xls.options["Status"] = "string";

        if (filter.dateFrom && filter.dateTo) {
            xls.name = `Inventory Movement ${moment(new Date(filter.dateFrom)).format(dateFormat)} - ${moment(new Date(filter.dateTo)).format(dateFormat)}.xlsx`;
        }
        else {
            xls.name = `Inventory Movement.xlsx`;
        }

        return Promise.resolve(xls);
    }
}
<commit_msg>update document inventory<commit_after>"use strict";

var ObjectId = require("mongodb").ObjectId;
require("mongodb-toolkit");
var generateCode = require("../../utils/code-generator");

var ProductManager = require('../master/product-manager');
var StorageManager = require('../master/storage-manager');
var UomManager = require('../master/uom-manager');
var InventorySummaryManager = require('./inventory-summary-manager');

var Models = require("dl-models");
var Map = Models.map;
var InventorySummaryModel = Models.inventory.InventoryMovement;
var InventoryMovementModel = Models.inventory.InventoryMovement;

var BaseManager = require("module-toolkit").BaseManager;
var i18n = require("dl-i18n");
var moment = require("moment");

const PROPERTY_PAIRS = {
    "uom": "quantity",
    "secondUom": "secondQuantity",
    "thirdUom": "thirdQuantity"
}

module.exports = class InventoryMovementManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(Map.inventory.collection.InventoryMovement);
        this.inventoryDocumentCollection = this.db.use(Map.inventory.collection.InventoryDocument);

        this.inventorySummaryManager = new InventorySummaryManager(db, user);
        this.storageManager = new StorageManager(db, user);
        this.productManager = new ProductManager(db, user);
        this.uomManager = new UomManager(db, user);
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false
        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},
            query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var productNameFilter = {
                "productName": {
                    "$regex": regex
                }
            };
            var productCodeFilter = {
                "productCode": {
                    "$regex": regex
                }
            };
            keywordFilter["$or"] = [productNameFilter, productCodeFilter];
        }
        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    _beforeInsert(data) {
        if (!data.code)
            data.code = generateCode();

        return Promise.resolve(data);
    }

    // _afterInsert(id) {
    //     return this.getSingleById(id)
    //         .then((inventoryMovement) => {
    //             var getSum = this.collection.aggregate([{
    //                 '$match': {
    //                     storageId: inventoryMovement.storageId,
    //                     productId: inventoryMovement.productId,
    //                     uomId: inventoryMovement.uomId
    //                 }
    //             }, {
    //                 "$group": {
    //                     _id: null,
    //                     quantity: {
    //                         '$sum': '$quantity'
    //                     }
    //                 }
    //             }]).toArray().then(results => results[0]);

    //             var getSummary = this.inventorySummaryManager.getSert(inventoryMovement.productId, inventoryMovement.storageId, inventoryMovement.uomId);

    //             return Promise.all([getSum, getSummary])
    //                 .then(results => {
    //                     var sum = results[0];
    //                     var summary = results[1];
    //                     summary.quantity = sum.quantity;
    //                     return this.inventorySummaryManager.update(summary)
    //                 })
    //                 .then(sumId => id)
    //         });
    // }

    _afterInsert(id) {
        return this.getSingleById(id)
            .then((inventoryMovement) => {
                var inventoryMovement = inventoryMovement;
                var updateSummary = this.inventorySummaryManager.getSert(inventoryMovement.productId, inventoryMovement.storageId, inventoryMovement.uomId)
                    .then((summary) => {
                        return sumInventory(inventoryMovement, summary)
                            .then((inventorySummary) => {
                                return this.inventorySummaryManager.update(inventorySummary)
                                    .then((summaryId) => Promise.resolve(id))
                            })
                    })
            })
    }

    searchObjectProperty(object, query) {
        for (var key in object) {
            var value = object[key];
            if (value === query) {
                return key
            }
        }
    }

    sumInventory(movement, summary) {
        var inventoryMovement = movement;
        var inventorySummary = summary;
        return new Promise((resolve, reject) => {

            if (movement.uom && movement.uom !== "") {
                property = searchObjectProperty(inventorySummary, movement.uom);
                inventorySummary[PROPERTY_PAIRS[property]] -= movement.quantity;
            }

            if (movement.secondUom && movement.secondUom !== "") {
                property = searchObjectProperty(inventorySummary, movement.secondUom);
                inventorySummary[PROPERTY_PAIRS[property]] -= movement.secondQuantity;
            }

            if (movement.thirdUom && movement.thirdUom !== "") {
                property = searchObjectProperty(inventorySummary, movement.thirdUom);
                inventorySummary[PROPERTY_PAIRS[property]] -= movement.thirdQuantity;
            }

            return Promise.resolve(inventorySummary);
        })
    }

    _validate(inventoryMovement) {
        var errors = {};
        var valid = inventoryMovement;

        var getInventorySummary = this.inventorySummaryManager.getSert(valid.productId, valid.storageId, valid.uomId)

        var getProduct = valid.productId && ObjectId.isValid(valid.productId) ? this.productManager.getSingleByIdOrDefault(valid.productId) : Promise.resolve(null);
        var getStorage = valid.storageId && ObjectId.isValid(valid.storageId) ? this.storageManager.getSingleByIdOrDefault(valid.storageId) : Promise.resolve(null);
        var getUom = valid.uomId && ObjectId.isValid(valid.uomId) ? this.uomManager.getSingleByIdOrDefault(valid.uomId) : Promise.resolve(null);
        var getSecondUom = valid.secondUomId && ObjectId.isValid(valid.secondUomId) ? this.uomManager.getSingleByIdOrDefault(valid.secondUomId) : Promise.resolve(null);
        var getThirdUom = valid.thirdUomId && ObjectId.isValid(valid.thirdUomId) ? this.uomManager.getSingleByIdOrDefault(valid.thirdUomId) : Promise.resolve(null);

        return Promise.all([getInventorySummary, getProduct, getStorage, getUom, getSecondUom, getThirdUom])
            .then(results => {
                var _dbInventorySummary = results[0];
                var _product = results[1];
                var _storage = results[2];
                var _uom = results[3];
                var _secondUom = results[4];
                var _thirdUom = results[5];

                if (_dbInventorySummary)
                    valid.code = _dbInventorySummary.code; // prevent code changes.

                if (!valid.referenceNo || valid.referenceNo === '')
                    errors["referenceNo"] = i18n.__("InventoryMovement.referenceNo.isRequired:%s is required", i18n.__("InventoryMovement.referenceNo._:Reference No"));

                if (!valid.referenceType || valid.referenceType === '')
                    errors["referenceType"] = i18n.__("InventoryMovement.referenceType.isRequired:%s is required", i18n.__("InventoryMovement.referenceType._:Reference Type"));

                if (!valid.productId || valid.productId === '')
                    errors["productId"] = i18n.__("InventoryMovement.productId.isRequired:%s is required", i18n.__("InventoryMovement.productId._:Product")); //"Grade harus diisi";
                else if (!_product)
                    errors["productId"] = i18n.__("InventoryMovement.productId: %s not found", i18n.__("InventoryMovement.productId._:Product"));

                if (!valid.storageId || valid.storageId === '')
                    errors["storageId"] = i18n.__("InventoryMovement.storageId.isRequired:%s is required", i18n.__("InventoryMovement.storageId._:Storage")); //"Grade harus diisi";
                else if (!_storage)
                    errors["storageId"] = i18n.__("InventoryMovement.storageId: %s not found", i18n.__("InventoryMovement.storageId._:Storage"));

                if (!valid.uomId || valid.uomId === '')
                    errors["uomId"] = i18n.__("InventoryMovement.uomId.isRequired:%s is required", i18n.__("InventoryMovement.uomId._:Uom")); //"Grade harus diisi";
                else if (!_uom)
                    errors["uomId"] = i18n.__("InventoryMovement.uomId: %s not found", i18n.__("InventoryMovement.uomId._:Uom"));

                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require('module-toolkit').ValidationError;
                    return Promise.reject(new ValidationError('data does not pass validation', errors));
                }

                valid.productId = _product._id;
                valid.productName = _product.name;
                valid.productCode = _product.code;

                valid.storageId = _storage._id;
                valid.storageName = _storage.name;
                valid.storageCode = _storage.code;

                valid.uomId = _uom._id;
                valid.uom = _uom.unit;

                valid.secondUomId = _secondUom._id ? _secondUom._id : null;
                valid.secondUom = _secondUom.unit ? _secondUom.unit : "";

                valid.thirdUomId = _thirdUom._id ? _thirdUom._id : null;
                valid.thirdUomId = _thirdUom.unit;

                if (valid.type == "OUT") {
                    valid.quantity = valid.quantity * -1;
                }

                valid.before = _dbInventorySummary.quantity;

                if (valid.type == "ADJ") {
                    valid.after = valid.quantity;
                } else {
                    valid.after = _dbInventorySummary.quantity + valid.quantity;
                }

                if (!valid.stamp) {
                    valid = new InventoryMovementModel(valid);
                }

                valid.stamp(this.user.username, "manager");
                return Promise.resolve(valid);

            })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        }
        var productIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__productId`,
            key: {
                productId: 1
            }
        };
        var storageIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__storageId`,
            key: {
                storageId: 1
            }
        };
        var uomIndex = {
            name: `ix_${Map.inventory.collection.InventoryMovement}__uomId`,
            key: {
                uomId: 1
            }
        };

        return this.collection.createIndexes([dateIndex, productIndex, storageIndex, uomIndex]);
    }

    getReferenceNo(query) {
        return this.inventoryDocumentCollection.find({
            _deleted: false,
            date: query
        }, { "referenceNo": 1 }).toArray()
            .then((data) => {
                var referenceNumbers = data.map((inventoryDocument) => {
                    return inventoryDocument.referenceNo;
                })
                return Promise.resolve(referenceNumbers)
            })
    }

    getMovementReport(info) {
        var _defaultFilter = {
            _deleted: false
        },
            query = {},
            order = info.order || {};

        var dateFrom = info.dateFrom ? (new Date(info.dateFrom)) : (new Date(1900, 1, 1));
        var dateTo = info.dateTo ? (new Date(info.dateTo + "T23:59")) : (new Date());

        var filterMovement = {};

        if (info.storageId)
            filterMovement.storageId = new ObjectId(info.storageId);

        if (info.type && info.type != "")
            filterMovement.type = info.type;

        if (info.productId)
            filterMovement.productId = new ObjectId(info.productId);

        var dateQuery = {
            $gte: dateFrom,
            $lte: dateTo
        }

        return this.getReferenceNo(dateQuery)
            .then((referenceNumbers) => {
                filterMovement.referenceNo = {
                    $in: referenceNumbers
                };
                var data = this._createIndexes()
                    .then((createIndexResults) => {
                        query = { '$and': [_defaultFilter, filterMovement] };
                        return !info.xls ?
                            this.collection
                                .where(query)
                                .order(order)
                                .execute() :
                            this.collection
                                .where(query)
                                .page(info.page, info.size)
                                .order(order)
                                .execute();
                    });
                return Promise.resolve(data);
            })
    }

    getXls(result, filter) {
        var xls = {};
        xls.data = [];
        xls.options = [];
        xls.name = '';

        var index = 0;
        var dateFormat = "DD/MM/YYYY";

        for (var movement of result.data) {
            index++;

            var item = {};
            item["No"] = index;
            item["Storage"] = movement.storageName ? movement.storageName : '';
            item["Nomor Referensi"] = movement.referenceType ? movement.referenceNo : '';
            item["Tipe Referensi"] = movement.referenceType ? movement.referenceType : '';
            item["Tanggal"] = movement.date ? moment(movement.date).format(dateFormat) : '';
            item["Nama Barang"] = movement.productName ? movement.productName : '';
            item["UOM"] = movement.uom ? movement.uom : '';
            item["Before"] = movement.before ? movement.before : 0;
            item["Kuantiti"] = movement.quantity ? movement.quantity : 0;
            item["After"] = movement.after ? movement.after : 0;
            item["Status"] = movement.type ? movement.type : '';

            xls.data.push(item);
        }

        xls.options["No"] = "number";
        xls.options["Storage"] = "string";
        xls.options["Nomor Referensi"] = "string";
        xls.options["Tipe Referensi"] = "string";
        xls.options["Tanggal"] = "string";
        xls.options["Nama Barang"] = "string";
        xls.options["UOM"] = "string";
        xls.options["Before"] = "number";
        xls.options["Kuantiti"] = "number";
        xls.options["After"] = "number";
        xls.options["Status"] = "string";

        if (filter.dateFrom && filter.dateTo) {
            xls.name = `Inventory Movement ${moment(new Date(filter.dateFrom)).format(dateFormat)} - ${moment(new Date(filter.dateTo)).format(dateFormat)}.xlsx`;
        }
        else {
            xls.name = `Inventory Movement.xlsx`;
        }

        return Promise.resolve(xls);
    }
}
<|endoftext|>


<commit_before>var
	kind = require('enyo/kind'),
	Image = require('enyo/Image');

var
	Scroller = require('moonstone/Scroller'),
	Divider = require('moonstone/Divider'),
	Button = require('moonstone/Button'),
	ShowingTransitionSupport = require('moonstone/ShowingTransitionSupport');

var Pane = kind({
	name: 'Pane',
	classes: 'pane',
	showingDuration: 1000,
	hidingDuration: 500,
	mixins: [ ShowingTransitionSupport ],
	components: [
		{name: 'client', classes: 'glass moon-neutral moon-3v moon-5h'}
	]
});

var PopupMockup = kind({
	name: 'PopupMockup',
	classes: 'popup-mockup moon-neutral',
	showingDuration: 500,
	hidingDuration: 500,
	showing: false,
	showingClass: 'shown',
	shownClass: 'shown',
	mixins: [ ShowingTransitionSupport ]
});

module.exports = kind({
	name: 'moon.sample.ShowingTransitionSample',
	classes: 'moon enyo-unselectable enyo-fit showing-transition-sample',
	components: [
		{kind: Scroller, classes: 'enyo-fill', components: [
			{kind: Divider, content: 'Showing Transitions'},
			{kind: Button, content: 'Toggle Pane', ontap: 'togglePane'},
			{kind: Button, content: 'Toggle Popup', ontap: 'togglePopup'},
			{classes: 'moon-1v'},
			{components: [
				{name: 'pane', kind: Pane, components: [{content: 'This looks like a card'}]}
			]}
		]},
		{name: 'popup', kind: PopupMockup, components: [
			{content: 'Commense the jiggling!'},
			{kind: Image, src: 'http://static.fjcdn.com/gifs/Shake+it_945873_5126044.gif'}
		]}
	],
	togglePane: function (sender, ev) {
		this.$.pane.set('showing', !this.$.pane.get('showing'));
	},
	togglePopup: function (sender, ev) {
		this.$.popup.set('showing', !this.$.popup.get('showing'));
	}
});
<commit_msg>Fixed a Travis warning (`Image` redefined)<commit_after>var
	kind = require('enyo/kind'),
	Img = require('enyo/Image');

var
	Scroller = require('moonstone/Scroller'),
	Divider = require('moonstone/Divider'),
	Button = require('moonstone/Button'),
	ShowingTransitionSupport = require('moonstone/ShowingTransitionSupport');

var Pane = kind({
	name: 'Pane',
	classes: 'pane',
	showingDuration: 1000,
	hidingDuration: 500,
	mixins: [ ShowingTransitionSupport ],
	components: [
		{name: 'client', classes: 'glass moon-neutral moon-3v moon-5h'}
	]
});

var PopupMockup = kind({
	name: 'PopupMockup',
	classes: 'popup-mockup moon-neutral',
	showingDuration: 500,
	hidingDuration: 500,
	showing: false,
	showingClass: 'shown',
	shownClass: 'shown',
	mixins: [ ShowingTransitionSupport ]
});

module.exports = kind({
	name: 'moon.sample.ShowingTransitionSample',
	classes: 'moon enyo-unselectable enyo-fit showing-transition-sample',
	components: [
		{kind: Scroller, classes: 'enyo-fill', components: [
			{kind: Divider, content: 'Showing Transitions'},
			{kind: Button, content: 'Toggle Pane', ontap: 'togglePane'},
			{kind: Button, content: 'Toggle Popup', ontap: 'togglePopup'},
			{classes: 'moon-1v'},
			{components: [
				{name: 'pane', kind: Pane, components: [{content: 'This looks like a card'}]}
			]}
		]},
		{name: 'popup', kind: PopupMockup, components: [
			{content: 'Commense the jiggling!'},
			{kind: Img, src: 'http://static.fjcdn.com/gifs/Shake+it_945873_5126044.gif'}
		]}
	],
	togglePane: function (sender, ev) {
		this.$.pane.set('showing', !this.$.pane.get('showing'));
	},
	togglePopup: function (sender, ev) {
		this.$.popup.set('showing', !this.$.popup.get('showing'));
	}
});
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { connect } from 'react-redux'

import LoadingIndicatorFullPage from 'shared/LoadingIndicatorFullPage/LoadingIndicatorFullPage'
import { loadBuyerTeams } from '../../../actions/teamActions'
import TeamsOverviewTable from './TeamsOverviewTable'

import styles from './TeamsOverview.scss'

export class TeamsOverview extends Component {
  componentDidMount() {
    this.props.loadTeams()
  }

  render() {
    const { createTeamButton, loading, teamsOverview } = this.props
    const teams = teamsOverview.teams

    const NoTeamsMessage = () => (

Easily track and manage access to opportunities created within your organisation.

        {createTeamButton}
        How to manage teams within an organisation

    )

    if (loading) {
      return <LoadingIndicatorFullPage />
    }

    return (

        {Object.keys(teams).length === 0 ? <NoTeamsMessage /> : <TeamsOverviewTable teams={teams} />}

    )
  }
}

const mapStateToProps = state => ({
  loading: state.app.currentlySending,
  teamsOverview: state.teamsDashboard.teamsOverview
})

const mapDispatchToProps = dispatch => ({
  loadTeams: () => dispatch(loadBuyerTeams())
})

export default connect(mapStateToProps, mapDispatchToProps)(TeamsOverview)
<commit_msg>[Teams] Update link to Zendesk article (#807)<commit_after>import React, { Component } from 'react'
import { connect } from 'react-redux'

import LoadingIndicatorFullPage from 'shared/LoadingIndicatorFullPage/LoadingIndicatorFullPage'
import { loadBuyerTeams } from '../../../actions/teamActions'
import TeamsOverviewTable from './TeamsOverviewTable'

import styles from './TeamsOverview.scss'

export class TeamsOverview extends Component {
  componentDidMount() {
    this.props.loadTeams()
  }

  render() {
    const { createTeamButton, loading, teamsOverview } = this.props
    const teams = teamsOverview.teams

    const NoTeamsMessage = () => (

Easily track and manage access to opportunities created within your organisation.

        {createTeamButton}
        How to manage teams within an organisation

    )

    if (loading) {
      return <LoadingIndicatorFullPage />
    }

    return (

        {Object.keys(teams).length === 0 ? <NoTeamsMessage /> : <TeamsOverviewTable teams={teams} />}

    )
  }
}

const mapStateToProps = state => ({
  loading: state.app.currentlySending,
  teamsOverview: state.teamsDashboard.teamsOverview
})

const mapDispatchToProps = dispatch => ({
  loadTeams: () => dispatch(loadBuyerTeams())
})

export default connect(mapStateToProps, mapDispatchToProps)(TeamsOverview)
<|endoftext|>


<commit_before>/*globals MySystem IntegrationTestHelper describe beforeEach afterEach it */

describe("The diagram feedback", function(){
  var helper = IntegrationTestHelper.create({
    authoredContent: {
       "type": "mysystem2",
       "prompt": "",
       "modules": [
         {
           "name": "obj1",
           "uuid": "obj1"
         }
       ],
       "energy_types": [
         {
           "label": "en1",
           "uuid": "en1"
         }
       ],
       "diagram_rules": []
     }
  });

  beforeEach(function(){
    helper.setupApp();
  });

  afterEach(function(){
    helper.teardownApp();
  });

  it("should be saved when the submit button is pressed", function(){
    helper.submitDiagram();

    expect(helper.get('domIO').textContent.length).toBeGreaterThan(0);
    expect(helper.lastFeedback().success).toBe(true);
    expect(helper.lastFeedback().feedback).toBe("Your diagram has no obvious problems.");
  });

  it("is not saved when save button is pressed and submit has not been pressed yet (note: this is not a requirement just a current behavior)", function(){
    helper.addNode('obj1').saveDiagram();

    expect(helper.get('externalSaveCount')).toBe(1);
    expect(helper.lastFeedback()).toBeUndefined();
  });

  it("should be saved when save is triggered externally", function(){
    expect(helper.get('domIO').textContent.length).toBe(0);
    MySystem.preExternalSave();

    // There should now be feedback in the saved data
    expect(helper.get('domIO').textContent.length).toBeGreaterThan(0);
    expect(helper.lastFeedback().success).toBe(true);
    expect(helper.lastFeedback().feedback).toBe("Your diagram has no obvious problems.");
  });

  it("should be not increment the numOfSubmits when save is triggered externally", function(){
    MySystem.preExternalSave();

    expect(helper.lastFeedback().numOfSubmits).toBe(0);
  });

  it("should be saved by the submit button even if save button has been pushed first", function(){
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram();

    expect(helper.get('externalSaveCount')).toBe(2);
  });

  it("should be saved by the submit button if the submit button was just pressed and there have been no changes", function(){
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram().
      submitDiagram();

    expect(helper.get('externalSaveCount')).toBe(3);
  });

  it("should include the number of submits", function(){
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram().
      submitDiagram();

    expect(helper.get('externalSaveCount')).toBe(3);
    expect(helper.lastFeedback().numOfSubmits).toBe(2);
  });

  it("the feedback should not include the number of submits", function() {
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram();

    expect(helper.lastFeedback().feedback).not.toMatch('submission:');

  });
});

describe("maximum feedback exceeded", function(){
  var clickLimit = 3;
  var tooManyClicks = "You clicked 'submit' too many times";
  var helper = IntegrationTestHelper.create({
    authoredContent: {
       "type": "mysystem2",
       "prompt": "",
       "modules": [
         {
           "name": "obj1",
           "uuid": "obj1"
         }
       ],
       "energy_types": [
         {
           "label": "en1",
           "uuid": "en1"
         }
       ],
       "diagram_rules": [],
       "maxSubmissionClicks": clickLimit,
       "maxSubmissionFeedback": tooManyClicks
     }
  });

  beforeEach(function(){
    helper.setupApp();
  });

  afterEach(function(){
    helper.teardownApp();
  });

  it("should limit the number of submits", function(){
    var i = 0;
    helper.addNode('obj1');
    for (i = 0; i < 10; i++) {
      helper.submitDiagram();
    }
    // we expect submit to still save:
    expect(helper.get('externalSaveCount')).toBe(10);
    // but it shoudn't resubmit
    expect(helper.lastFeedback().numOfSubmits).toBe(clickLimit);
  });
});

describe("submit timestamp", function(){
  var helper = IntegrationTestHelper.create({
    authoredContent: {
       "type": "mysystem2",
       "prompt": "",
       "modules": [
         {
           "name": "obj1",
           "uuid": "obj1"
         }
       ],
       "energy_types": [
         {
           "label": "en1",
           "uuid": "en1"
         }
       ],
       "diagram_rules": [],
     }
  });
  beforeEach(function(){
    helper.setupApp();
  });

  afterEach(function(){
    helper.teardownApp();
  });

  it("should update the timestamp on submit", function() {
    var milliesNow       = new Date().getTime();
    var firstSubmitTime  = null;
    var secondSubmitTime = null;
    var self             = this;

    helper.addNode('obj1');

    helper.submitDiagram();
    console.log(helper.lastFeedback().numOfSubmits);
    firstSubmitTime = helper.lastFeedback().timeStampMs;
    expect(firstSubmitTime > milliesNow).toBeTruthy();

    helper.submitDiagram();
    secondSubmitTime = helper.lastFeedback().timeStampMs;
    expect(secondSubmitTime > firstSubmitTime).toBeTruthy();
  });
});
<commit_msg>Wait for the submission button to show up before clicking it.<commit_after>/*globals MySystem IntegrationTestHelper describe beforeEach afterEach it */

describe("The diagram feedback", function(){
  var helper = IntegrationTestHelper.create({
    authoredContent: {
       "type": "mysystem2",
       "prompt": "",
       "modules": [
         {
           "name": "obj1",
           "uuid": "obj1"
         }
       ],
       "energy_types": [
         {
           "label": "en1",
           "uuid": "en1"
         }
       ],
       "diagram_rules": []
     }
  });

  beforeEach(function(){
    helper.setupApp();
  });

  afterEach(function(){
    helper.teardownApp();
  });

  it("should be saved when the submit button is pressed", function(){
    helper.submitDiagram();

    expect(helper.get('domIO').textContent.length).toBeGreaterThan(0);
    expect(helper.lastFeedback().success).toBe(true);
    expect(helper.lastFeedback().feedback).toBe("Your diagram has no obvious problems.");
  });

  it("is not saved when save button is pressed and submit has not been pressed yet (note: this is not a requirement just a current behavior)", function(){
    helper.addNode('obj1').saveDiagram();

    expect(helper.get('externalSaveCount')).toBe(1);
    expect(helper.lastFeedback()).toBeUndefined();
  });

  it("should be saved when save is triggered externally", function(){
    expect(helper.get('domIO').textContent.length).toBe(0);
    MySystem.preExternalSave();

    // There should now be feedback in the saved data
    expect(helper.get('domIO').textContent.length).toBeGreaterThan(0);
    expect(helper.lastFeedback().success).toBe(true);
    expect(helper.lastFeedback().feedback).toBe("Your diagram has no obvious problems.");
  });

  it("should be not increment the numOfSubmits when save is triggered externally", function(){
    MySystem.preExternalSave();

    expect(helper.lastFeedback().numOfSubmits).toBe(0);
  });

  it("should be saved by the submit button even if save button has been pushed first", function(){
    runs(function() {
      helper
        .addNode('obj1').
        saveDiagram();
    });

    waitsFor(function() {
      var selector = ".button:contains('Submit Diagram'):not(.disabled)";
      var target = SC.CoreQuery(selector);
      return (!!selector);
    }, "waiting for submit button", 3000);

    runs(function() {
      helper.submitDiagram();
    });

}, "message");
    simulateClickOnSelector(".button:contains('Submit Diagram'):not(.disabled)");

      submitDiagram();

    expect(helper.get('externalSaveCount')).toBe(2);
  });

  it("should be saved by the submit button if the submit button was just pressed and there have been no changes", function(){
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram().
      submitDiagram();

    expect(helper.get('externalSaveCount')).toBe(3);
  });

  it("should include the number of submits", function(){
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram().
      submitDiagram();

    expect(helper.get('externalSaveCount')).toBe(3);
    expect(helper.lastFeedback().numOfSubmits).toBe(2);
  });

  it("the feedback should not include the number of submits", function() {
    helper.
      addNode('obj1').
      saveDiagram().
      submitDiagram();

    expect(helper.lastFeedback().feedback).not.toMatch('submission:');

  });
});

describe("maximum feedback exceeded", function(){
  var clickLimit = 3;
  var tooManyClicks = "You clicked 'submit' too many times";
  var helper = IntegrationTestHelper.create({
    authoredContent: {
       "type": "mysystem2",
       "prompt": "",
       "modules": [
         {
           "name": "obj1",
           "uuid": "obj1"
         }
       ],
       "energy_types": [
         {
           "label": "en1",
           "uuid": "en1"
         }
       ],
       "diagram_rules": [],
       "maxSubmissionClicks": clickLimit,
       "maxSubmissionFeedback": tooManyClicks
     }
  });

  beforeEach(function(){
    helper.setupApp();
  });

  afterEach(function(){
    helper.teardownApp();
  });

  it("should limit the number of submits", function(){
    var i = 0;
    helper.addNode('obj1');
    for (i = 0; i < 10; i++) {
      helper.submitDiagram();
    }
    // we expect submit to still save:
    expect(helper.get('externalSaveCount')).toBe(10);
    // but it shoudn't resubmit
    expect(helper.lastFeedback().numOfSubmits).toBe(clickLimit);
  });
});

describe("submit timestamp", function(){
  var helper = IntegrationTestHelper.create({
    authoredContent: {
       "type": "mysystem2",
       "prompt": "",
       "modules": [
         {
           "name": "obj1",
           "uuid": "obj1"
         }
       ],
       "energy_types": [
         {
           "label": "en1",
           "uuid": "en1"
         }
       ],
       "diagram_rules": []
     }
  });
  beforeEach(function(){
    helper.setupApp();
  });

  afterEach(function(){
    helper.teardownApp();
  });

  it("should update the timestamp on submit", function() {
    var milliesNow       = new Date().getTime();
    var firstSubmitTime  = null;
    var secondSubmitTime = null;
    var self             = this;

    helper.addNode('obj1');

    helper.submitDiagram();
    console.log(helper.lastFeedback().numOfSubmits);
    firstSubmitTime = helper.lastFeedback().timeStampMs;
    expect(firstSubmitTime > milliesNow).toBeTruthy();

    helper.submitDiagram();
    secondSubmitTime = helper.lastFeedback().timeStampMs;
    expect(secondSubmitTime > firstSubmitTime).toBeTruthy();
  });
});
<|endoftext|>


<commit_before>export default Ember.Component.extend({
  tagName: 'a',
  classNameBindings: [':discourse-tag'],
  attributeBindings: ['href', 'style'],

  href: function() {
    return "/tagging/tag/" + this.get('tagId');
  }.property('tagId'),

  style: function() {
    var count = parseFloat(this.get('count')),
        minCount = parseFloat(this.get('minCount')),
        maxCount = parseFloat(this.get('maxCount'));

    if (count && maxCount && minCount) {
      var ratio = (count - minCount) / maxCount;
      if (ratio) {
        ratio = ratio + 1.0;
        return "font-size: " + ratio + "em";
      }
    }
  }.property('count', 'scaleTo'),

  render: function(buffer) {
    buffer.push(this.get('tagId'));
  },

  click: function(e) {
    e.preventDefault();
    Discourse.URL.routeTo(this.get('href'));
    return true;
  }
});
<commit_msg>FIX: Escape tag rendering<commit_after>export default Ember.Component.extend({
  tagName: 'a',
  classNameBindings: [':discourse-tag'],
  attributeBindings: ['href', 'style'],

  href: function() {
    return "/tagging/tag/" + this.get('tagId');
  }.property('tagId'),

  style: function() {
    var count = parseFloat(this.get('count')),
        minCount = parseFloat(this.get('minCount')),
        maxCount = parseFloat(this.get('maxCount'));

    if (count && maxCount && minCount) {
      var ratio = (count - minCount) / maxCount;
      if (ratio) {
        ratio = ratio + 1.0;
        return "font-size: " + ratio + "em";
      }
    }
  }.property('count', 'scaleTo'),

  render: function(buffer) {
    buffer.push(Handlebars.Utils.escapeExpression(this.get('tagId')));
  },

  click: function(e) {
    e.preventDefault();
    Discourse.URL.routeTo(this.get('href'));
    return true;
  }
});
<|endoftext|>


<commit_before>/**
 * AdSenseModuleStatus component.
 *
 * Site Kit by Google, Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';
import SvgIcon from 'GoogleUtil/svg-icon';
/**
 * Internal dependencies
 */
import { getAdSenseAccountStatus } from '../util';
import ProgressBar from 'GoogleComponents/progress-bar';
import AdSenseSetupInstructions from '../setup/adsense-setup-instructions';
import AdSenseInProcessStatus from './adsense-in-process-status';
import {
	getExistingTag,
} from 'GoogleUtil';

const { Component, Fragment } = wp.element;
const { __ } = wp.i18n;

class AdSenseModuleStatus extends Component {
	constructor( props ) {
		super( props );
		this.state = {
			loadStatus: __( 'Loading…', 'google-site-kit' ),
			existingTag: false,
		};
		this.updateLoadStatus = this.updateLoadStatus.bind( this );
		this.handleComponentRender = this.handleComponentRender.bind( this );
		this.continueSetup = this.continueSetup.bind( this );
		this.goBack = this.goBack.bind( this );
	}

	// Update the load status as the user status is determined.
	updateLoadStatus( loadStatus ) {
		this.setState( { ...this.state, loadStatus } );
	}

	async componentDidMount() {
		let existingTag = await getExistingTag( 'adsense' );
		existingTag = existingTag ? existingTag : false;

		this.setState( { existingTag } );

		getAdSenseAccountStatus( this.updateLoadStatus, existingTag ).then( ( results ) => {
			this.setState( results );
		} );
	}

	/**
	 * If setup requires a continue step, the method repopulates state with the new data.
	 */
	continueSetup( continueData ) {
		continueData.existingState = this.state;
		this.setState( continueData );
	}

	/**
	 * Go back to the previous (existing) state.
	 */
	goBack() {
		const { existingState } = this.state;
		if ( existingState ) {
			existingState.existingState = false;
			this.setState( existingState );
		}
	}

	handleComponentRender() {
		const {
			accountStatus,
			loadStatus,
		} = this.state;

		if ( ! googlesitekit.canAdsRun && ! googlesitekit.modules.adsense.setupComplete ) {
			return (
				<Fragment>

						<SvgIcon id="error" height="20" width="23" /> { __( 'Ad blocker detected, you need to disable it in order to setup AdSense.', 'google-site-kit' ) }

				</Fragment>
			);
		}

		if ( ! accountStatus ) {
			return (
				<Fragment>
					{ loadStatus }
					<ProgressBar />
				</Fragment>
			);
		}
		if ( 'account-pending-review' === accountStatus ) {
			return (
				<AdSenseInProcessStatus status="incomplete" />
			);
		}

		if ( 'account-required-action' === accountStatus ) {
			return (
				<AdSenseInProcessStatus status="requiredAction" />
			);
		}

		if ( 'ads-display-pending' === accountStatus ) {
			return (
				<AdSenseInProcessStatus status="adsDisplayPending" />
			);
		}

		return (
			<AdSenseSetupInstructions
				{ ...this.state }
				continueSetup={ this.continueSetup }
				goBack={ this.goBack }
			/>
		);
	}

	render() {
		return (

						<SvgIcon id="adsense" width="33" height="33" />

						{ __( 'AdSense', 'google-site-kit' ) }

					{ this.handleComponentRender() }

		);
	}
}

AdSenseModuleStatus.propTypes = {
	status: PropTypes.string,
	module: PropTypes.string,
};

export default AdSenseModuleStatus;
<commit_msg>Update assets/js/modules/adsense/dashboard/adsense-module-status.js<commit_after>/**
 * AdSenseModuleStatus component.
 *
 * Site Kit by Google, Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';
import SvgIcon from 'GoogleUtil/svg-icon';
/**
 * Internal dependencies
 */
import { getAdSenseAccountStatus } from '../util';
import ProgressBar from 'GoogleComponents/progress-bar';
import AdSenseSetupInstructions from '../setup/adsense-setup-instructions';
import AdSenseInProcessStatus from './adsense-in-process-status';
import {
	getExistingTag,
} from 'GoogleUtil';

const { Component, Fragment } = wp.element;
const { __ } = wp.i18n;

class AdSenseModuleStatus extends Component {
	constructor( props ) {
		super( props );
		this.state = {
			loadStatus: __( 'Loading…', 'google-site-kit' ),
			existingTag: false,
		};
		this.updateLoadStatus = this.updateLoadStatus.bind( this );
		this.handleComponentRender = this.handleComponentRender.bind( this );
		this.continueSetup = this.continueSetup.bind( this );
		this.goBack = this.goBack.bind( this );
	}

	// Update the load status as the user status is determined.
	updateLoadStatus( loadStatus ) {
		this.setState( { ...this.state, loadStatus } );
	}

	async componentDidMount() {
		let existingTag = await getExistingTag( 'adsense' );

		this.setState( { existingTag } );

		getAdSenseAccountStatus( this.updateLoadStatus, existingTag ).then( ( results ) => {
			this.setState( results );
		} );
	}

	/**
	 * If setup requires a continue step, the method repopulates state with the new data.
	 */
	continueSetup( continueData ) {
		continueData.existingState = this.state;
		this.setState( continueData );
	}

	/**
	 * Go back to the previous (existing) state.
	 */
	goBack() {
		const { existingState } = this.state;
		if ( existingState ) {
			existingState.existingState = false;
			this.setState( existingState );
		}
	}

	handleComponentRender() {
		const {
			accountStatus,
			loadStatus,
		} = this.state;

		if ( ! googlesitekit.canAdsRun && ! googlesitekit.modules.adsense.setupComplete ) {
			return (
				<Fragment>

						<SvgIcon id="error" height="20" width="23" /> { __( 'Ad blocker detected, you need to disable it in order to setup AdSense.', 'google-site-kit' ) }

				</Fragment>
			);
		}

		if ( ! accountStatus ) {
			return (
				<Fragment>
					{ loadStatus }
					<ProgressBar />
				</Fragment>
			);
		}
		if ( 'account-pending-review' === accountStatus ) {
			return (
				<AdSenseInProcessStatus status="incomplete" />
			);
		}

		if ( 'account-required-action' === accountStatus ) {
			return (
				<AdSenseInProcessStatus status="requiredAction" />
			);
		}

		if ( 'ads-display-pending' === accountStatus ) {
			return (
				<AdSenseInProcessStatus status="adsDisplayPending" />
			);
		}

		return (
			<AdSenseSetupInstructions
				{ ...this.state }
				continueSetup={ this.continueSetup }
				goBack={ this.goBack }
			/>
		);
	}

	render() {
		return (

						<SvgIcon id="adsense" width="33" height="33" />

						{ __( 'AdSense', 'google-site-kit' ) }

					{ this.handleComponentRender() }

		);
	}
}

AdSenseModuleStatus.propTypes = {
	status: PropTypes.string,
	module: PropTypes.string,
};

export default AdSenseModuleStatus;
<|endoftext|>


<commit_before>"use strict";
var _ = require("lodash");
var moment = require("moment-timezone");

// helper class to talk to schedule_matcher.py and use it to match up scheduled
// events and dosed events
// initialise with a zerorpc client
var ScheduleMatcher = module.exports = function (params) {
    // parameters to send straight to ScheduleMatcher (see documentation in schedule_matcher.py)
    // deprecated
    this.params = params;
    if (typeof this.params === "undefined" || this.params === null) this.params = {};
};

// take a Medication schedule and an array of dose times, and send them to schedule_matcher.py
// send them over ZeroMQ using ZeroRPC wrapper (sockets but better)
// may take a non-trivial amonut of time (but still millseconds)
ScheduleMatcher.prototype.match = function (schedule, doses, habits, callback) {

    // Setup =================================================================

    // set defaults for habits
    if (!_.has(habits, "wake") || habits.wake === null) {
        habits["wake"] = "09:00 am";
    }
    if (!_.has(habits, "tz") || habits.tz === null) {
        habits.tz = "America/New_York";
    }
    this.habits = habits;
    var tz = habits["tz"];

    // parse ISO 8601-formatted dates into Date objects, and sort them
    function parseDose(dose) {
        dose["date"] = moment.tz(dose["date"], tz).format();
        return dose;
    }
    function sortByDate(dose) {
        return moment(dose.date).unix();
    }
    this.doses = _.map(doses, parseDose);
    this.doses = _.sortBy(this.doses, sortByDate);

    // store time separately for quick access in cost function
    this.doseTimes = _.map(this.doses, sortByDate);

    // calculate start of first day
    // TODO: needs handling of am/pm
    var ampm = this.habits["wake"].split(" ")[1];
    var wake = _.map(this.habits["wake"].split(" ")[0].split(":"), Number);

    if (ampm === "pm") {
        wake[0] = wake[0] + 12;
    }

    var firstWake;
    if (this.doseTimes.length > 0) {
        firstWake = (moment(this.doseTimes[0] * 1000).hour(wake[0]).minute(wake[1]).second(0).millisecond(0)).format();
        if (moment(firstWake).isAfter(moment(this.doseTimes[0] * 1000))) {
            firstWake = (moment(firstWake).subtract(1, "days")).format();
        }
    } else {
        // sensible default (TODO: I don"t think this is sensible *JSS; what about timezone?)
        firstWake = moment().format();
    }

    // find all the "unspecified" schedule events we have
    var unspecified = [];
    _.forEach(schedule["times"], function (event) {
        if (event["type"] === "unspecified") {
            unspecified.push(event["_id"]);
        }
    });

    // helper function for indexing days
    function dayIndex(dose) {
        // calculate start of that day
        var startDay = moment(dose).hour(wake[0]).minute(wake[1]).second(0).millisecond(0);
        if (startDay.isAfter(moment(dose))) {
            startDay = startDay.subtract(1, "days");
        }
        return startDay.diff(firstWake, "days");
    }

    // Matching ==============================================================

    // match objects to be returned
    var matches = [];

    // transpose of matrix corresponding to the above,
    // used to determine what to do with unmatched dose events
    var reverse_matches = {};

    _.forEach(this.doses, function (dose) {
        var match = {
            "match": {}
        };

        // extract day of dose
        var day = dayIndex(dose["date"]);
        match["match"]["day"] = day;
        if (!_.has(reverse_matches, day)) {
            reverse_matches[day] = {};
        }

        // store ID of dose
        match["dose"] = dose["_id"];

        // use scheduled attribute if present (contains ID of index we should match to)
        if (_.has(dose, "scheduled") && dose["scheduled"] !== null) {
            // just in case the event matched is unspecified, record it so we don"t duplicate it
            reverse_matches[day][dose["scheduled"]] = true;
            match["match"]["index"] = dose["scheduled"];
        }

        // otherwise loop through and match up
        matches.push(match);
    });

    _.forEach(matches, function (match, i) {
        var day = match["match"]["day"];

        // skip the match if we"ve already matched it
        if (_.has(match["match"], "index")) {
            return;
        }

        // otherwise check if there"s still a free "unspecified" schedule event that day to match to
        console.log('UNSPEC:', unspecified);
        unspecified.every(function (event) {
            console.log("EVENT:", event);
            var event_used = (_.has(reverse_matches[day], event)) && (reverse_matches[day][event] === true);
            console.log("USED?", event_used);
            if (!event_used) {
                reverse_matches[day][event] = true;
                match["match"]["index"] = event;
                return false;
            }
        });

        // if we still haven"t found anything, use null to denote no match was found
        // i.e. it was probably a PRN medication
        if (!_.has(match["match"], "index")) {
            match["match"] = null;
        }

        matches[i] = match;
    });

    var ret = {
        "matches": matches,
        "start": moment(firstWake).toISOString()
    };
    callback(null, ret);
};
<commit_msg>tests passing locally<commit_after>"use strict";
var _ = require("lodash");
var moment = require("moment-timezone");

// helper class to talk to schedule_matcher.py and use it to match up scheduled
// events and dosed events
// initialise with a zerorpc client
var ScheduleMatcher = module.exports = function (zerorpc, params) {
    // parameters to send straight to ScheduleMatcher (see documentation in schedule_matcher.py)
    // deprecated
    this.zerorpc = zerorpc;
    this.params = params;
    if (typeof this.params === "undefined" || this.params === null) this.params = {};
};

// take a Medication schedule and an array of dose times, and send them to schedule_matcher.py
// send them over ZeroMQ using ZeroRPC wrapper (sockets but better)
// may take a non-trivial amonut of time (but still millseconds)
ScheduleMatcher.prototype.match = function (schedule, doses, habits, callback) {

    // Setup =================================================================

    // set defaults for habits
    if (!_.has(habits, "wake") || habits.wake === null) {
        habits["wake"] = "09:00 am";
    }
    if (!_.has(habits, "tz") || habits.tz === null) {
        habits.tz = "America/New_York";
    }
    this.habits = habits;
    var tz = habits.tz;

    // parse ISO 8601-formatted dates into Date objects, and sort them
    function parseDose(dose) {
        var newDose = JSON.parse(JSON.stringify(dose));  // copy the object
        var formatted = moment(dose["date"]).format();
        var newTz = moment.tz(formatted, tz).format();
        newDose.date = newTz;
        return newDose;
    }
    function sortByDate(dose) {
        return moment.tz(dose.date, tz).unix();
    }
    this.doses = _.map(doses, parseDose);
    this.doses = _.sortBy(this.doses, sortByDate);

    // store time separately for quick access in cost function
    this.doseTimes = _.map(this.doses, sortByDate);

    // calculate start of first day
    // TODO: needs handling of am/pm
    var ampm = this.habits["wake"].split(" ")[1];
    var wake = _.map(this.habits["wake"].split(" ")[0].split(":"), Number);

    if (ampm === "pm") {
        wake[0] = wake[0] + 12;
    }

    var firstWake;
    if (this.doseTimes.length > 0) {
        firstWake = (moment.tz(this.doseTimes[0] * 1000, tz).hour(wake[0]).minute(wake[1]).second(0).millisecond(0)).format();
        if (moment.tz(firstWake, tz).isAfter(moment(this.doseTimes[0] * 1000))) {
            firstWake = (moment.tz(firstWake, tz).subtract(1, "days")).format();
        }
    } else {
        // sensible default (TODO: I don"t think this is sensible *JSS; what about timezone?)
        firstWake = moment().tz(tz).format();
    }

    // find all the "unspecified" schedule events we have
    var unspecified = [];
    _.forEach(schedule["times"], function (event) {
        if (event["type"] === "unspecified") {
            unspecified.push(event["_id"]);
        }
    });

    // helper function for indexing days
    function dayIndex(dose) {
        // calculate start of that day
        var startDay = moment.tz(dose, tz).hour(wake[0]).minute(wake[1]).second(0).millisecond(0);
        if (startDay.isAfter(moment.tz(dose, tz))) {
            startDay = startDay.subtract(1, "days");
        }
        return startDay.diff(firstWake, "days");
    }

    // Matching ==============================================================

    // match objects to be returned
    var matches = [];

    // transpose of matrix corresponding to the above,
    // used to determine what to do with unmatched dose events
    var reverse_matches = {};

    _.forEach(this.doses, function (dose) {
        var match = {
            "match": {}
        };

        // extract day of dose
        var day = dayIndex(dose["date"]);
        match["match"]["day"] = day;
        if (!_.has(reverse_matches, day)) {
            reverse_matches[day] = {};
        }

        // store ID of dose
        match["dose"] = dose["_id"];

        // use scheduled attribute if present (contains ID of index we should match to)
        if (_.has(dose, "scheduled") && dose["scheduled"] !== null) {
            // just in case the event matched is unspecified, record it so we don"t duplicate it
            reverse_matches[day][dose["scheduled"]] = true;
            match["match"]["index"] = dose["scheduled"];
        }

        // otherwise loop through and match up
        matches.push(match);
    });

    _.forEach(matches, function (match, i) {
        var day = match["match"]["day"];

        // skip the match if we"ve already matched it
        if (_.has(match["match"], "index")) {
            return;
        }

        // otherwise check if there"s still a free "unspecified" schedule event that day to match to
        unspecified.every(function (event) {
            var event_used = (_.has(reverse_matches[day], event)) && (reverse_matches[day][event] === true);
            if (!event_used) {
                reverse_matches[day][event] = true;
                match["match"]["index"] = event;
                return false;
            }
        });

        // if we still haven"t found anything, use null to denote no match was found
        // i.e. it was probably a PRN medication
        if (!_.has(match["match"], "index")) {
            match["match"] = null;
        }

        matches[i] = match;
    });

    var ret = {
        "matches": matches,
        "start": moment.tz(firstWake, tz).format()
    };
    callback(null, ret);
};
<|endoftext|>