@@ -136,4 +136,262 @@ describe('convertPdfStatementTransaction', () => {
136136 expect ( tx . comment ) . toEqual ( 'Выплата процентов по вкладу' )
137137 expect ( tx . merchant ) . toBeNull ( )
138138 } )
139+
140+ it ( 'builds transfer from deposit to card using deposit sync id from origin string' , ( ) => {
141+ const rawTransaction = {
142+ hold : false ,
143+ date : '2025-12-12T00:00:00.000Z' ,
144+ originalAmount : '+70000.00 KZT' ,
145+ amount : '+70000.00' ,
146+ description : 'Другое Плательщик: Иванов Иван Получатель: Иванов Иван Назначение: Выплата вклада по Договору No KZ00000B000000002KZT от 01.02.2025' ,
147+ statementUid : 'deposit-transfer-uid' ,
148+ originString : '12.12.2025 +70,000.00 ₸ KZT Другое Плательщик: Иванов Иван Получатель: Иванов Иван Назначение: Выплата вклада по Договору No KZ00000B000000002KZT от 01.02.2025'
149+ }
150+ const account = { id : 'KZCARD0001' , instrument : 'KZT' }
151+ const currencyRates = { }
152+
153+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account , currencyRates )
154+ if ( converted == null ) {
155+ throw new Error ( 'Expected conversion result' )
156+ }
157+ const tx = converted . transaction
158+ expect ( tx . movements ) . toHaveLength ( 2 )
159+ expect ( tx . movements [ 0 ] ) . toEqual ( expect . objectContaining ( {
160+ account : { id : 'KZCARD0001' } ,
161+ sum : 70000
162+ } ) )
163+ expect ( tx . movements [ 1 ] ) . toEqual ( expect . objectContaining ( {
164+ account : {
165+ type : AccountType . deposit ,
166+ instrument : 'KZT' ,
167+ company : null ,
168+ syncIds : [ 'KZ00000B000000002' ]
169+ } ,
170+ sum : - 70000
171+ } ) )
172+ } )
173+
174+ it ( 'removes processing marker from merchant title' , ( ) => {
175+ const rawTransaction = {
176+ hold : false ,
177+ date : '2025-12-09T00:00:00.000' ,
178+ originalAmount : '-1820.00 KZT' ,
179+ amount : '-1820.00' ,
180+ description : 'Покупка в обработке YANDEX.GO ALMATY KZ' ,
181+ statementUid : 'processing-marker-uid' ,
182+ originString : '09.12.2025 -1,820.00 ₸ KZT Сумма в обработке Покупка в обработке YANDEX.GO ALMATY KZ'
183+ }
184+ const account = { id : 'KZCARD0001' , instrument : 'KZT' }
185+ const currencyRates = { }
186+
187+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account , currencyRates )
188+ if ( converted == null ) {
189+ throw new Error ( 'Expected conversion result' )
190+ }
191+ const tx = converted . transaction
192+ expect ( tx . merchant ) . toEqual ( {
193+ title : 'YANDEX.GO' ,
194+ city : 'Almaty' ,
195+ country : 'Kazakhstan' ,
196+ mcc : null ,
197+ location : null ,
198+ category : null
199+ } )
200+ expect ( tx . hold ) . toBe ( true )
201+ } )
202+
203+ it ( 'treats deposit payout by contract as transfer from deposit to card' , ( ) => {
204+ const rawTransaction = {
205+ hold : false ,
206+ date : '2025-12-20T00:00:00.000Z' ,
207+ originalAmount : '+70000.00 KZT' ,
208+ amount : '+70000.00' ,
209+ description : 'Выплата вклада по Договору №\nKZ00000B000000002KZT от 01.02.2025.\nВкладчик: Тестовый Тест' ,
210+ statementUid : 'deposit-payout-uid' ,
211+ originString : '20.12.2025 +70,000.00 ₸ KZT Выплата вклада по Договору №\nKZ00000B000000002KZT от 01.02.2025.\nВкладчик: Тестовый Тест'
212+ }
213+ const account = { id : 'KZCARD0001' , instrument : 'KZT' }
214+ const currencyRates = { }
215+
216+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account , currencyRates )
217+ if ( converted == null ) {
218+ throw new Error ( 'Expected conversion result' )
219+ }
220+ const tx = converted . transaction
221+ expect ( tx . movements ) . toHaveLength ( 2 )
222+ expect ( tx . movements [ 0 ] ) . toEqual ( expect . objectContaining ( {
223+ account : { id : 'KZCARD0001' } ,
224+ sum : 70000
225+ } ) )
226+ expect ( tx . movements [ 1 ] ) . toEqual ( expect . objectContaining ( {
227+ account : {
228+ type : AccountType . deposit ,
229+ instrument : 'KZT' ,
230+ company : null ,
231+ syncIds : [ 'KZ00000B000000002' ]
232+ } ,
233+ sum : - 70000
234+ } ) )
235+ } )
236+
237+ it ( 'uses ccard counterpart for transfer when source account is deposit statement account' , ( ) => {
238+ const rawTransaction = {
239+ hold : false ,
240+ date : '2025-12-20T00:00:00.000Z' ,
241+ originalAmount : '-70000.00 KZT' ,
242+ amount : '-70000.00' ,
243+ description : 'Выплата вклада по Договору № KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест' ,
244+ statementUid : 'deposit-source-uid' ,
245+ originString : '20.12.2025 -70,000.00 ₸ KZT Другое Выплата вклада по Договору № KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест'
246+ }
247+ const account = { id : 'KZ00000B000000002KZT' , instrument : 'KZT' , type : AccountType . deposit }
248+ const currencyRates = { }
249+
250+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account as any , currencyRates )
251+ if ( converted == null ) {
252+ throw new Error ( 'Expected conversion result' )
253+ }
254+ const tx = converted . transaction
255+ expect ( tx . movements ) . toHaveLength ( 2 )
256+ expect ( tx . movements [ 0 ] ) . toEqual ( expect . objectContaining ( {
257+ account : { id : 'KZ00000B000000002KZT' } ,
258+ sum : - 70000
259+ } ) )
260+ expect ( tx . movements [ 1 ] ) . toEqual ( expect . objectContaining ( {
261+ account : {
262+ type : AccountType . ccard ,
263+ instrument : 'KZT' ,
264+ company : null ,
265+ syncIds : null
266+ } ,
267+ sum : 70000
268+ } ) )
269+ expect ( tx . comment ) . toBeNull ( )
270+ } )
271+
272+ it ( 'does not set merchant or comment for contract reference transfer text' , ( ) => {
273+ const rawTransaction = {
274+ hold : false ,
275+ date : '2026-01-10T00:00:00.000Z' ,
276+ originalAmount : '-30000.00 KZT' ,
277+ amount : '-30000.00' ,
278+ description : 'No KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест' ,
279+ statementUid : 'contract-ref-uid' ,
280+ originString : '10.01.2026 -30,000.00 ₸ KZT Другое No KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест'
281+ }
282+ const account = { id : 'KZ00000B000000002KZT' , instrument : 'KZT' , type : AccountType . deposit }
283+ const currencyRates = { }
284+
285+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account as any , currencyRates )
286+ if ( converted == null ) {
287+ throw new Error ( 'Expected conversion result' )
288+ }
289+ const tx = converted . transaction
290+ expect ( tx . comment ) . toBeNull ( )
291+ expect ( tx . merchant ) . toBeNull ( )
292+ } )
293+
294+ it ( 'parses card top-up from deposit reference as transfer with deposit sync id' , ( ) => {
295+ const rawTransaction = {
296+ hold : false ,
297+ date : '2026-01-15T00:00:00.000Z' ,
298+ originalAmount : '+35000.00 KZT' ,
299+ amount : '+35000.00' ,
300+ description : 'Другое KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест' ,
301+ statementUid : 'card-topup-from-deposit-uid' ,
302+ originString : '15.01.2026 +35,000.00 ₸ KZT Другое KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест'
303+ }
304+ const account = { id : 'KZCARD0001' , instrument : 'KZT' , type : AccountType . ccard }
305+ const currencyRates = { }
306+
307+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account as any , currencyRates )
308+ if ( converted == null ) {
309+ throw new Error ( 'Expected conversion result' )
310+ }
311+ const tx = converted . transaction
312+ expect ( tx . movements ) . toHaveLength ( 2 )
313+ expect ( tx . movements [ 0 ] ) . toEqual ( expect . objectContaining ( {
314+ account : { id : 'KZCARD0001' } ,
315+ sum : 35000
316+ } ) )
317+ expect ( tx . movements [ 1 ] ) . toEqual ( expect . objectContaining ( {
318+ account : {
319+ type : AccountType . deposit ,
320+ instrument : 'KZT' ,
321+ company : null ,
322+ syncIds : [ 'KZ00000B000000002' ]
323+ } ,
324+ sum : - 35000
325+ } ) )
326+ expect ( tx . comment ) . toBeNull ( )
327+ expect ( tx . merchant ) . toBeNull ( )
328+ } )
329+
330+ it ( 'does not treat ccard as deposit source even if account id ends with currency' , ( ) => {
331+ const rawTransaction = {
332+ hold : false ,
333+ date : '2026-01-17T00:00:00.000Z' ,
334+ originalAmount : '+10000.00 KZT' ,
335+ amount : '+10000.00' ,
336+ description : 'Другое KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест' ,
337+ statementUid : 'ccard-id-format-uid' ,
338+ originString : '17.01.2026 +10,000.00 ₸ KZT Другое KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест'
339+ }
340+ const account = { id : 'KZ43551B829618809KZT' , instrument : 'KZT' , type : AccountType . ccard }
341+ const currencyRates = { }
342+
343+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account as any , currencyRates )
344+ if ( converted == null ) {
345+ throw new Error ( 'Expected conversion result' )
346+ }
347+ const tx = converted . transaction
348+ expect ( tx . movements ) . toHaveLength ( 2 )
349+ expect ( tx . movements [ 0 ] ) . toEqual ( expect . objectContaining ( {
350+ account : { id : 'KZ43551B829618809KZT' } ,
351+ sum : 10000
352+ } ) )
353+ expect ( tx . movements [ 1 ] ) . toEqual ( expect . objectContaining ( {
354+ account : {
355+ type : AccountType . deposit ,
356+ instrument : 'KZT' ,
357+ company : null ,
358+ syncIds : [ 'KZ00000B000000002' ]
359+ } ,
360+ sum : - 10000
361+ } ) )
362+ } )
363+
364+ it ( 'normalizes wrong negative sign for payout transfer on card statement to income' , ( ) => {
365+ const rawTransaction = {
366+ hold : false ,
367+ date : '2026-01-16T00:00:00.000Z' ,
368+ originalAmount : '-35000.00 KZT' ,
369+ amount : '-35000.00' ,
370+ description : 'Другое KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест' ,
371+ statementUid : 'card-topup-wrong-sign-uid' ,
372+ originString : '16.01.2026 -35,000.00 ₸ KZT Другое Выплата вклада по Договору No KZ00000B000000002KZT от 01.02.2025. Вкладчик: Тестовый Тест'
373+ }
374+ const account = { id : 'KZCARD0001' , instrument : 'KZT' , type : AccountType . ccard }
375+ const currencyRates = { }
376+
377+ const converted = convertPdfStatementTransaction ( rawTransaction as any , account as any , currencyRates )
378+ if ( converted == null ) {
379+ throw new Error ( 'Expected conversion result' )
380+ }
381+ const tx = converted . transaction
382+ expect ( tx . movements ) . toHaveLength ( 2 )
383+ expect ( tx . movements [ 0 ] ) . toEqual ( expect . objectContaining ( {
384+ account : { id : 'KZCARD0001' } ,
385+ sum : 35000
386+ } ) )
387+ expect ( tx . movements [ 1 ] ) . toEqual ( expect . objectContaining ( {
388+ account : {
389+ type : AccountType . deposit ,
390+ instrument : 'KZT' ,
391+ company : null ,
392+ syncIds : [ 'KZ00000B000000002' ]
393+ } ,
394+ sum : - 35000
395+ } ) )
396+ } )
139397} )
0 commit comments