ledger.test.js 51 KB

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