Commit 893354b2d9d50045352a38c1130fc62f94f759cc

Authored by Adhidarma Hadiwinoto
1 parent 68717b5ed7
Exists in master

calculateBaseBillAmount fix tested

Showing 2 changed files with 66 additions and 2 deletions Inline Diff

1 /* eslint-disable no-console */
1 "use strict"; 2 "use strict";
2 3
3 const regexLooperReplace = require('tektrans-lib/regex-looper/replace'); 4 const regexLooperReplace = require('tektrans-lib/regex-looper/replace');
4 const rcFromMsg = require('komodo-sdk/rc-from-msg'); 5 const rcFromMsg = require('komodo-sdk/rc-from-msg');
5 const organicRc = require('./rc'); 6 const organicRc = require('./rc');
6 7
8 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) {
9 console.log('DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT detected');
10 }
11
7 function isInquiryResponseMessage(msg) { 12 function isInquiryResponseMessage(msg) {
8 return (msg || '').indexOf('CEK TAGIHAN') >= 0; 13 return (msg || '').indexOf('CEK TAGIHAN') >= 0;
9 } 14 }
10 15
11 function isPaymentResponseMessage(msg) { 16 function isPaymentResponseMessage(msg) {
12 return (msg || '').indexOf('BAYAR TAGIHAN') >= 0; 17 return (msg || '').indexOf('BAYAR TAGIHAN') >= 0;
13 } 18 }
14 19
15 function isPostpaidResponseMessage(msg) { 20 function isPostpaidResponseMessage(msg) {
16 return isInquiryResponseMessage(msg) || isPaymentResponseMessage(msg); 21 return isInquiryResponseMessage(msg) || isPaymentResponseMessage(msg);
17 } 22 }
18 23
19 function getRcFromMessage(msg, customRc) { 24 function getRcFromMessage(msg, customRc) {
20 let rc; 25 let rc;
21 if (customRc && Array.isArray(customRc) && customRc.length) { 26 if (customRc && Array.isArray(customRc) && customRc.length) {
22 rc = rcFromMsg(msg, customRc); 27 rc = rcFromMsg(msg, customRc);
23 } 28 }
24 29
25 if (!rc) { 30 if (!rc) {
26 rc = rcFromMsg(msg, organicRc); 31 rc = rcFromMsg(msg, organicRc);
27 } 32 }
28 33
29 return rc; 34 return rc;
30 } 35 }
31 36
32 function getPriceFromMessage(msg, rule) { 37 function getPriceFromMessage(msg, rule) {
33 if (typeof msg !== 'string') { 38 if (typeof msg !== 'string') {
34 return; 39 return;
35 } 40 }
36 41
37 if (process.env.DEBUG_IRS && !rule) { 42 if (process.env.DEBUG_IRS && !rule) {
38 console.log('** IRS.getPriceFromMessage no rule'); // eslint-disable-line no-console 43 console.log('** IRS.getPriceFromMessage no rule'); // eslint-disable-line no-console
39 } 44 }
40 45
41 if (process.env.DEBUG_IRS && rule) { 46 if (process.env.DEBUG_IRS && rule) {
42 console.log('** IRS.getPriceFromMessage rule: ' + JSON.stringify(rule, null, 2)); // eslint-disable-line no-console 47 console.log('** IRS.getPriceFromMessage rule: ' + JSON.stringify(rule, null, 2)); // eslint-disable-line no-console
43 } 48 }
44 49
45 //const pattern = (rule && typeof rule.pattern === 'string') ? rule.pattern : "Harga: ([\\d\\.]+?) "; 50 //const pattern = (rule && typeof rule.pattern === 'string') ? rule.pattern : "Harga: ([\\d\\.]+?) ";
46 const pattern = (rule && typeof rule.pattern === 'string') ? rule.pattern : "\\d+\\s+-\\s+([\\d,\\.]+)\\s+="; 51 const pattern = (rule && typeof rule.pattern === 'string') ? rule.pattern : "\\d+\\s+-\\s+([\\d,\\.]+)\\s+=";
47 const match_idx = (rule && typeof rule.match_idx === 'number') ? rule.match_idx : 1; 52 const match_idx = (rule && typeof rule.match_idx === 'number') ? rule.match_idx : 1;
48 53
49 const re = new RegExp(pattern); 54 const re = new RegExp(pattern);
50 const matches = msg.match(re); 55 const matches = msg.match(re);
51 if (process.env.DEBUG_IRS) { 56 if (process.env.DEBUG_IRS) {
52 console.log('** IRS.getPriceFromMessage msg: "' + msg + '" active_pattern: "' + pattern + '" active_match_idx: ' + match_idx); // eslint-disable-line no-console 57 console.log('** IRS.getPriceFromMessage msg: "' + msg + '" active_pattern: "' + pattern + '" active_match_idx: ' + match_idx); // eslint-disable-line no-console
53 console.log('** IRS.getPriceFromMessage matches:\n' + JSON.stringify(matches)); // eslint-disable-line no-console 58 console.log('** IRS.getPriceFromMessage matches:\n' + JSON.stringify(matches)); // eslint-disable-line no-console
54 } 59 }
55 60
56 if (matches && matches[match_idx]) { 61 if (matches && matches[match_idx]) {
57 const result = Number(matches[match_idx].replace(/\./g, '')); 62 const result = Number(matches[match_idx].replace(/\./g, ''));
58 if (process.env.DEBUG_IRS) { 63 if (process.env.DEBUG_IRS) {
59 console.log('** IRS.getPriceFromMessage SUPPLIER-PRICE: ' + result); // eslint-disable-line no-console 64 console.log('** IRS.getPriceFromMessage SUPPLIER-PRICE: ' + result); // eslint-disable-line no-console
60 } 65 }
61 return result; 66 return result;
62 } 67 }
63 } 68 }
64 69
65 function extractFromMessage(msg, rule) { 70 function extractFromMessage(msg, rule) {
66 if (typeof msg !== 'string') { return; } 71 if (typeof msg !== 'string') { return; }
67 72
68 if (!rule) { return; } 73 if (!rule) { return; }
69 74
70 if (typeof rule !== 'object') { 75 if (typeof rule !== 'object') {
71 return; 76 return;
72 } 77 }
73 78
74 rule.match_idx = Number(rule.match_idx); 79 rule.match_idx = Number(rule.match_idx);
75 80
76 if (!rule.match_idx) { 81 if (!rule.match_idx) {
77 rule.match_idx = 1; 82 rule.match_idx = 1;
78 } 83 }
79 84
80 const re = new RegExp(rule.pattern); 85 const re = new RegExp(rule.pattern);
81 const matches = msg.match(re); 86 const matches = msg.match(re);
82 if (matches && matches[rule.match_idx] && typeof matches[rule.match_idx] === 'string') { 87 if (matches && matches[rule.match_idx] && typeof matches[rule.match_idx] === 'string') {
83 return matches[rule.match_idx]; 88 return matches[rule.match_idx];
84 } 89 }
85 } 90 }
86 91
87 function getSnFromMessage(msg, rule) { 92 function getSnFromMessage(msg, rule) {
88 if (!rule) { 93 if (!rule) {
89 rule = { 94 rule = {
90 pattern: "[: ]S/*N:\\s*(.+?)\\s", 95 pattern: "[: ]S/*N:\\s*(.+?)\\s",
91 match_idx: 1 96 match_idx: 1
92 } 97 }
93 } 98 }
94 99
95 let sn = extractFromMessage(msg, rule); 100 let sn = extractFromMessage(msg, rule);
96 if (!sn || typeof sn !== 'string') { return; } 101 if (!sn || typeof sn !== 'string') { return; }
97 102
98 return sn.toUpperCase().replace(/[^a-zA-Z0-9:,/]/g, '-').replace(/-+/g, '-').replace(/-*\/-*/g, '/').replace(/^-+/, '').replace(/-+$/, ''); 103 return sn.toUpperCase().replace(/[^a-zA-Z0-9:,/]/g, '-').replace(/-+/g, '-').replace(/-*\/-*/g, '/').replace(/^-+/, '').replace(/-+$/, '');
99 } 104 }
100 105
101 function getBalanceFromMessage(msg, rule) { 106 function getBalanceFromMessage(msg, rule) {
102 if (!rule) { 107 if (!rule) {
103 rule = { 108 rule = {
104 pattern: "Saldo: .+? = ([\\d\\.]+) ", 109 pattern: "Saldo: .+? = ([\\d\\.]+) ",
105 match_idx: 1 110 match_idx: 1
106 } 111 }
107 } 112 }
108 113
109 let result = extractFromMessage(msg, rule); 114 let result = extractFromMessage(msg, rule);
110 if (!result || typeof result !== 'string') { return; } 115 if (!result || typeof result !== 'string') { return; }
111 116
112 return Number(result.replace(/\D/g, '')); 117 return Number(result.replace(/\D/g, ''));
113 } 118 }
114 119
115 function getDetailFromMessage(msg, rule, replacementRules) { 120 function getDetailFromMessage(msg, rule, replacementRules) {
116 if (!rule) { 121 if (!rule) {
117 rule = { 122 rule = {
118 pattern: " Detail:\\s*(.+?)\\s+Sisa [Ss]aldo", 123 pattern: " Detail:\\s*(.+?)\\s+Sisa [Ss]aldo",
119 match_idx: 1, 124 match_idx: 1,
120 } 125 }
121 } 126 }
122 127
123 return ( 128 return (
124 regexLooperReplace(extractFromMessage(msg, rule), replacementRules) || '' 129 regexLooperReplace(extractFromMessage(msg, rule), replacementRules) || ''
125 ).trim() || null; 130 ).trim() || null;
126 } 131 }
127 132
128 function splitPostpaidDetail(str) { 133 function splitPostpaidDetail(str) {
129 const retval = (str || '') 134 const retval = (str || '')
130 .split('/') 135 .split('/')
131 .map((item) => { 136 .map((item) => {
132 let [keyword, value] = item.split(':'); 137 let [keyword, value] = item.split(':');
133 keyword = (keyword || '').trim() 138 keyword = (keyword || '').trim()
134 139
135 if (keyword === 'N') keyword = 'SN'; 140 if (keyword === 'N') keyword = 'SN';
136 141
137 return { 142 return {
138 keyword, 143 keyword,
139 value: (value || '').trim(), 144 value: (value || '').trim(),
140 }; 145 };
141 }) 146 })
142 .filter((item) => item.keyword.length && item.value.length); 147 .filter((item) => item.keyword.length && item.value.length);
143 return retval; 148 return retval;
144 } 149 }
145 150
146 function calculateBaseBillAmountAuto(detailSplitted, customKeywords, productKeyval) { 151 function calculateBaseBillAmountAuto(detailSplitted, customKeywords, productKeyval) {
147 const tagihanAsliKeyvalKeywords = (productKeyval && productKeyval.KEYWORD_TAGASLI) ? productKeyval.KEYWORD_TAGASLI.split(/ *, */) 152 const tagihanAsliKeyvalKeywords = (productKeyval && productKeyval.KEYWORD_TAGASLI) ? productKeyval.KEYWORD_TAGASLI.split(/ *, */)
148 : null; 153 : null;
149 154
150 const keywords = (tagihanAsliKeyvalKeywords && Array.isArray(tagihanAsliKeyvalKeywords) && tagihanAsliKeyvalKeywords.length && tagihanAsliKeyvalKeywords) 155 const keywords = (tagihanAsliKeyvalKeywords && Array.isArray(tagihanAsliKeyvalKeywords) && tagihanAsliKeyvalKeywords.length && tagihanAsliKeyvalKeywords)
151 || customKeywords 156 || customKeywords
152 || ['TAGIHANASLI', 'TAGIHAN', 'DENDA', 'RPPREMI', 'BIAYA']; 157 || ['TAGIHANASLI', 'TAGIHAN', 'DENDA', 'RPPREMI', 'BIAYA'];
153 158
154 let retval = 0; 159 let retval = 0;
155 let detailCount = (detailSplitted || []).length; 160 let detailCount = (detailSplitted || []).length;
156 161
157 for (let i = 0; i < detailCount; i += 1) { 162 for (let i = 0; i < detailCount; i += 1) {
158 const item = detailSplitted[i]; 163 const item = detailSplitted[i];
159 if (keywords.indexOf(item.keyword.toUpperCase()) >= 0) { 164 if (keywords.indexOf(item.keyword.toUpperCase()) >= 0) {
160 const value = (item.value || '').trim().replace(/^rp */i, '').replace(/\./g, ''); 165 const value = (item.value || '').trim().replace(/^rp */i, '').replace(/\./g, '');
161 retval += Number(value) || 0; 166 retval += Number(value) || 0;
162 } 167 }
163 } 168 }
164 169
165 return retval; 170 return retval;
166 } 171 }
167 172
168 function calculateBaseBillAmount(detailSplitted, customKeywords, productKeyval, billCount) { 173 function calculateBaseBillAmount(detailSplitted, customKeywords, productKeyval, billCount) {
169 if ( 174 if (
170 !productKeyval 175 !productKeyval
171 || !productKeyval.KEYWORD_TOTALTAG 176 || !productKeyval.KEYWORD_TOTALTAG
172 || (!productKeyval.KEYWORD_ADMINFEE && !!productKeyval.ADMINFEE) 177 || (!productKeyval.KEYWORD_ADMINFEE && !productKeyval.ADMINFEE)
173 ) { 178 ) {
179 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) {
180 console.log(`=========== 0D299D07 using calculateBaseBillAmountAuto KEYWORD_TOTALTAG=${productKeyval.KEYWORD_TOTALTAG} KEYWORD_KEYWORD_ADMINFEE=${productKeyval.KEYWORD_ADMINFEE} KEYWORD_ADMINFEE=${productKeyval.ADMINFEE}`);
181 }
174 return calculateBaseBillAmountAuto(detailSplitted, customKeywords, productKeyval, billCount); 182 return calculateBaseBillAmountAuto(detailSplitted, customKeywords, productKeyval, billCount);
175 } 183 }
176 184
177 const billCountOrDefault = billCount || 1; 185 const billCountOrDefault = billCount || 1;
178 186
179 const totalTagihanKeyword = productKeyval.KEYWORD_TOTALTAG; 187 const totalTagihanKeyword = productKeyval.KEYWORD_TOTALTAG;
180 if (!totalTagihanKeyword) return 0; 188 if (!totalTagihanKeyword) return 0;
181 189
182 const totalTagihanItem = detailSplitted.find((item) => (item.keyword || '').toUpperCase() === totalTagihanKeyword.toUpperCase()); 190 const totalTagihanItem = detailSplitted.find((item) => (item.keyword || '').toUpperCase() === totalTagihanKeyword.toUpperCase());
183 const totalTagihanValue = Number( 191 const totalTagihanValue = Number(
184 ((totalTagihanItem && totalTagihanItem.value) || '') 192 ((totalTagihanItem && totalTagihanItem.value) || '')
185 .trim() 193 .trim()
186 .replace(/^rp */i, '') 194 .replace(/^rp */i, '')
187 .replace(/\./g, '') 195 .replace(/\./g, '')
188 ); 196 );
189 197
190 if (!totalTagihanValue) { 198 if (!totalTagihanValue) {
191 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) { 199 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) {
192 // eslint-disable-next-line no-console
193 console.log('=========== MISSING totalTagihanValue D7282FA7'); 200 console.log('=========== MISSING totalTagihanValue D7282FA7');
194 } 201 }
195 202
196 return 0; 203 return 0;
197 } 204 }
198 205
199 const defaultAdminFee = Number(productKeyval.ADMINFEE || ''); 206 const defaultAdminFee = Number(productKeyval.ADMINFEE || '');
200 207
201 const adminFeeKeyword = productKeyval.KEYWORD_ADMINFEE; 208 const adminFeeKeyword = productKeyval.KEYWORD_ADMINFEE;
202 if (!adminFeeKeyword && defaultAdminFee) { 209 if (!adminFeeKeyword && defaultAdminFee) {
203 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) { 210 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) {
204 // eslint-disable-next-line no-console 211 // eslint-disable-next-line no-console
205 console.log('======== TOTAL TAGIHAN VALUE - (DEFAULT ADMIN FEE * BILL COUNT) D35E56AD') ; 212 console.log('======== TOTAL TAGIHAN VALUE - (DEFAULT ADMIN FEE * BILL COUNT) D35E56AD') ;
206 } 213 }
207 return totalTagihanValue - (defaultAdminFee * billCountOrDefault); 214 return totalTagihanValue - (defaultAdminFee * billCountOrDefault);
208 } 215 }
209 216
210 if (!adminFeeKeyword) { 217 if (!adminFeeKeyword) {
211 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) { 218 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) {
212 // eslint-disable-next-line no-console 219 // eslint-disable-next-line no-console
213 console.log('======== Missing adminFeeKeyword'); 220 console.log('======== Missing adminFeeKeyword');
214 } 221 }
215 222
216 return 0; 223 return 0;
217 } 224 }
218 225
219 const adminFeeItem = detailSplitted.find((item) => (item.keyword || '').toUpperCase() === adminFeeKeyword.toUpperCase()); 226 const adminFeeItem = detailSplitted.find((item) => (item.keyword || '').toUpperCase() === adminFeeKeyword.toUpperCase());
220 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) { 227 if (process.env.DEBUG_IRS_CALCULATE_BASE_BILL_AMOUNT) {
221 // eslint-disable-next-line no-console 228 // eslint-disable-next-line no-console
222 console.log(`======== adminFeeItem: ${adminFeeKeyword}`, adminFeeItem); 229 console.log(`======== adminFeeItem: ${adminFeeKeyword}`, adminFeeItem);
223 } 230 }
224 const adminFeeValue = Number((adminFeeItem.value || '').trim().replace(/^rp */i, '').replace(/\./g, '')); 231 const adminFeeValue = Number((adminFeeItem.value || '').trim().replace(/^rp */i, '').replace(/\./g, ''));
225 if (!adminFeeValue) return 0; 232 if (!adminFeeValue) return 0;
226 233
227 return totalTagihanValue - (adminFeeValue * billCountOrDefault); 234 return totalTagihanValue - (adminFeeValue * billCountOrDefault);
228 } 235 }
229 236
230 237
231 function getBillCount(msg) { 238 function getBillCount(msg) {
232 const matches = (msg || '').match(/JMLBLN:(\d+)BLN/); 239 const matches = (msg || '').match(/JMLBLN:(\d+)BLN/);
233 return (matches && Number(matches[1])) || null; 240 return (matches && Number(matches[1])) || null;
234 } 241 }
235 242
236 exports.getRcFromMessage = getRcFromMessage; 243 exports.getRcFromMessage = getRcFromMessage;
237 exports.getPriceFromMessage = getPriceFromMessage; 244 exports.getPriceFromMessage = getPriceFromMessage;
238 exports.getSnFromMessage = getSnFromMessage; 245 exports.getSnFromMessage = getSnFromMessage;
239 exports.getBalanceFromMessage = getBalanceFromMessage; 246 exports.getBalanceFromMessage = getBalanceFromMessage;
240 exports.isInquiryResponseMessage = isInquiryResponseMessage; 247 exports.isInquiryResponseMessage = isInquiryResponseMessage;
241 exports.isPaymentResponseMessage = isPaymentResponseMessage; 248 exports.isPaymentResponseMessage = isPaymentResponseMessage;
242 exports.isPostpaidResponseMessage = isPostpaidResponseMessage; 249 exports.isPostpaidResponseMessage = isPostpaidResponseMessage;
243 exports.getDetailFromMessage = getDetailFromMessage; 250 exports.getDetailFromMessage = getDetailFromMessage;
244 exports.splitPostpaidDetail = splitPostpaidDetail; 251 exports.splitPostpaidDetail = splitPostpaidDetail;
245 exports.calculateBaseBillAmount = calculateBaseBillAmount; 252 exports.calculateBaseBillAmount = calculateBaseBillAmount;
246 exports.getBillCount = getBillCount; 253 exports.getBillCount = getBillCount;
test/supplier-htc-postpaid.js
File was created 1 /* global describe it */
2
3 require('should');
4
5 const irs = require('../index');
6
7 describe('Respon dari HTC postpaid', () => {
8 describe('#irs', () => {
9 describe('#calculateBaseBillAmount', () => {
10 it('should return correct value', () => {
11 const msg = 'CEK BPJSKS BERHASIL,SN:IDPEL:0001465757368,NAMA:BAMBANG PARTODEWO,CABANG:1101-SEMARANG,JML:,TOTALBAYAR:28.000';
12
13 const detailPattern = {
14 pattern: 'SN:(.*)($|(, *SALDO))',
15 match_idx: 1,
16 };
17
18 const detailReplacements = [
19 {
20 pattern: ' *\\.\\.+ *',
21 replacement: '/',
22 flags: 'g',
23 },
24 {
25 pattern: ' *, *',
26 replacement: '/',
27 flags: 'g',
28 },
29 {
30 pattern: ' *: *',
31 replacement: ':',
32 flags: 'g',
33 },
34 ]
35
36 const detail = irs.getDetailFromMessage(
37 msg,
38 detailPattern,
39 detailReplacements
40 );
41
42 detail.should.equal('IDPEL:0001465757368/NAMA:BAMBANG PARTODEWO/CABANG:1101-SEMARANG/JML:/TOTALBAYAR:28.000', 'HTC BPJSK POSTPAID getDetailFromMessage');
43 const detailSplitted = irs.splitPostpaidDetail(detail);
44
45 irs.calculateBaseBillAmount(
46 detailSplitted,
47 null,
48 {
49 KEYWORD_TOTALTAG: 'TOTALBAYAR',
50 ADMINFEE: '2500',
51 },
52 1,
53 ).should.equal(25500);
54 })
55 });
56 })
57 });