/FileCabinet/SuiteScripts/sku-analytics/total-monthly/sa-TotalMonthly.js

https://gitlab.com/stoicsoftware/netsuite-sku-analytics · JavaScript · 252 lines · 62 code · 15 blank · 175 comment · 1 complexity · 84cf50fbc6dfe15cbef5b19444834829 MD5 · raw file

  1. if (typeof define !== "function") {
  2. var define = require("amdefine")(module);
  3. }
  4. define([
  5. "N/search",
  6. "../lib/ramda.min",
  7. "../lib/moment.min",
  8. "../lib/sa-DateUtilities"
  9. ], function (s, R, moment, d) {
  10. /**
  11. * Business logic and data manipulation methods for the Total Monthly
  12. * Sales data
  13. *
  14. * @exports sa/total-monthly
  15. *
  16. * @requires N/search
  17. * @requires ramda
  18. * @requires moment
  19. * @requires sa/date-util
  20. *
  21. * @copyright 2016 Stoic Software
  22. * @author Eric T Grubaugh <eric@stoic.software>
  23. *
  24. * @NApiVersion 2.x
  25. * @NModuleScope Public
  26. */
  27. var exports = {};
  28. /**
  29. * The data format used to define Total Monthly Sales data
  30. * @typedef {Object} MonthlySalesData
  31. * @property month {moment} A moment representing the first of the month
  32. * @property sales {Number} The number of sales in the month
  33. */
  34. /**
  35. * monthToData :: moment -> MonthlySalesData
  36. *
  37. * Translates a moment representing a month in the year into a processable
  38. * data object
  39. *
  40. * @governance 0
  41. *
  42. * @param m {moment} The moment to translate
  43. *
  44. * @return {MonthlySalesData} Translated moment
  45. *
  46. * @private
  47. * @function monthToData
  48. */
  49. function monthToData(m) {
  50. return {
  51. "month": m,
  52. "sales": 0
  53. };
  54. }
  55. /**
  56. * monthsToData :: [moment] -> [MonthlySalesData]
  57. *
  58. * Translates a list of moments representing a month in the year into a
  59. * list of processable data objects
  60. *
  61. * @governance 0
  62. *
  63. * @param data {moment[]} The moments to translate
  64. *
  65. * @return {MonthlySalesData[]} Translated moments
  66. *
  67. * @private
  68. * @function monthsToData
  69. */
  70. var monthsToData = R.map(monthToData);
  71. /**
  72. * resultToData :: search.Result -> MonthlySalesData
  73. *
  74. * Translates a Total Monthly Sales search result into a processable
  75. * data object
  76. *
  77. * @governance 0
  78. *
  79. * @param result {search.Result} The search result to translate
  80. *
  81. * @return {MonthlySalesData} Translated search result
  82. *
  83. * @private
  84. * @function resultToData
  85. */
  86. function resultToData(result) {
  87. var month = moment(
  88. result.getValue({
  89. "name": "formulatext",
  90. "summary": s.Summary.GROUP
  91. }),
  92. "MMMM YYYY"
  93. );
  94. return {
  95. "month": month.startOf("month"),
  96. "sales": result.getValue({
  97. "name": "quantity",
  98. "summary": s.Summary.SUM
  99. })
  100. };
  101. }
  102. /**
  103. * resultsToData :: [search.Result] -> [MonthlySalesData]
  104. *
  105. * Translates a list of Total Monthly Sales search results into a list of
  106. * processable data object
  107. *
  108. * @governance 0
  109. *
  110. * @param data {search.Result[]} The list of search results to translate
  111. *
  112. * @return {MonthlySalesData[]} List of Monthly Sales data objects
  113. *
  114. * @private
  115. * @function resultsToData
  116. */
  117. var resultsToData = R.map(resultToData);
  118. /**
  119. * Predicate that determines whether two SKU sales data elements should be
  120. * merged together
  121. *
  122. * @param a {MonthlySalesData} first SKU sales data
  123. * @param b {MonthlySalesData} second SKU sales data
  124. *
  125. * @return {Boolean}
  126. *
  127. * @private
  128. * @function areDuplicates
  129. */
  130. function areDuplicates(a, b) {
  131. return d.sameMonth(a.month, b.month);
  132. }
  133. /**
  134. * generateData :: [search.Result] -> moment -> [MonthlySalesData]
  135. *
  136. * Translates the given search results to Monthly Sales data for the
  137. * rolling year starting with the given date
  138. *
  139. * @governance 0
  140. *
  141. * @param results {search.Result[]} List of Total Monthly Sales search
  142. * results to translate into processable data Objects
  143. * @param seedDate {moment} The date to start the rolling year from
  144. *
  145. * @return {MonthlySalesData[]} Data list processable by the Total Monthly
  146. * module
  147. *
  148. * @private
  149. * @function generateData
  150. */
  151. var generateData = R.useWith(R.unionWith(areDuplicates), [
  152. resultsToData,
  153. R.pipe(
  154. d.monthsSameYear,
  155. monthsToData
  156. )
  157. ]);
  158. /**
  159. * translateResults :: [search.Result] -> [MonthlySalesData]
  160. *
  161. * Translates the given search results to Monthly Sales data
  162. *
  163. * @governance 0
  164. *
  165. * @param results {search.Result[]} List of Total Monthly Sales search
  166. * results to translate into processable data Objects. Results
  167. * must be grouped by a formulatext column representing the month and
  168. * contain a summed quantity column representing the sales for that
  169. * month
  170. *
  171. * @return {MonthlySalesData[]} Data list processable by the Total Monthly
  172. * module
  173. *
  174. * @static
  175. * @function translateResults
  176. */
  177. var translateResults = R.pipe(
  178. generateData(R.__, moment()),
  179. R.sortBy(R.pipe(
  180. R.prop("month"),
  181. R.invoker(0, "valueOf")
  182. ))
  183. );
  184. /**
  185. * label :: MonthlySalesData -> String
  186. *
  187. * Generates a label for a MonthlySalesData object that can be used on, for
  188. * instance, a chart axis
  189. *
  190. * @governance 0
  191. *
  192. * @param data {MonthlySalesData} The data object to generate a label for
  193. *
  194. * @return {String} The label for the given data object
  195. *
  196. * @private
  197. * @function label
  198. */
  199. var label = R.pipe(
  200. R.prop("month"),
  201. d.format("MMM YYYY")
  202. );
  203. /**
  204. * labels :: [MonthlySalesData] -> [String]
  205. *
  206. * Generates the list of axis labels for the given dataset
  207. *
  208. * @governance 0
  209. *
  210. * @param data {MonthlySalesData[]} The dataset to transform to labels
  211. *
  212. * @return {String[]} The list of labels to be used for the data
  213. *
  214. * @static
  215. * @function labels
  216. */
  217. var labels = R.map(label);
  218. /**
  219. * values :: [MonthlySalesData] -> [Number]
  220. *
  221. * Generates the values that will be charted for the given dataset
  222. *
  223. * @governance 0
  224. *
  225. * @param data {MonthlySalesData[]} The dataset to transform to values
  226. *
  227. * @return {Number[]} The values to be used for the chart
  228. *
  229. * @static
  230. * @function values
  231. */
  232. var values = R.pluck("sales");
  233. exports.values = values;
  234. exports.labels = labels;
  235. exports.translateResults = translateResults;
  236. return exports;
  237. });