ledger.test.js 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. /**
  2. * 标段--台账 模型 单元测试
  3. *
  4. * @author Mai
  5. * @date 2017/2/1
  6. * @version
  7. */
  8. 'use strict';
  9. const excel = require('node-xlsx');
  10. const _ = require('lodash');
  11. /*const testNodeData = [
  12. { ledger_id: 1, ledger_pid: -1, order: 1, level: 1, full_path: '1', code: '1', is_leaf: false },
  13. { ledger_id: 2, ledger_pid: 1, order: 1, level: 2, full_path: '1.2', code: '1-1', is_leaf: false },
  14. { ledger_id: 6, ledger_pid: 2, order: 1, level: 3, full_path: '1.2.6', code: '1-1-1', is_leaf: false },
  15. { ledger_id: 7, ledger_pid: 6, order: 1, level: 4, full_path: '1.2.6.7', code: '202-1', is_leaf: false },
  16. { ledger_id: 10, ledger_pid: 7, order: 2, level: 5, full_path: '1.2.6.7.10', code: '202-1-a', is_leaf: true },
  17. { ledger_id: 9, ledger_pid: 7, order: 1, level: 5, full_path: '1.2.6.7.9', code: '202-1-b', is_leaf: true },
  18. { ledger_id: 8, ledger_pid: 6, order: 2, level: 4, full_path: '1.2.6.8', code: '202-2', is_leaf: false },
  19. { ledger_id: 11, ledger_pid: 8, order: 1, level: 5, full_path: '1.2.6.8.11', code: '202-2-c', is_leaf: true },
  20. { ledger_id: 12, ledger_pid: 8, order: 2, level: 5, full_path: '1.2.6.8.12', code: '202-2-e', is_leaf: true },
  21. { ledger_id: 13, ledger_pid: 2, order: 2, level: 3, full_path: '1.2.13', code: '1-1-2', is_leaf: true },
  22. { ledger_id: 14, ledger_pid: 2, order: 3, level: 3, full_path: '1.2.14', code: '1-1-3', is_leaf: true },
  23. { ledger_id: 3, ledger_pid: 1, order: 2, level: 2, full_path: '1.3', code: '1-2', is_leaf: false },
  24. { ledger_id: 15, ledger_pid: 3, order: 1, level: 3, full_path: '1.3.15', code: '1-2-1', is_leaf: true },
  25. { ledger_id: 4, ledger_pid: 1, order: 3, level: 2, full_path: '1.4', code: '1-3', is_leaf: false },
  26. { ledger_id: 16, ledger_pid: 4, order: 1, level: 3, full_path: '1.4.16', code: '1-3-1', is_leaf: true },
  27. { ledger_id: 5, ledger_pid: 1, order: 4, level: 2, full_path: '1.5', code: '1-4', is_leaf: true },
  28. ];*/
  29. const testNodeData = [
  30. { id: 1, pid: -1, order: 1, level: 1, full_path: '1', code: '1', is_leaf: false },
  31. { id: 2, pid: 1, order: 1, level: 2, full_path: '1.2', code: '1-1', is_leaf: false },
  32. { id: 6, pid: 2, order: 1, level: 3, full_path: '1.2.6', code: '1-1-1', is_leaf: false },
  33. { id: 7, pid: 6, order: 1, level: 4, full_path: '1.2.6.7', code: '202-1', is_leaf: false },
  34. { id: 10, pid: 7, order: 2, level: 5, full_path: '1.2.6.7.10', code: '202-1-a', is_leaf: true },
  35. { id: 9, pid: 7, order: 1, level: 5, full_path: '1.2.6.7.9', code: '202-1-b', is_leaf: true },
  36. { id: 8, pid: 6, order: 2, level: 4, full_path: '1.2.6.8', code: '202-2', is_leaf: false },
  37. { id: 11, pid: 8, order: 1, level: 5, full_path: '1.2.6.8.11', code: '202-2-c', is_leaf: true },
  38. { id: 12, pid: 8, order: 2, level: 5, full_path: '1.2.6.8.12', code: '202-2-e', is_leaf: true },
  39. { id: 13, pid: 2, order: 2, level: 3, full_path: '1.2.13', code: '1-1-2', is_leaf: true },
  40. { id: 14, pid: 2, order: 3, level: 3, full_path: '1.2.14', code: '1-1-3', is_leaf: true },
  41. { id: 3, pid: 1, order: 2, level: 2, full_path: '1.3', code: '1-2', is_leaf: false },
  42. { id: 15, pid: 3, order: 1, level: 3, full_path: '1.3.15', code: '1-2-1', is_leaf: true },
  43. { id: 4, pid: 1, order: 3, level: 2, full_path: '1.4', code: '1-3', is_leaf: false },
  44. { id: 16, pid: 4, order: 1, level: 3, full_path: '1.4.16', code: '1-3-1', is_leaf: true },
  45. { id: 5, pid: 1, order: 4, level: 2, full_path: '1.5', code: '1-4', is_leaf: true },
  46. ];
  47. const testTenderId = 3;
  48. const testUserId = 2;
  49. const { app, assert } = require('egg-mock/bootstrap');
  50. const findById = function(nodes, Id) {
  51. const filters = nodes.filter(function(x) {
  52. return x.ledger_id === Id;
  53. });
  54. return filters.length > 0 ? filters[0] : undefined;
  55. };
  56. describe('test/app/service/ledger.test.js', () => {
  57. // 准备测试数据
  58. it('clear history test data', function* () {
  59. const ctx = app.mockContext();
  60. const result = yield ctx.service.ledger.db.delete(ctx.service.ledger.tableName, { tender_id: testTenderId });
  61. const posResult = yield ctx.service.pos.db.delete(ctx.service.ledger.tableName, { tender_id: testTenderId });
  62. assert(result.affectedRows >= 0 && posResult.affectedRows >= 0);
  63. });
  64. it('add test data(test add)', function* () {
  65. const ctx = app.mockContext();
  66. for (const data of testNodeData) {
  67. data.tender_id = testTenderId;
  68. }
  69. //const result = yield ctx.service.ledger.db.insert(ctx.service.ledger.tableName, testNodeData);
  70. //assert(result.affectedRows === testNodeData.length);
  71. const result = yield ctx.service.ledger.add(testNodeData, testTenderId);
  72. assert(result);
  73. ctx.service.ledger.cache.set('tender_node_maxId:' + testTenderId, 16, 'EX', ctx.app.config.cacheTime);
  74. });
  75. /* 期望运行结果:
  76. 1
  77. ├── 1-1
  78. │ ├── 1-1-1
  79. │ │ ├── 202-1
  80. │ │ │ ├── 202-1-a
  81. │ │ │ └── 202-1-b
  82. │ │ └── 202-2
  83. │ │ ├── 202-2-c
  84. │ │ └── 202-1-3
  85. │ ├── 1-1-2
  86. │ └── 1-1-3
  87. ├── 1-2
  88. │ └── 1-2-1
  89. ├── 1-3
  90. │ └── 1-3-1
  91. └── 1-4
  92. */
  93. // 测试R类方法
  94. it('test getDataByTenderId', function* () {
  95. const ctx = app.mockContext();
  96. // 查询前4层节点
  97. const result1 = yield ctx.service.ledger.getDataByTenderId(testTenderId);
  98. assert(result1.length === 12);
  99. // 查询前3层节点
  100. const result2 = yield ctx.service.ledger.getDataByTenderId(testTenderId, 3);
  101. assert(result2.length === 10);
  102. });
  103. it('test getDataByNodeId', function* () {
  104. const ctx = app.mockContext();
  105. // 查询节点202-1
  106. const node = yield ctx.service.ledger.getDataByNodeId(testTenderId, 7);
  107. assert(node);
  108. assert(node.code === '202-1');
  109. assert(node.full_path === '1.2.6.7');
  110. });
  111. it('test getDataByNodeIds', function* () {
  112. const ctx = app.mockContext();
  113. // 查询节点202-1-a与201-1-b
  114. const result = yield ctx.service.ledger.getDataByNodeIds(testTenderId, [10, 9]);
  115. assert(result.length === 2);
  116. let node = findById(result, 10);
  117. assert(node.code === '202-1-a');
  118. node = findById(result, 9);
  119. assert(node.full_path === '1.2.6.7.9');
  120. });
  121. it('test getDataByIds', function* () {
  122. const ctx = app.mockContext();
  123. // 查询节点202-1
  124. const node = yield ctx.service.ledger.getDataByNodeId(testTenderId, 7);
  125. const result = yield ctx.service.ledger.getDataByIds([node.id]);
  126. assert(result.length === 1);
  127. assert(node.code === result[0].code);
  128. assert(node.full_path === result[0].full_path);
  129. });
  130. it('test getLastChildData', function* () {
  131. const ctx = app.mockContext();
  132. // 查询节点202-1最后一个子节点
  133. const result = yield ctx.service.ledger.getLastChildData(testTenderId, 7);
  134. assert(result.ledger_id === 10);
  135. assert(result.full_path === '1.2.6.7.10');
  136. });
  137. it('test getDataByParentAndOrder', function* () {
  138. const ctx = app.mockContext();
  139. // 查询节点202-1 第1子节点
  140. const result1 = yield ctx.service.ledger.getDataByParentAndOrder(testTenderId, 8, 1);
  141. assert(result1.ledger_id === 11);
  142. assert(result1.full_path === '1.2.6.8.11');
  143. // 查询节点1-1 第2/3子节点
  144. const result2 = yield ctx.service.ledger.getDataByParentAndOrder(testTenderId, 2, [2, 3]);
  145. assert(result2.length === 2);
  146. let node = findById(result2, 13);
  147. assert(node);
  148. assert(node.code === '1-1-2');
  149. node = findById(result2, 14);
  150. assert(node);
  151. assert(node.code === '1-1-3');
  152. });
  153. it('test getChildrenByParentId', function* () {
  154. const ctx = app.mockContext();
  155. // 查询节点202-1最后一个子节点
  156. const result = yield ctx.service.ledger.getChildrenByParentId(testTenderId, 8);
  157. assert(result.length === 2);
  158. let node = findById(result, 11);
  159. assert(node);
  160. assert(node.code === '202-2-c');
  161. node = findById(result, 12);
  162. assert(node);
  163. assert(node.full_path === '1.2.6.8.12');
  164. });
  165. it('test getNextsData', function* () {
  166. const ctx = app.mockContext();
  167. // 查询节点1-1-1的全部子节点
  168. const result = yield ctx.service.ledger.getNextsData(testTenderId, 2, 1);
  169. assert(result.length === 2);
  170. let node = findById(result, 13);
  171. assert(node);
  172. assert(node.code === '1-1-2');
  173. node = findById(result, 14);
  174. assert(node);
  175. assert(node.code === '1-1-3');
  176. });
  177. it('test getDataByFullPath', function* () {
  178. const ctx = app.mockContext();
  179. // 查询节点202-2及其子节点
  180. const result = yield ctx.service.ledger.getDataByFullPath(testTenderId, '1.2.6.8%');
  181. assert(result.length === 3);
  182. let node = findById(result, 8);
  183. assert(node);
  184. assert(node.code === '202-2');
  185. node = findById(result, 11);
  186. assert(node);
  187. assert(node.code === '202-2-c');
  188. node = findById(result, 12);
  189. assert(node);
  190. assert(node.full_path === '1.2.6.8.12');
  191. // 查询1-1-1的子孙节点
  192. const result1 = yield ctx.service.ledger.getDataByFullPath(testTenderId, '1.2.6.%');
  193. assert(result1.length === 6);
  194. });
  195. it('test getFullLevelDataByFullPath', function* () {
  196. const ctx = app.mockContext();
  197. // 查询202-2-c及其全部父节点
  198. const result1 = yield ctx.service.ledger.getFullLevelDataByFullPath(testTenderId, '1.2.6.8.11');
  199. assert(result1.length === 5);
  200. const result2 = yield ctx.service.ledger.getFullLevelDataByFullPath(testTenderId, ['1.2.6.8.11', '1.2.6.7.9']);
  201. assert(result2.length === 7);
  202. });
  203. // 测试CUD类方法
  204. // 基本树结构操作
  205. it('test addNode', function* () {
  206. const ctx = app.mockContext();
  207. // 选中1-1-1,插入节点
  208. const resultData = yield ctx.service.ledger.addNode(testTenderId, 6);
  209. assert(resultData.create.length === 1);
  210. assert(resultData.update.length === 2);
  211. assert(resultData.create[0].is_leaf === 1);
  212. assert(resultData.create[0].ledger_id === 17);
  213. });
  214. /* 期望运行结果:
  215. 1
  216. ├── 1-1
  217. │ ├── 1-1-1
  218. │ │ ├── 202-1
  219. │ │ │ ├── 202-1-a
  220. │ │ │ └── 202-1-b
  221. │ │ └── 202-2
  222. │ │ ├── 202-2-c
  223. │ │ └── 202-1-3
  224. │ ├── new
  225. │ ├── 1-1-2
  226. │ └── 1-1-3
  227. ├── 1-2
  228. │ └── 1-2-1
  229. ├── 1-3
  230. │ └── 1-3-1
  231. └── 1-4
  232. */
  233. it('test deleteNode', function* () {
  234. const ctx = app.mockContext();
  235. // 选中202-1,删除节点
  236. const resultData = yield ctx.service.ledger.deleteNode(testTenderId, 7);
  237. assert(resultData.delete.length === 3);
  238. assert(resultData.update.length === 1);
  239. });
  240. /* 期望运行结果:
  241. 1
  242. ├── 1-1
  243. │ ├── 1-1-1
  244. │ │ └── 202-2
  245. │ │ ├── 202-2-c
  246. │ │ └── 202-2-e
  247. │ ├── new
  248. │ ├── 1-1-2
  249. │ └── 1-1-3
  250. ├── 1-2
  251. │ └── 1-2-1
  252. ├── 1-3
  253. │ └── 1-3-1
  254. └── 1-4
  255. */
  256. it('test upMoveNode', function* () {
  257. const ctx = app.mockContext();
  258. // 选中202-2-e上移
  259. const resultData = yield ctx.service.ledger.upMoveNode(testTenderId, 12);
  260. resultData.update.sort(function(x, y) {
  261. return x.order - y.order;
  262. });
  263. assert(resultData.update.length === 2);
  264. assert(resultData.update[0].code === '202-2-e');
  265. });
  266. /* 期望运行结果:
  267. 1
  268. ├── 1-1
  269. │ ├── 1-1-1
  270. │ │ └── 202-2
  271. │ │ ├── 202-2-c
  272. │ │ └── 202-2-e
  273. │ ├── new
  274. │ ├── 1-1-2
  275. │ └── 1-1-3
  276. ├── 1-2
  277. │ └── 1-2-1
  278. ├── 1-3
  279. │ └── 1-3-1
  280. └── 1-4
  281. */
  282. it('test downMoveNode', function* () {
  283. const ctx = app.mockContext();
  284. // 选中202-2-e下移
  285. const resultData = yield ctx.service.ledger.downMoveNode(testTenderId, 12);
  286. resultData.update.sort(function(x, y) {
  287. return x.order - y.order;
  288. });
  289. assert(resultData.update.length === 2);
  290. assert(resultData.update[0].code === '202-2-c');
  291. });
  292. /* 期望运行结果:
  293. 1
  294. ├── 1-1
  295. │ ├── 1-1-1
  296. │ │ └── 202-2
  297. │ │ ├── 202-2-c
  298. │ │ └── 202-2-e
  299. │ ├── new
  300. │ ├── 1-1-2
  301. │ └── 1-1-3
  302. ├── 1-2
  303. │ └── 1-2-1
  304. ├── 1-3
  305. │ └── 1-3-1
  306. └── 1-4
  307. */
  308. it('test upLevelNode', function* () {
  309. const ctx = app.mockContext();
  310. // 选中 1-1-2 升级
  311. const resultData = yield ctx.service.ledger.upLevelNode(testTenderId, 13);
  312. assert(resultData);
  313. assert(resultData.update.length === 6);
  314. let node = findById(resultData.update, 13);
  315. assert(node.full_path === '1.13');
  316. assert(node.ledger_pid === 1);
  317. assert(!node.is_leaf);
  318. node = findById(resultData.update, 14);
  319. assert(node.ledger_pid === 13);
  320. assert(node.full_path === '1.13.14');
  321. node = findById(resultData.update, 3);
  322. assert(node.order === 3);
  323. node = findById(resultData.update, 4);
  324. assert(node.order === 4);
  325. node = findById(resultData.update, 5);
  326. assert(node.order === 5);
  327. });
  328. /* 期望运行结果:
  329. 1
  330. ├── 1-1
  331. │ ├── 1-1-1
  332. │ │ └── 202-2
  333. │ │ ├── 202-2-c
  334. │ │ └── 202-2-e
  335. │ └── new
  336. ├── 1-1-2
  337. │ └── 1-1-3
  338. ├── 1-2
  339. │ └── 1-2-1
  340. ├── 1-3
  341. │ └── 1-3-1
  342. └── 1-4
  343. */
  344. it('test downLevelNode', function* () {
  345. const ctx = app.mockContext();
  346. // 选中1-3 降级
  347. const resultData = yield ctx.service.ledger.downLevelNode(testTenderId, 4);
  348. // 1-2/1-3/1-3-1/1-4修改
  349. assert(resultData.update.length === 4);
  350. let node = findById(resultData.update, 4);
  351. assert(node.full_path === '1.3.4');
  352. assert(node.ledger_pid === 3);
  353. assert(node.level === 3);
  354. assert(node.order === 2);
  355. node = findById(resultData.update, 16);
  356. assert(node.level === 4);
  357. assert(node.full_path === '1.3.4.16');
  358. node = findById(resultData.update, 5);
  359. assert(node.order === 4);
  360. });
  361. /* 期望运行结果:
  362. 1
  363. ├── 1-1
  364. │ ├── 1-1-1
  365. │ │ └── 202-2
  366. │ │ ├── 202-2-c
  367. │ │ └── 202-2-e
  368. │ └── new
  369. ├── 1-1-2
  370. │ └── 1-1-3
  371. ├── 1-2
  372. │ ├── 1-2-1
  373. │ └── 1-3
  374. │ └── 1-3-1
  375. └── 1-4
  376. */
  377. // 复制整块
  378. it('test pasteBlock', function* () {
  379. const ctx = app.mockContext();
  380. // 选中1-2-1, 粘贴1-1-1和new
  381. const resultData = yield ctx.service.ledger.pasteBlock(testTenderId, 15, [6, 17]);
  382. const ledger = resultData.ledger;
  383. assert(ledger.create.length === 5);
  384. assert(ledger.create[0].order = 2);
  385. assert(ledger.create[0].level = 3);
  386. assert(ledger.create[0].full_path = '1.3.18');
  387. assert(ledger.create[1].order = 3);
  388. assert(ledger.create[1].level = 3);
  389. assert(ledger.create[1].full_path = '1.3.22');
  390. assert(ledger.update.length === 1);
  391. assert(ledger.update[0].order = 3);
  392. assert(resultData.pos.length === 0);
  393. });
  394. /* 期望运行结果:
  395. 1
  396. ├── 1-1
  397. │ ├── 1-1-1
  398. │ │ └── 202-2
  399. │ │ ├── 202-2-c
  400. │ │ └── 202-2-e
  401. │ └── new
  402. ├── 1-1-2
  403. │ └── 1-1-3
  404. ├── 1-2
  405. │ ├── 1-2-1
  406. │ ├── 1-1-1
  407. │ │ └── 202-2
  408. │ │ ├── 202-2-c
  409. │ │ └── 202-2-e
  410. │ ├── new
  411. │ └── 1-3
  412. │ └── 1-3-1
  413. └── 1-4
  414. */
  415. // 增量计算
  416. it('test updateInfo', function* () {
  417. const ctx = app.mockContext();
  418. // 修改new(id=17)的code 为 1-1-4
  419. const node = yield ctx.service.ledger.getDataByNodeId(testTenderId, 17);
  420. assert(node);
  421. const resultData = yield ctx.service.ledger.updateInfo(testTenderId, {
  422. id: node.id,
  423. tender_id: node.tender_id,
  424. ledger_id: node.ledger_id,
  425. code: '1-1-4',
  426. });
  427. assert(resultData.code === '1-1-4');
  428. });
  429. /* 期望运行结果:
  430. 1
  431. ├── 1-1
  432. │ ├── 1-1-1
  433. │ │ └── 202-2
  434. │ │ ├── 202-2-c
  435. │ │ └── 202-2-e
  436. │ └── 1-1-4
  437. ├── 1-1-2
  438. │ └── 1-1-3
  439. ├── 1-2
  440. │ ├── 1-2-1
  441. │ ├── 1-1-1
  442. │ │ └── 202-2
  443. │ │ ├── 202-2-c
  444. │ │ └── 202-2-e
  445. │ ├── new
  446. │ └── 1-3
  447. │ └── 1-3-1
  448. └── 1-4
  449. */
  450. it('test updateInfos', function* () {
  451. const ctx = app.mockContext();
  452. // 修改1-1-1(id=18)的code 为 1-2-2、修改new(id=22)的code 为 1-2-3
  453. const node1 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 18);
  454. assert(node1);
  455. const node2 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 22);
  456. assert(node2);
  457. const resultData = yield ctx.service.ledger.updateInfos(testTenderId, [{
  458. id: node1.id,
  459. tender_id: node1.tender_id,
  460. ledger_id: node1.ledger_id,
  461. code: '1-2-2',
  462. }, {
  463. id: node2.id,
  464. tender_id: node2.tender_id,
  465. ledger_id: node2.ledger_id,
  466. code: '1-2-3',
  467. }]);
  468. assert(resultData.length === 2);
  469. assert(resultData[0].code === '1-2-2');
  470. assert(resultData[1].code === '1-2-3');
  471. });
  472. /* 期望运行结果:
  473. 1
  474. ├── 1-1
  475. │ ├── 1-1-1
  476. │ │ └── 202-2
  477. │ │ ├── 202-2-c
  478. │ │ └── 202-2-e
  479. │ └── 1-1-4
  480. ├── 1-1-2
  481. │ └── 1-1-3
  482. ├── 1-2
  483. │ ├── 1-2-1
  484. │ ├── 1-2-2
  485. │ │ └── 202-2
  486. │ │ ├── 202-2-c
  487. │ │ └── 202-2-e
  488. │ ├── 1-2-3
  489. │ └── 1-3
  490. │ └── 1-3-1
  491. └── 1-4
  492. */
  493. it('test updateCalc - update 1', function* () {
  494. const ctx = app.mockContext();
  495. // 计算需使用清单精度、小数位数
  496. ctx.tender = {id: testTenderId};
  497. ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
  498. ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
  499. // 修改202-2-e(1-1-1下)(id=12)的quantity为2.00000001, unit_price位3.0000005
  500. const qty = 2.00000001, fQty = ctx.helper.round(qty, ctx.tender.info.precision.other.value);
  501. const up = 3.0000005, fUp = ctx.helper.round(up, ctx.tender.info.decimal.up);
  502. const tp = 6.00000103, fTp = ctx.helper.times(fQty, fUp);
  503. const node1 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 12);
  504. assert(node1);
  505. const resultData = yield ctx.service.ledger.updateCalc(testTenderId, {
  506. id: node1.id,
  507. tender_id: node1.tender_id,
  508. ledger_id: node1.ledger_id,
  509. quantity: qty,
  510. unit_price: up
  511. });
  512. assert(resultData.update.length === 1);
  513. let node = findById(resultData.update, 12);
  514. assert(node.quantity === fQty);
  515. assert(node.unit_price === fUp);
  516. assert(node.total_price == fTp);
  517. });
  518. /* 期望运行结果:
  519. 1
  520. ├── 1-1
  521. │ ├── 1-1-1
  522. │ │ └── 202-2
  523. │ │ ├── 202-2-c
  524. │ │ └── 202-2-e 2 3 6
  525. │ └── 1-1-4
  526. ├── 1-1-2
  527. │ └── 1-1-3
  528. ├── 1-2
  529. │ ├── 1-2-1
  530. │ ├── 1-2-2
  531. │ │ └── 202-2
  532. │ │ ├── 202-2-c
  533. │ │ └── 202-2-e
  534. │ ├── 1-2-3
  535. │ └── 1-3
  536. │ └── 1-3-1
  537. └── 1-4
  538. */
  539. it('test updateCalc - update N', function* () {
  540. const ctx = app.mockContext();
  541. // 计算需使用清单精度、小数位数
  542. ctx.tender = {id: testTenderId};
  543. ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
  544. ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
  545. // 修改202-2-c(1-1-1下)(id=11)的quantity为4.00000025, unit_price为6.0000083
  546. // 202-2-c(1-2-2下)(id=20)的quantity为2.0000001, unit_price为5.000065
  547. // 202-2-e(1-2-2下)(id=21)的quantity为8.0000579, unit_price为4.0000086
  548. const qty = [4.00000025, 2.0000001, 8.0000579];
  549. const up = [6.0000083, 5.000065, 4.0000086];
  550. const tp = [24.0000347, 10.0001305, 32.0003004];
  551. // 实际结果
  552. const fQty = [], fUp = [], fTp = [];
  553. for (const q of qty) {
  554. fQty.push(ctx.helper.round(q, ctx.tender.info.precision.other.value));
  555. }
  556. for (const p of up) {
  557. fUp.push(ctx.helper.round(p, ctx.tender.info.decimal.up));
  558. }
  559. for (const i in qty) {
  560. fTp.push(ctx.helper.times(fQty[i], fUp[i]));
  561. }
  562. const node1 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 11);
  563. assert(node1);
  564. const node2 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 20);
  565. assert(node2);
  566. const node3 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 21);
  567. assert(node3);
  568. const resultData = yield ctx.service.ledger.updateCalc(testTenderId, [{
  569. id: node1.id,
  570. tender_id: node1.tender_id,
  571. ledger_id: node1.ledger_id,
  572. quantity: qty[0],
  573. unit_price: up[0]
  574. }, {
  575. id: node2.id,
  576. tender_id: node2.tender_id,
  577. ledger_id: node2.ledger_id,
  578. quantity: qty[1],
  579. unit_price: up[1]
  580. }, {
  581. id: node3.id,
  582. tender_id: node3.tender_id,
  583. ledger_id: node3.ledger_id,
  584. quantity: qty[2],
  585. unit_price: up[2]
  586. }]);
  587. assert(resultData.update.length === 3);
  588. let node = findById(resultData.update, 11);
  589. assert(node.quantity == fQty[0]);
  590. assert(node.unit_price == fUp[0]);
  591. assert(node.total_price === fTp[0]);
  592. node = findById(resultData.update, 20);
  593. assert(node.quantity == fQty[1]);
  594. assert(node.unit_price == fUp[1]);
  595. assert(node.total_price === fTp[1]);
  596. node = findById(resultData.update, 21);
  597. assert(node.quantity == fQty[2]);
  598. assert(node.unit_price == fUp[2]);
  599. assert(node.total_price == fTp[2]);
  600. });
  601. /* 期望运行结果:
  602. 1
  603. ├── 1-1
  604. │ ├── 1-1-1
  605. │ │ └── 202-2
  606. │ │ ├── 202-2-c 4 6 24
  607. │ │ └── 202-2-e 2 3 6
  608. │ └── 1-1-4
  609. ├── 1-1-2
  610. │ └── 1-1-3
  611. ├── 1-2
  612. │ ├── 1-2-1
  613. │ ├── 1-2-2
  614. │ │ └── 202-2
  615. │ │ ├── 202-2-c 2 5 10
  616. │ │ └── 202-2-e 8 4 32
  617. │ ├── 1-2-3
  618. │ └── 1-3
  619. │ └── 1-3-1
  620. └── 1-4
  621. */
  622. // 复制整块+实时计算
  623. it('test pasteBlock - with Increment Calculate', function* () {
  624. const ctx = app.mockContext();
  625. // 选中1-1-4, 粘贴202-2(1-1-1下)
  626. const resultData = yield ctx.service.ledger.pasteBlock(testTenderId, 17, [8]);
  627. assert(resultData.ledger.create.length === 3);
  628. assert(resultData.ledger.update.length === 0);
  629. });
  630. /* 期望运行结果:
  631. 1
  632. ├── 1-1
  633. │ ├── 1-1-1
  634. │ │ └── 202-2
  635. │ │ ├── 202-2-c 4 6 24
  636. │ │ └── 202-2-e 2 3 6
  637. │ ├── 1-1-4
  638. │ └── 202-2
  639. │ ├── 202-2-c 4 6 24
  640. │ └── 202-2-e 2 3 6
  641. ├── 1-1-2
  642. │ └── 1-1-3
  643. ├── 1-2
  644. │ ├── 1-2-1
  645. │ ├── 1-2-2
  646. │ │ └── 202-2
  647. │ │ ├── 202-2-c 2 5 10
  648. │ │ └── 202-2-e 8 4 32
  649. │ ├── 1-2-3
  650. │ └── 1-3
  651. │ └── 1-3-1
  652. └── 1-4
  653. */
  654. // 树结构基本操作+实时计算
  655. it('test downLevel - with Increment Calculate', function* () {
  656. const ctx = app.mockContext();
  657. // 选中202-2(1-1-4后兄弟节点) 降级
  658. const resultData = yield ctx.service.ledger.downLevelNode(testTenderId, 23);
  659. assert(resultData.update.length === 4);
  660. });
  661. /* 期望运行结果:
  662. 1
  663. ├── 1-1
  664. │ ├── 1-1-1
  665. │ │ └── 202-2
  666. │ │ ├── 202-2-c 4 6 24
  667. │ │ └── 202-2-e 2 3 6
  668. │ └── 1-1-4
  669. │ └── 202-2
  670. │ ├── 202-2-c 4 6 24
  671. │ └── 202-2-e 2 3 6
  672. ├── 1-1-2
  673. │ └── 1-1-3
  674. ├── 1-2
  675. │ ├── 1-2-1
  676. │ ├── 1-2-2
  677. │ │ └── 202-2
  678. │ │ ├── 202-2-c 2 5 10
  679. │ │ └── 202-2-e 8 4 32
  680. │ ├── 1-2-3
  681. │ └── 1-3
  682. │ └── 1-3-1
  683. └── 1-4
  684. */
  685. it('test upLevel - with Increment Calculate', function* () {
  686. const ctx = app.mockContext();
  687. yield ctx.service.ledger.pasteBlock(testTenderId, 23, [23]);
  688. /* 期望运行结果:
  689. 1
  690. ├── 1-1
  691. │ ├── 1-1-1
  692. │ │ └── 202-2
  693. │ │ ├── 202-2-c 4 6 24
  694. │ │ └── 202-2-e 2 3 6
  695. │ └── 1-1-4
  696. │ ├── 202-2
  697. │ │ ├── 202-2-c 4 6 24
  698. │ │ └── 202-2-e 2 3 6
  699. │ └── 202-2
  700. │ ├── 202-2-c 4 6 24
  701. │ └── 202-2-e 2 3 6
  702. ├── 1-1-2
  703. │ └── 1-1-3
  704. ├── 1-2
  705. │ ├── 1-2-1
  706. │ ├── 1-2-2
  707. │ │ └── 202-2
  708. │ │ ├── 202-2-c 2 5 10
  709. │ │ └── 202-2-e 8 4 32
  710. │ ├── 1-2-3
  711. │ └── 1-3
  712. │ └── 1-3-1
  713. └── 1-4
  714. */
  715. // 选中202-2-c(1-1-4下)(id=23)升级
  716. const resultData = yield ctx.service.ledger.upLevelNode(testTenderId, 23);
  717. assert(resultData.update.length === 7);
  718. });
  719. /* 期望运行结果:
  720. 1
  721. ├── 1-1
  722. │ ├── 1-1-1
  723. │ │ └── 202-2
  724. │ │ ├── 202-2-c 4 6 24
  725. │ │ └── 202-2-e 2 3 6
  726. │ ├── 1-1-4
  727. │ └── 202-2
  728. │ ├── 202-2-c 4 6 24
  729. │ ├── 202-2-e 2 3 6
  730. │ └── 202-2
  731. │ ├── 202-2-c 4 6 24
  732. │ └── 202-2-e 2 3 6
  733. ├── 1-1-2
  734. │ └── 1-1-3
  735. ├── 1-2
  736. │ ├── 1-2-1
  737. │ ├── 1-2-2
  738. │ │ └── 202-2
  739. │ │ ├── 202-2-c 2 5 10
  740. │ │ └── 202-2-e 8 4 32
  741. │ ├── 1-2-3
  742. │ └── 1-3
  743. │ └── 1-3-1
  744. └── 1-4
  745. */
  746. it('test deleteNode - with Increment Calculate', function* () {
  747. const ctx = app.mockContext();
  748. // 选中202-2-c(1-2-2下)(id=20),删除节点
  749. const resultData = yield ctx.service.ledger.deleteNode(testTenderId, 20);
  750. assert(resultData.delete.length === 1);
  751. assert(resultData.update.length === 1);
  752. });
  753. /* 期望运行结果:
  754. 1
  755. ├── 1-1
  756. │ ├── 1-1-1
  757. │ │ └── 202-2
  758. │ │ ├── 202-2-c 4 6 24
  759. │ │ └── 202-2-e 2 3 6
  760. │ ├── 1-1-4
  761. │ └── 202-2
  762. │ ├── 202-2-c 4 6 24
  763. │ ├── 202-2-e 2 3 6
  764. │ └── 202-2
  765. │ ├── 202-2-c 4 6 24
  766. │ └── 202-2-e 2 3 6
  767. ├── 1-1-2
  768. │ └── 1-1-3
  769. ├── 1-2
  770. │ ├── 1-2-1
  771. │ ├── 1-2-2
  772. │ │ └── 202-2
  773. │ │ └── 202-2-e 8 4 32
  774. │ ├── 1-2-3
  775. │ └── 1-3
  776. │ └── 1-3-1
  777. └── 1-4
  778. */
  779. // 从标准库添加数据
  780. // 检查添加,直接添加为选中节点子节点
  781. it('test addStdNode', function* () {
  782. const ctx = app.mockContext();
  783. // 选中1-1-4
  784. const selectData = yield ctx.service.ledger.getDataByCondition({ tender_id: testTenderId, code: '1-1-4' });
  785. assert(selectData);
  786. // 从标准库中添加1-1-5
  787. const condition1 = { list_id: 1, code: '1-1-5' };
  788. const libData1 = yield ctx.service.stdChapter.getDataByCondition(condition1);
  789. assert(libData1);
  790. const stdData1 = yield ctx.service.stdChapter.getDataByDataId(1, libData1.chapter_id);
  791. assert(stdData1);
  792. assert(stdData1.id === libData1.id);
  793. const result1 = yield ctx.service.ledger.addStdNode(testTenderId, selectData.ledger_id, stdData1);
  794. assert(result1);
  795. assert(result1.create.length === 1);
  796. assert(result1.update.length === 1);
  797. // 从标准库中添加101-1
  798. });
  799. /* 期望运行结果:
  800. 1
  801. ├── 1-1
  802. │ ├── 1-1-1
  803. │ │ └── 202-2
  804. │ │ ├── 202-2-c 4 6 24
  805. │ │ └── 202-2-e 2 3 6
  806. │ ├── 1-1-4
  807. │ ├── 1-1-5
  808. │ └── 202-2
  809. │ ├── 202-2-c 4 6 24
  810. │ ├── 202-2-e 2 3 6
  811. │ └── 202-2
  812. │ ├── 202-2-c 4 6 24
  813. │ └── 202-2-e 2 3 6
  814. ├── 1-1-2
  815. │ └── 1-1-3
  816. ├── 1-2
  817. │ ├── 1-2-1
  818. │ ├── 1-2-2
  819. │ │ └── 202-2
  820. │ │ └── 202-2-e 8 4 32
  821. │ ├── 1-2-3
  822. │ └── 1-3
  823. │ └── 1-3-1
  824. └── 1-4
  825. */
  826. it('test addStdNodeWithParent', function* () {
  827. const ctx = app.mockContext();
  828. // 从标准库添加1-4-2-1
  829. const condition1 = { list_id: 1, code: '1-4-2-1'};
  830. const libData1 = yield ctx.service.stdChapter.getDataByCondition(condition1);
  831. assert(libData1);
  832. const stdData1 = yield ctx.service.stdChapter.getDataByDataId(1, libData1.chapter_id);
  833. assert(stdData1);
  834. assert(stdData1.id === libData1.id);
  835. const result1 = yield ctx.service.ledger.addStdNodeWithParent(testTenderId, stdData1, ctx.service.stdChapter);
  836. assert(result1);
  837. assert(result1.create.length === 4);
  838. assert(!result1.update || result1.update.length === 0);
  839. assert(!result1.expand || result1.expand.length === 0);
  840. // 从标准库添加1-4-2-1-2
  841. const condition2 = { list_id: 1, code: '1-4-2-1-2'};
  842. const libData2 = yield ctx.service.stdChapter.getDataByCondition(condition2);
  843. assert(libData2);
  844. const stdData2 = yield ctx.service.stdChapter.getDataByDataId(1, libData2.chapter_id);
  845. assert(stdData2);
  846. assert(stdData2.id === libData2.id);
  847. const result2 = yield ctx.service.ledger.addStdNodeWithParent(testTenderId, stdData2, ctx.service.stdChapter);
  848. assert(result2);
  849. assert(result2.create.length === 1);
  850. assert(result2.update.length === 1);
  851. assert(result2.update[0].code = '1-4-2-1');
  852. assert(!result2.update[0].is_leaf);
  853. // 从标准库添加1-4-2-1-1
  854. const condition3 = { list_id: 1, code: '1-4-2-1-1'};
  855. const libData3 = yield ctx.service.stdChapter.getDataByCondition(condition3);
  856. assert(libData3);
  857. const stdData3 = yield ctx.service.stdChapter.getDataByDataId(1, libData3.chapter_id);
  858. assert(stdData3);
  859. assert(stdData3.id === libData3.id);
  860. const result3 = yield ctx.service.ledger.addStdNodeWithParent(testTenderId, stdData3, ctx.service.stdChapter);
  861. assert(result3);
  862. assert(result3.create.length === 1);
  863. assert(result3.create[0].order === 1);
  864. assert(result3.update.length === 1);
  865. assert(result3.update[0].code === '1-4-2-1-2');
  866. assert(result3.update[0].order === 2);
  867. });
  868. /* 期望运行结果:
  869. 1
  870. ├── 1-1
  871. │ ├── 1-1-1
  872. │ │ └── 202-2
  873. │ │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  874. │ │ └── 202-2-e 2.00000001 3.0000005 6.00000103
  875. │ ├── 1-1-4
  876. │ ├── 1-1-5
  877. │ └── 202-2
  878. │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  879. │ ├── 202-2-e 2.00000001 3.0000005 6.00000103
  880. │ └── 202-2
  881. │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  882. │ └── 202-2-e 2.00000001 3.0000005 6.00000103
  883. ├── 1-1-2
  884. │ └── 1-1-3
  885. ├── 1-2
  886. │ ├── 1-2-1
  887. │ ├── 1-2-2
  888. │ │ └── 202-2
  889. │ │ └── 202-2-e 8.0000579 4.0000086 32.0003004
  890. │ ├── 1-2-3
  891. │ └── 1-3
  892. │ └── 1-3-1
  893. └── 1-4
  894. └── 1-4-2
  895. └── 1-4-2-1
  896. ├── 1-4-2-1-1
  897. └── 1-4-2-1-2
  898. */
  899. // 批量插入
  900. it('test batchInsertChild', function* () {
  901. const ctx = app.mockContext();
  902. // 计算需使用清单精度、小数位数
  903. ctx.tender = {id: testTenderId};
  904. ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
  905. ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
  906. // pos需要记录createUserId
  907. ctx.session = {
  908. sessionUser: {
  909. accountId: testUserId,
  910. },
  911. };
  912. const batchData = [
  913. {
  914. b_code: 401-1, name: 'A1', unit: 'B1', price: 2,
  915. pos: [{name: 'X1', quantity: 1}, {name: 'X2', quantity: 2}],
  916. },
  917. {
  918. b_code: 402-1, name: 'A2', unit: 'B2', price: 3,
  919. pos: [{name: 'X1', quantity: 3}, {name: 'X2', quantity: 4}],
  920. },
  921. ];
  922. // 选中1-1-3(id=14)
  923. const result = yield ctx.service.ledger.batchInsertChild(testTenderId, 14, batchData);
  924. assert(result.ledger.create.length === 2);
  925. let node = _.find(result.ledger.create, {name: 'A1'});
  926. assert(node.quantity === 3);
  927. assert(node.total_price === 6);
  928. node = _.find(result.ledger.create, {name: 'A2'});
  929. assert(node.quantity === 7);
  930. assert(node.total_price === 21);
  931. assert(result.pos.length === 4);
  932. });
  933. /* 期望运行结果:
  934. 1
  935. ├── 1-1
  936. │ ├── 1-1-1
  937. │ │ └── 202-2
  938. │ │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  939. │ │ └── 202-2-e 2.00000001 3.0000005 6.00000103
  940. │ ├── 1-1-4
  941. │ ├── 1-1-5
  942. │ └── 202-2
  943. │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  944. │ ├── 202-2-e 2.00000001 3.0000005 6.00000103
  945. │ └── 202-2
  946. │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  947. │ └── 202-2-e 2.00000001 3.0000005 6.00000103
  948. ├── 1-1-2
  949. │ └── 1-1-3
  950. │ ├── 401-1 2 3 6
  951. │ │ ├── (pos)X1 1
  952. │ │ └── (pos)X1 2
  953. │ └── 402-1 3 7 21
  954. │ ├── (pos)X1 3
  955. │ └── (pos)X2 4
  956. ├── 1-2
  957. │ ├── 1-2-1
  958. │ ├── 1-2-2
  959. │ │ └── 202-2
  960. │ │ └── 202-2-e 8.0000579 4.0000086 32.0003004
  961. │ ├── 1-2-3
  962. │ └── 1-3
  963. │ └── 1-3-1
  964. └── 1-4
  965. └── 1-4-2
  966. └── 1-4-2-1
  967. ├── 1-4-2-1-1
  968. └── 1-4-2-1-2
  969. */
  970. // 批量插入
  971. it('test batchInsertNext', function* () {
  972. const ctx = app.mockContext();
  973. // 计算需使用清单精度、小数位数
  974. ctx.tender = {id: testTenderId};
  975. ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
  976. ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
  977. // pos需要记录createUserId
  978. ctx.session = {
  979. sessionUser: {
  980. accountId: testUserId,
  981. },
  982. };
  983. const batchData = [
  984. {
  985. b_code: 403-1, name: 'A3', unit: 'B1', price: 2,
  986. pos: [{name: 'Y1', quantity: 5}, {name: 'Y2', quantity: 6}],
  987. },
  988. {
  989. b_code: 404-1, name: 'A4', unit: 'B2', price: 3,
  990. pos: [{name: 'Y1', quantity: 7}, {name: 'Y2', quantity: 8}],
  991. },
  992. ];
  993. // 选中1-1-3(id=14)
  994. const result = yield ctx.service.ledger.batchInsertNext(testTenderId, 14, batchData);
  995. assert(result.ledger.create.length === 2);
  996. let node = _.find(result.ledger.create, {name: 'A3'});
  997. assert(node.quantity === 11);
  998. assert(node.total_price === 22);
  999. node = _.find(result.ledger.create, {name: 'A4'});
  1000. assert(node.quantity === 15);
  1001. assert(node.total_price === 45);
  1002. assert(result.pos.length === 4);
  1003. });
  1004. /* 期望运行结果:
  1005. 1
  1006. ├── 1-1
  1007. │ ├── 1-1-1
  1008. │ │ └── 202-2
  1009. │ │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  1010. │ │ └── 202-2-e 2.00000001 3.0000005 6.00000103
  1011. │ ├── 1-1-4
  1012. │ ├── 1-1-5
  1013. │ └── 202-2
  1014. │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  1015. │ ├── 202-2-e 2.00000001 3.0000005 6.00000103
  1016. │ └── 202-2
  1017. │ ├── 202-2-c 4.00000025 6.0000083 24.0000347
  1018. │ └── 202-2-e 2.00000001 3.0000005 6.00000103
  1019. ├── 1-1-2
  1020. │ ├── 1-1-3
  1021. │ │ ├── 401-1 2 3 6
  1022. │ │ │ ├── (pos)X1 1
  1023. │ │ │ └── (pos)X1 2
  1024. │ │ └── 402-1 3 7 21
  1025. │ │ ├── (pos)X1 3
  1026. │ │ └── (pos)X2 4
  1027. │ ├── 403-1 2 11 22
  1028. │ │ ├── (pos)Y1 5
  1029. │ │ └── (pos)Y2 6
  1030. │ └── 404-1 3 15 45
  1031. │ ├── (pos)Y1 7
  1032. │ └── (pos)Y2 8
  1033. ├── 1-2
  1034. │ ├── 1-2-1
  1035. │ ├── 1-2-2
  1036. │ │ └── 202-2
  1037. │ │ └── 202-2-e 8.0000579 4.0000086 32.0003004
  1038. │ ├── 1-2-3
  1039. │ └── 1-3
  1040. │ └── 1-3-1
  1041. └── 1-4
  1042. └── 1-4-2
  1043. └── 1-4-2-1
  1044. ├── 1-4-2-1-1
  1045. └── 1-4-2-1-2
  1046. */
  1047. // 测试统计类方法
  1048. it('test addUpChildren', function* () {
  1049. const ctx = app.mockContext();
  1050. // 统计202-2(id=23)前两个子节点的金额
  1051. const result1 = yield ctx.service.ledger.addUpChildren(testTenderId, 23, 2, '<=');
  1052. assert(result1 && result1 === 30);
  1053. // 数据库不再存储父项金额,以下两个查询不能获得实际金额
  1054. // 统计202-2(id=23)后两个子节点的金额
  1055. //const result2 = yield ctx.service.ledger.addUpChildren(testTenderId, 23, 2, '>=');
  1056. //assert(result2 && result2.toFixed(8) == 36.00003676);
  1057. // 统计202-2(id=23)全部子节点的金额
  1058. //const result3 = yield ctx.service.ledger.addUpChildren(testTenderId, 23, 0, '>');
  1059. //assert(result3 && result3.toFixed(8) == 60.00007146);
  1060. });
  1061. // 测试搜索类方法
  1062. it('test search', function* () {
  1063. const ctx = app.mockContext();
  1064. const result = yield ctx.service.ledger.search(testTenderId, {
  1065. value: app.mysql.escape('%1-3%'),
  1066. operate: 'Like',
  1067. fields: ['code', 'name'],
  1068. });
  1069. assert(result.length === 3);
  1070. });
  1071. it('test searchRange', function* () {
  1072. const ctx = app.mockContext();
  1073. const result = yield ctx.service.ledger.searchRange(testTenderId, {
  1074. value: app.mysql.escape('%1-3%'),
  1075. operate: 'Like',
  1076. fields: ['code', 'name'],
  1077. }, [{
  1078. type: 'And',
  1079. value: app.mysql.escape('1.13.%'),
  1080. operate: 'Like',
  1081. fields: ['full_path'],
  1082. }]);
  1083. assert(result.length === 1);
  1084. assert(result[0].code === '1-1-3');
  1085. });
  1086. // it('test ImportExcelData', function* () {
  1087. // const ctx = app.mockContext();
  1088. //
  1089. // const file = ctx.app.baseDir + '/test/app/test_file/ledger-upload-test.xls';
  1090. // const sheets = excel.parse(file);
  1091. // const result = yield ctx.service.
  1092. // });
  1093. // 小数位数策略示例:
  1094. /* 先加总再保留3位小数:
  1095. 1 35.585
  1096. ├── 1-1 35.585
  1097. │ ├── 1-1-1 35.585
  1098. │ │ └── 202-2 35.585
  1099. │ │ ├── 202-2-c 4.25 6.83 29.028(29.0275)
  1100. │ │ └── 202-2-e 2.15 3.05 6.558(6.5575)
  1101. │ └── 1-1-3
  1102. ├── 1-1-2
  1103. │ └── 1-1-3
  1104. ├── 1-2
  1105. │ ├── 1-2-1
  1106. │ ├── 1-2-2
  1107. │ │ └── 202-2
  1108. │ │ ├── 202-2-c
  1109. │ │ └── 202-2-e
  1110. │ ├── 1-2-3
  1111. │ └── 1-3
  1112. │ └── 1-3-1
  1113. └── 1-4
  1114. */
  1115. /* 先保留3位小数再加总:
  1116. 1 35.586
  1117. ├── 1-1 35.586
  1118. │ ├── 1-1-1 35.586
  1119. │ │ └── 202-2 35.586
  1120. │ │ ├── 202-2-c 4.25 6.83 29.028(29.0275)
  1121. │ │ └── 202-2-e 2.15 3.05 6.558(6.5575)
  1122. │ └── 1-1-3
  1123. ├── 1-1-2
  1124. │ └── 1-1-3
  1125. ├── 1-2
  1126. │ ├── 1-2-1
  1127. │ ├── 1-2-2
  1128. │ │ └── 202-2
  1129. │ │ ├── 202-2-c
  1130. │ │ └── 202-2-e
  1131. │ ├── 1-2-3
  1132. │ └── 1-3
  1133. │ └── 1-3-1
  1134. └── 1-4
  1135. */
  1136. });