You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 line
15KB

  1. package main
  2. import (
  3. "fmt"
  4. log "github.com/sirupsen/logrus"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. "time"
  9. )
  10. var sample_resimac = `
  11. TRSTCD,ORGNTR,LOANNO,PORTNO,BRNAMX,LNAMT,INTRTE,DELRTE,MARGIN,SETLDX,LNBAL,MANFEE,RSINCP,RSSACT,RSSACP,SACAMT,MOFEE,MANTOT,NEWLON,REFADJ,NETNEW,FIXED,LNFORT,ORGNAM,LNEOM
  12. 335,8779,1,A ,Huang ,113423,3.79,3.36,0.43,02/08/2019,81865.89,29.73,0.6,60,0.18,-12.45,0,17.28,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  13. 334,8779,2,A ,Ding ,321030,3.72,3.16,0.56,12/10/2018,311077.1,143.25,1,60,0.28,-71.62,0,71.63,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  14. 334,8779,4,A ,Song ,640000,3.69,3.29,0.4,01/23/2019,607519.14,198.79,0.8,60,0.23,-114.3,0,84.49,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  15. 334,8779,4,B ,Song ,208000,3.69,3.29,0.4,01/23/2019,208055,68.4,0.8,60,0.23,-39.33,0,29.07,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  16. 337,8779,7,A ,Gill ,404376,3.79,3.26,0.53,02/25/2019,393745.79,171.5,1,60,0.28,-90.6,0,80.9,0,0,0, ,F,Super Finance Markets Pty Ltd ,202006
  17. 507,8779,9,A ,Lu ,980000,4.6,4.07,0.53,06/18/2019,980000,426.9,1,60,0.28,-225.53,0,201.37,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  18. 335,8779,10,A ,Sideris ,556000,3.32,2.79,0.53,04/23/2019,543091.68,236.7,1,60,0.28,-125.05,0,111.65,0,0,0, ,W,Super Finance Markets Pty Ltd ,202006
  19. 507,8779,13,A ,Lu ,570000,4.6,4.07,0.53,06/18/2019,50000,21.78,1,60,0.28,-11.51,0,10.27,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  20. 507,8779,14,A ,Lu ,970000,4.15,3.62,0.53,06/18/2019,954336.82,416.06,1,60,0.28,-219.8,0,196.26,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  21. 337,8779,18,A ,Chen ,444000,3.82,3.29,0.53,06/18/2019,444000,193.41,1,60,0.28,-102.18,0,91.23,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  22. 522,8779,19,A ,Horm ,944000,4.7,4.17,0.53,07/24/2019,544000,295.06,1,60,0.28,-155.88,0,139.18,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  23. 522,8779,21,A ,Kemp ,479952,4.25,3.72,0.53,07/24/2019,470613.4,204.94,1,60,0.28,-108.27,0,96.67,0,0,0, ,W,Super Finance Markets Pty Ltd ,202006
  24. 522,8779,24,A ,Tiang ,684481,4.7,4.17,0.53,08/23/2019,668000,290.99,1,60,0.28,-153.73,0,137.26,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  25. 500,8779,26,A ,Li ,564000,4.25,3.72,0.53,09/26/2019,557190.2,243,1,60,0.28,-128.38,0,114.62,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  26. 500,8779,27,A ,Quach ,406000,4.4,3.87,0.53,10/21/2019,398603.27,174.39,1,60,0.28,-92.13,0,82.26,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  27. 500,8779,27,B ,Quach ,406000,4.4,3.87,0.53,10/21/2019,406000,176.86,1,60,0.28,-93.44,0,83.42,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  28. 502,8779,28,A ,Zhu ,1000000,4.55,4.02,0.53,09/18/2019,988561.45,430.95,1,60,0.28,-227.67,0,203.28,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  29. 307,8779,30,A ,Huynh ,410453,3.22,2.69,0.53,09/19/2019,394606.79,172.23,1,60,0.28,-90.99,0,81.24,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  30. 500,8779,31,A ,Xu ,830000,4.15,3.62,0.53,01/30/2020,824329.48,359.53,1,60,0.28,-189.94,0,169.59,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  31. 305,8779,32,A ,Tran ,476000,3.52,2.99,0.53,10/03/2019,470274.11,204.88,1,60,0.28,-108.24,0,96.64,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  32. 334,8779,37,A ,Zulfaqari ,552000,3.22,2.69,0.53,12/19/2019,543482.81,237.12,1,60,0.28,-125.27,0,111.85,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  33. 308,8779,38,A ,Pham ,512000,3.22,2.69,0.53,01/10/2020,507925.37,221.37,1,60,0.28,-116.95,0,104.42,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  34. 310,8779,42,A ,Nguyen ,318542,3.52,2.99,0.53,12/06/2019,311782.42,135.71,1,60,0.28,-71.7,0,64.01,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  35. 334,8779,43,A ,Hopkins ,427505,3.52,2.99,0.53,01/08/2020,415112.03,180.87,1,60,0.28,-95.55,0,85.32,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  36. 334,8779,43,B ,Hopkins ,41567,3.52,2.99,0.53,01/08/2020,40011.29,17.43,1,60,0.28,-9.21,0,8.22,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  37. 334,8779,43,C ,Hopkins ,10292,3.52,2.99,0.53,01/08/2020,9991.49,4.35,1,60,0.28,-2.3,0,2.05,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  38. 308,8779,45,A ,Tran ,408000,3.22,2.69,0.53,12/06/2019,403381.11,175.81,1,60,0.28,-92.88,0,82.93,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  39. 308,8779,47,A ,Lebon ,100000,3.32,2.79,0.53,12/09/2019,44000,20.14,1,60,0.28,-10.64,0,9.5,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  40. 337,8779,48,A ,Le ,400000,3.22,2.69,0.53,12/03/2019,396171.84,172.6,1,60,0.28,-91.18,0,81.42,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  41. 308,8779,49,A ,Vu ,509600,3.22,2.69,0.53,12/13/2019,504687.98,220.02,1,60,0.28,-116.24,0,103.78,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  42. 500,8779,50,A ,Wang ,1500000,4.15,3.62,0.53,01/15/2020,1387663.97,604.28,1,60,0.28,-319.24,0,285.04,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  43. 308,8779,52,A ,Le ,520000,3.32,2.79,0.53,01/20/2020,513359.23,224.03,1,60,0.28,-118.36,0,105.67,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  44. 308,8779,54,A ,Nguyen ,268000,3.32,2.79,0.53,01/08/2020,265878.84,115.87,1,60,0.28,-61.21,0,54.66,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  45. 308,8779,56,A ,Hanna ,250000,3.22,2.69,0.53,01/09/2020,245368.96,107,1,60,0.28,-56.53,0,50.47,0,0,0, ,W,Super Finance Markets Pty Ltd ,202006
  46. 308,8779,57,A ,Le ,300000,3.22,2.69,0.53,01/08/2020,293231.8,127.97,1,60,0.28,-67.61,0,60.36,0,0,0, ,W,Super Finance Markets Pty Ltd ,202006
  47. 309,8779,58,A ,Le ,432000,3.22,2.69,0.53,12/17/2019,427824.14,186.53,1,60,0.28,-98.54,0,87.99,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  48. 308,8779,63,A ,Nguyen ,449175,3.22,2.69,0.53,12/23/2019,444814.79,194,1,60,0.28,-102.49,0,91.51,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  49. 308,8779,64,A ,Leav ,444000,3.42,2.89,0.53,01/07/2020,443334.6,193.23,1,60,0.28,-102.08,0,91.15,0,0,0, ,F,Super Finance Markets Pty Ltd ,202006
  50. 308,8779,66,A ,Nguyen ,516750,3.22,2.62,0.6,01/21/2020,511192.69,252.48,1,60,0.28,-117.82,0,134.66,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  51. 500,8779,69,A ,Leab ,435000,4.14,3.61,0.53,02/10/2020,432580.51,188.52,1,60,0.28,-99.59,0,88.93,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  52. 308,8779,71,A ,Yang ,511000,3.22,2.62,0.6,02/07/2020,506610.13,249.98,1,60,0.28,-116.66,0,133.32,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  53. 308,8779,76,A ,Huynh ,442060,3.22,2.62,0.6,02/28/2020,438854.39,216.79,1,60,0.28,-101.17,0,115.62,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  54. 308,8779,76,B ,Huynh ,77940,3.22,2.62,0.6,02/28/2020,77374.82,38.22,1,60,0.28,-17.84,0,20.38,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  55. 500,8779,82,A ,Pham ,788000,4.7,4.17,0.53,05/12/2020,791145.52,344.13,1,60,0.28,-181.81,0,162.32,0,0,0, ,M,Super Finance Markets Pty Ltd ,202006
  56. `
  57. type ResimacRow struct {
  58. TRSTCD int
  59. ORGNTR int
  60. LOANNO int
  61. PORTN string
  62. BRNAMX string //Brower
  63. LNAMT float64 //Loan amount
  64. INTRTE float64
  65. DELRTE float64
  66. MARGIN float64
  67. SETLDX time.Time //settled date
  68. LNBAL float64
  69. MANFEE float64
  70. RSINCP float64
  71. RSSACT float64
  72. RSSACP float64
  73. SACAMT float64
  74. MOFEE float64
  75. MANTOT float64
  76. NEWLON float64
  77. REFADJ float64
  78. NETNEW float64
  79. FIXED string
  80. LNFORT string
  81. ORGNAM string
  82. LNEOM time.Time
  83. //Derived attributes
  84. LoanNumber string
  85. Borrower string
  86. LoanAmount float64
  87. Balance float64
  88. IncomeAmount float64
  89. }
  90. type ResimacPdf struct {
  91. Period time.Time
  92. LoanNumber string
  93. Borrower string
  94. LoanAmount float64
  95. InterestRate float64
  96. DelvRate float64
  97. Margin float64
  98. Settlement time.Time
  99. Balance float64
  100. OffsetBalance float64
  101. GrossManFee float64
  102. IncentiveP float64
  103. Months int
  104. SacrificeP float64
  105. Fee float64
  106. MoFee float64
  107. NetManFee float64
  108. IncomeAmount float64
  109. }
  110. func (m *AiDecodeIncome) isResimacXls(raw string) bool {
  111. keyword := "TRSTCD,ORGNTR,LOANNO,PORTNO,BRNAMX,LNAMT,INTRTE,DELRTE,MARGIN,SETLDX,LNBAL,MANFEE,RSINCP,RSSACT,RSSACP,SACAMT,MOFEE,MANTOT,NEWLON,REFADJ,NETNEW,FIXED,LNFORT,ORGNAM,LNEOM"
  112. lines := strings.Split(raw, "\n")
  113. //remove all spaces
  114. for i := 0; i < len(lines); i++ {
  115. lines[i] = strings.ReplaceAll(lines[i], " ", "") // remove all spaces
  116. }
  117. return m.isKeywordExist(keyword, lines)
  118. }
  119. func (m *AiDecodeIncome) isResimacPdf(raw string) bool {
  120. keyword := "SuperFinanceMarketsPtyLtd-8779"
  121. lines := strings.Split(raw, "\n")
  122. //remove all spaces
  123. for i := 0; i < len(lines); i++ {
  124. lines[i] = strings.ReplaceAll(lines[i], " ", "") // remove all spaces
  125. }
  126. return m.isKeywordExist(keyword, lines)
  127. }
  128. func (m *AiDecodeIncome) decodeResimacXls(raw []byte) (e error) {
  129. m.ResimacXls = make([]ResimacRow, 0, 100)
  130. lines := strings.Split(string(raw), "\n")
  131. foundHeader := false
  132. var idx map[string]int
  133. for i := 0; i < len(lines); i++ {
  134. lines[i] = strings.ReplaceAll(lines[i], " ", "") // remove all spaces
  135. el := strings.Split(lines[i], ",")
  136. if len(el) < 25 {
  137. continue //bypass
  138. }
  139. if !foundHeader {
  140. foundHeader, idx = m.decodeResimacXlsHeader(lines[i])
  141. continue
  142. }
  143. //we have already found header
  144. r := ResimacRow{}
  145. r.TRSTCD, _ = strconv.Atoi(el[idx["TRSTCD"]])
  146. r.ORGNTR, _ = strconv.Atoi(el[1])
  147. r.LOANNO, _ = strconv.Atoi(el[2])
  148. r.PORTN = el[3]
  149. r.LoanNumber = fmt.Sprintf("%d-%06d-%06d%s", r.TRSTCD, r.ORGNTR, r.LOANNO, r.PORTN)
  150. r.BRNAMX = el[4]
  151. r.Borrower = r.BRNAMX
  152. r.LNAMT = m.currencyToFloat64(el[5])
  153. r.LoanAmount = r.LNAMT
  154. r.INTRTE = m.currencyToFloat64(el[6])
  155. r.DELRTE = m.currencyToFloat64(el[7])
  156. r.MARGIN = m.currencyToFloat64(el[8])
  157. r.SETLDX, _ = time.Parse("1/02/2006", el[9])
  158. r.LNBAL = m.currencyToFloat64(el[10])
  159. r.Balance = r.LNBAL
  160. r.MANFEE = m.currencyToFloat64(el[11])
  161. r.RSINCP = m.currencyToFloat64(el[12])
  162. r.RSSACT = m.currencyToFloat64(el[13])
  163. r.RSSACP = m.currencyToFloat64(el[14])
  164. r.SACAMT = m.currencyToFloat64(el[15])
  165. r.MOFEE = m.currencyToFloat64(el[16])
  166. r.MANTOT = m.currencyToFloat64(el[17])
  167. r.IncomeAmount = r.MANTOT
  168. r.NEWLON = m.currencyToFloat64(el[18])
  169. r.REFADJ = m.currencyToFloat64(el[19])
  170. r.NETNEW = m.currencyToFloat64(el[20])
  171. r.FIXED = el[21]
  172. r.LNFORT = el[22]
  173. r.ORGNAM = strings.TrimSpace(el[23])
  174. r.LNEOM, _ = time.Parse("200601", el[24])
  175. m.ResimacXls = append(m.ResimacXls, r)
  176. }
  177. return
  178. }
  179. func (m *AiDecodeIncome) decodeResimacXlsHeader(line string) (isHeaderLine bool, idx map[string]int) {
  180. keys := []string{
  181. "TRSTCD", "ORGNTR", "LOANNO", "PORTNO", "BRNAMX", "LNAMT", "INTRTE", "DELRTE",
  182. "MARGIN", "SETLDX", "LNBAL", "MANFEE", "RSINCP", "RSSACT", "RSSACP", "SACAMT",
  183. "MOFEE", "MANTOT", "NEWLON", "REFADJ", "NETNEW", "FIXED", "LNFORT", "ORGNAM",
  184. "LNEOM"}
  185. idx = make(map[string]int)
  186. l := strings.ReplaceAll(line, " ", "") // remove space
  187. el := strings.Split(l, ",")
  188. found := 0
  189. for i := 0; i < len(el); i++ {
  190. a := strings.TrimSpace(el[i])
  191. a = strings.ToUpper(a)
  192. for _, k := range keys {
  193. if a == k {
  194. idx[k] = i
  195. found++
  196. break
  197. }
  198. }
  199. }
  200. isHeaderLine = found > 20 // if we found more than 20 headers
  201. return
  202. }
  203. func (m *AiDecodeIncome) decodeResimacPdf(raw []byte) (e error) {
  204. m.ResimacPdf = make([]ResimacPdf, 0, 30)
  205. period := `(?i)Trailer +Fees Report[ :]+((?:Jan|January|Feb|February|Mar|March|Apr|April|May|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December)[\t ]+[0-9]{4})`
  206. pattern := `(?i)(\d+-0*8779-[\d A-Za-z-]+[A-Za-z]) +([A-Za-z]+) +(\$\d{1,3}(?:,\d{3})*(?:[\d.]\d{2})?) +(\d{1,3}(?:\.\d{1,2})?) +([\d ]{1,3}(?:[ .]\d{1,2})?) +(\d{1,3}(?:[\d.]\d{1,2})?) +((?:(?:[12][0-9]|0?[1-9])[/.-]0?2|(?:30|[12][0-9]|0?[1-9])[/.-](?:0?[469]|11)|(?:3[01]|[12][0-9]|0?[1-9])[/.-](?:0?[13578]|1[02]))[/.-][0-9]{4}) +(-?\$\d{1,3}(?:,\d{3,5})*(?:\.\d{1,2})?) +(-?[\d$]\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?) +(\$\d{1,3}(?:,\d{2,3})*(?:\.\d{1,2})?) +(\d{1,3}(?:\.\d{1,2})?) +(\d+) +(\d{1,3}\.?\d{1,2}) +(-?\$\d{1,3}(?:,,)*(?:\.\d{1,2})?) +(\$\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?) +(\$\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?)`
  207. periodLine, e := regexp.Compile(period)
  208. if e != nil {
  209. return
  210. }
  211. validLine, e := regexp.Compile(pattern) // error if regexp invalid
  212. if e != nil {
  213. return
  214. }
  215. periods := periodLine.FindSubmatch(raw)
  216. CurrentPeriod, e1 := time.Parse("January 2006", string(periods[1]))
  217. if e1 != nil {
  218. log.Warn("failed to parse period of resimac PDF", e1)
  219. }
  220. matches := validLine.FindAllSubmatch(raw, -1)
  221. if matches == nil {
  222. log.Warn("Resimac PDF decode found nothing no matches", raw)
  223. return
  224. }
  225. for _, v := range matches {
  226. rp := ResimacPdf{Period: CurrentPeriod}
  227. rp.LoanNumber = string(v[1])
  228. rp.Borrower = string(v[2])
  229. rp.LoanAmount = m.currencyToFloat64(string(v[3]))
  230. rp.InterestRate = m.currencyToFloat64(string(v[4]))
  231. rp.DelvRate = m.currencyToFloat64(string(v[5]))
  232. rp.Margin = m.currencyToFloat64(string(v[6]))
  233. rp.Settlement, _ = time.Parse("02/01/2006", string(v[7]))
  234. rp.Balance = m.currencyToFloat64(string(v[8]))
  235. rp.OffsetBalance = m.currencyToFloat64(string(v[9]))
  236. rp.GrossManFee = m.currencyToFloat64(string(v[10]))
  237. rp.IncentiveP = m.currencyToFloat64(string(v[11]))
  238. rp.Months, _ = strconv.Atoi(string(v[12]))
  239. rp.SacrificeP = m.currencyToFloat64(string(v[13]))
  240. rp.Fee = m.currencyToFloat64(string(v[14]))
  241. rp.MoFee = m.currencyToFloat64(string(v[15]))
  242. rp.NetManFee = m.currencyToFloat64(string(v[16]))
  243. rp.IncomeAmount = rp.NetManFee
  244. m.ResimacPdf = append(m.ResimacPdf, rp)
  245. }
  246. return
  247. }