Skip to content

Commit 5abe52b

Browse files
authored
fix: bnp importer (#103)
1 parent 544eda6 commit 5abe52b

File tree

2 files changed

+208
-4
lines changed

2 files changed

+208
-4
lines changed

pkg/importers/common.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ func (b *BaseParser) ToCreateRequests(
6767
newTx.InternalReferenceNumbers = append(newTx.InternalReferenceNumbers, b.toKey(dup, importSource))
6868
}
6969

70+
if tx.ParsingError != nil {
71+
newTx.Extra["parsing_error"] = tx.ParsingError.Error()
72+
requests = append(requests, newTx)
73+
continue
74+
}
75+
7076
switch tx.Type {
7177
case TransactionTypeIncome:
7278
sourceAccount, err := b.GetDefaultAccountAndAmount(
@@ -221,10 +227,7 @@ func (b *BaseParser) ToCreateRequests(
221227
if newTx.Extra == nil {
222228
newTx.Extra = make(map[string]string)
223229
}
224-
if tx.ParsingError != nil {
225-
newTx.Extra["parsing_error"] = tx.ParsingError.Error()
226-
}
227-
// this is error transaction, will handle next
230+
newTx.Extra["unknown_type"] = fmt.Sprintf("%d", tx.Type)
228231
}
229232

230233
requests = append(requests, newTx)

pkg/importers/common_test.go

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
package importers_test
22

33
import (
4+
"context"
45
"testing"
6+
"time"
57

8+
importv1 "buf.build/gen/go/xskydev/go-money-pb/protocolbuffers/go/gomoneypb/import/v1"
9+
transactionsv1 "buf.build/gen/go/xskydev/go-money-pb/protocolbuffers/go/gomoneypb/transactions/v1"
610
v1 "buf.build/gen/go/xskydev/go-money-pb/protocolbuffers/go/gomoneypb/v1"
11+
"github.com/cockroachdb/errors"
712
"github.com/ft-t/go-money/pkg/database"
813
"github.com/ft-t/go-money/pkg/importers"
14+
"github.com/golang/mock/gomock"
15+
"github.com/shopspring/decimal"
916
"github.com/stretchr/testify/assert"
17+
"github.com/stretchr/testify/require"
1018
)
1119

1220
func TestGetAccountMapByNumbers(t *testing.T) {
@@ -155,6 +163,199 @@ func TestGetAccountMapByNumbers(t *testing.T) {
155163
})
156164
}
157165

166+
func TestToCreateRequests_ParsingError_Success(t *testing.T) {
167+
testCases := []struct {
168+
name string
169+
transaction *importers.Transaction
170+
expectedErr string
171+
}{
172+
{
173+
name: "expense with parsing error skips expense processing",
174+
transaction: &importers.Transaction{
175+
ID: "test-1",
176+
Type: importers.TransactionTypeExpense,
177+
SourceAmount: decimal.Zero,
178+
SourceCurrency: "PLN",
179+
DestinationAmount: decimal.Zero,
180+
DestinationCurrency: "PLN",
181+
Date: time.Now(),
182+
Description: "Pending transaction",
183+
ParsingError: errors.New("transaction is still pending"),
184+
},
185+
expectedErr: "transaction is still pending",
186+
},
187+
{
188+
name: "income with parsing error skips income processing",
189+
transaction: &importers.Transaction{
190+
ID: "test-2",
191+
Type: importers.TransactionTypeIncome,
192+
SourceAmount: decimal.Zero,
193+
SourceCurrency: "PLN",
194+
DestinationAmount: decimal.Zero,
195+
DestinationCurrency: "PLN",
196+
Date: time.Now(),
197+
Description: "Invalid income",
198+
ParsingError: errors.New("invalid amount format"),
199+
},
200+
expectedErr: "invalid amount format",
201+
},
202+
{
203+
name: "transfer with parsing error skips transfer processing",
204+
transaction: &importers.Transaction{
205+
ID: "test-3",
206+
Type: importers.TransactionTypeInternalTransfer,
207+
SourceAmount: decimal.Zero,
208+
SourceCurrency: "PLN",
209+
DestinationAmount: decimal.Zero,
210+
DestinationCurrency: "PLN",
211+
Date: time.Now(),
212+
Description: "Invalid transfer",
213+
ParsingError: errors.New("missing account"),
214+
},
215+
expectedErr: "missing account",
216+
},
217+
}
218+
219+
for _, tc := range testCases {
220+
t.Run(tc.name, func(t *testing.T) {
221+
ctrl := gomock.NewController(t)
222+
defer ctrl.Finish()
223+
224+
currencyConverter := NewMockCurrencyConverterSvc(ctrl)
225+
bp := importers.NewBaseParser(currencyConverter, nil, nil)
226+
227+
accountMap := map[string]*database.Account{
228+
"test-account": {
229+
ID: 1,
230+
Currency: "PLN",
231+
Type: v1.AccountType_ACCOUNT_TYPE_ASSET,
232+
},
233+
}
234+
235+
requests, err := bp.ToCreateRequests(
236+
context.Background(),
237+
[]*importers.Transaction{tc.transaction},
238+
false,
239+
accountMap,
240+
importv1.ImportSource_IMPORT_SOURCE_BNP_PARIBAS_POLSKA,
241+
)
242+
243+
require.NoError(t, err)
244+
require.Len(t, requests, 1)
245+
246+
req := requests[0]
247+
assert.Nil(t, req.Transaction)
248+
assert.Equal(t, tc.expectedErr, req.Extra["parsing_error"])
249+
assert.Equal(t, tc.transaction.Description, req.Title)
250+
})
251+
}
252+
}
253+
254+
func TestToCreateRequests_UnknownType_Success(t *testing.T) {
255+
ctrl := gomock.NewController(t)
256+
defer ctrl.Finish()
257+
258+
currencyConverter := NewMockCurrencyConverterSvc(ctrl)
259+
bp := importers.NewBaseParser(currencyConverter, nil, nil)
260+
261+
transaction := &importers.Transaction{
262+
ID: "test-unknown",
263+
Type: importers.TransactionType(99),
264+
SourceAmount: decimal.NewFromInt(100),
265+
SourceCurrency: "PLN",
266+
DestinationAmount: decimal.NewFromInt(100),
267+
DestinationCurrency: "PLN",
268+
Date: time.Now(),
269+
Description: "Unknown type transaction",
270+
}
271+
272+
accountMap := map[string]*database.Account{
273+
"test-account": {
274+
ID: 1,
275+
Currency: "PLN",
276+
Type: v1.AccountType_ACCOUNT_TYPE_ASSET,
277+
},
278+
}
279+
280+
requests, err := bp.ToCreateRequests(
281+
context.Background(),
282+
[]*importers.Transaction{transaction},
283+
false,
284+
accountMap,
285+
importv1.ImportSource_IMPORT_SOURCE_BNP_PARIBAS_POLSKA,
286+
)
287+
288+
require.NoError(t, err)
289+
require.Len(t, requests, 1)
290+
291+
req := requests[0]
292+
assert.Nil(t, req.Transaction)
293+
assert.Equal(t, "99", req.Extra["unknown_type"])
294+
}
295+
296+
func TestToCreateRequests_ExpenseWithValidData_Success(t *testing.T) {
297+
ctrl := gomock.NewController(t)
298+
defer ctrl.Finish()
299+
300+
currencyConverter := NewMockCurrencyConverterSvc(ctrl)
301+
currencyConverter.EXPECT().
302+
Convert(gomock.Any(), "PLN", "EUR", gomock.Any()).
303+
Return(decimal.NewFromInt(25), nil).
304+
Times(1)
305+
306+
bp := importers.NewBaseParser(currencyConverter, nil, nil)
307+
308+
transaction := &importers.Transaction{
309+
ID: "test-expense",
310+
Type: importers.TransactionTypeExpense,
311+
SourceAmount: decimal.NewFromInt(100),
312+
SourceCurrency: "PLN",
313+
SourceAccount: "source-acc",
314+
DestinationAmount: decimal.NewFromInt(100),
315+
DestinationCurrency: "PLN",
316+
Date: time.Now(),
317+
Description: "Valid expense",
318+
}
319+
320+
accountMap := map[string]*database.Account{
321+
"source-acc": {
322+
ID: 1,
323+
Currency: "PLN",
324+
Type: v1.AccountType_ACCOUNT_TYPE_ASSET,
325+
},
326+
"default-expense": {
327+
ID: 2,
328+
Currency: "EUR",
329+
Type: v1.AccountType_ACCOUNT_TYPE_EXPENSE,
330+
Flags: database.AccountFlagIsDefault,
331+
},
332+
}
333+
334+
requests, err := bp.ToCreateRequests(
335+
context.Background(),
336+
[]*importers.Transaction{transaction},
337+
false,
338+
accountMap,
339+
importv1.ImportSource_IMPORT_SOURCE_BNP_PARIBAS_POLSKA,
340+
)
341+
342+
require.NoError(t, err)
343+
require.Len(t, requests, 1)
344+
345+
req := requests[0]
346+
require.NotNil(t, req.Transaction)
347+
348+
expense, ok := req.Transaction.(*transactionsv1.CreateTransactionRequest_Expense)
349+
require.True(t, ok)
350+
assert.Equal(t, int32(1), expense.Expense.SourceAccountId)
351+
assert.Equal(t, "-100", expense.Expense.SourceAmount)
352+
assert.Equal(t, "PLN", expense.Expense.SourceCurrency)
353+
assert.Equal(t, int32(2), expense.Expense.DestinationAccountId)
354+
assert.Equal(t, "25", expense.Expense.DestinationAmount)
355+
assert.Equal(t, "EUR", expense.Expense.DestinationCurrency)
356+
assert.Empty(t, req.Extra["parsing_error"])
357+
}
358+
158359
func TestDecodeFiles(t *testing.T) {
159360
bp := importers.NewBaseParser(nil, nil, nil)
160361

0 commit comments

Comments
 (0)