Commit 0204ba4880843e467f86e9d587912077cbe429f7

Authored by Adhidarma Hadiwinoto
1 parent c453c120cc
Exists in master

Protheus tested

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

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