Skip to content

Commit 9b1f474

Browse files
Merge pull request #104 from StuartFerguson/task/#103_projectionsintests
Updated projections
2 parents 531b4ac + 0321bb8 commit 9b1f474

File tree

3 files changed

+183
-100
lines changed

3 files changed

+183
-100
lines changed

TransactionProcessor.IntegrationTests/Common/DockerHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ private async Task LoadEventStoreProjections()
190190
try
191191
{
192192
Logger.LogInformation($"Creating projection [{projectionName}]");
193-
await projectionClient.CreateContinuousAsync(projectionName, projection).ConfigureAwait(false);
193+
await projectionClient.CreateContinuousAsync(projectionName, projection, trackEmittedStreams:true).ConfigureAwait(false);
194194
}
195195
catch (Exception e)
196196
{
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
var fromAll = fromAll || require("../../node_modules/event-store-projection-testing").scope.fromAll;
2+
var linkTo = linkTo || require("../../node_modules/event-store-projection-testing").scope.linkTo;
3+
4+
isValidEvent = function (e) {
5+
6+
if (e) {
7+
if (e.data) {
8+
if (e.isJson) {
9+
if (e.eventType !== "$metadata") {
10+
return true;
11+
}
12+
}
13+
}
14+
}
15+
16+
return false;
17+
};
18+
19+
getMerchantId = function (e) {
20+
if (e.data.MerchantId === undefined) {
21+
return null;
22+
}
23+
return e.data.MerchantId;
24+
};
25+
26+
fromAll()
27+
.when({
28+
$any: function (s, e) {
29+
if (isValidEvent(e)) {
30+
var merchantId = getMerchantId(e);
31+
if (merchantId !== null) {
32+
s.merchantId = merchantId;
33+
var streamName = "MerchantArchive-" + merchantId.replace(/-/gi, "");
34+
s.streamName = streamName;
35+
linkTo(streamName, e, e.metadata);
36+
}
37+
}
38+
}
39+
});

TransactionProcessor.IntegrationTests/projections/continuous/MerchantBalanceCalculator.js

Lines changed: 143 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,18 @@
1-
var fromStreams = fromStreams || require('../../node_modules/event-store-projection-testing').scope.fromStreams;
1+
var fromCategory = fromCategory || require('../../node_modules/event-store-projection-testing').scope.fromCategory;
22
var partitionBy = partitionBy !== null ? partitionBy : require('../../node_modules/event-store-projection-testing').scope.partitionBy;
33
var emit = emit || require('../../node_modules/event-store-projection-testing').scope.emit;
44

5-
var incrementBalanceFromDeposit = function(s, merchantId, amount, dateTime) {
6-
var merchant = s.merchants[merchantId];
7-
merchant.Balance += amount;
8-
merchant.AvailableBalance += amount;
9-
// protect against events coming in out of order
10-
if (merchant.LastDepositDateTime === null || dateTime > merchant.LastDepositDateTime) {
11-
merchant.LastDepositDateTime = dateTime;
12-
}
13-
}
14-
15-
var addPendingBalanceUpdate = function(s, merchantId, amount, transactionId, dateTime)
16-
{
17-
var merchant = s.merchants[merchantId];
18-
merchant.AvailableBalance -= amount;
19-
merchant.PendingBalanceUpdates[transactionId] = {
20-
Amount: amount,
21-
TransactionId: transactionId
22-
};
23-
// protect against events coming in out of order
24-
if (merchant.LastSaleDateTime === null || dateTime > merchant.LastSaleDateTime)
25-
{
26-
merchant.LastSaleDateTime = dateTime;
27-
}
28-
}
5+
fromCategory('MerchantArchive')
6+
.foreachStream()
7+
.when({
8+
$any: function (s, e) {
299

30-
var decrementBalanceForSale = function(s, merchantId, transactionId, isAuthorised)
31-
{
32-
var merchant = s.merchants[merchantId];
33-
// lookup the balance update
34-
var balanceUpdate = merchant.PendingBalanceUpdates[transactionId];
10+
if (e === null || e.data === null || e.data.IsJson === false)
11+
return;
3512

36-
if (balanceUpdate !== undefined)
37-
{
38-
if (isAuthorised)
39-
{
40-
merchant.Balance -= balanceUpdate.Amount;
41-
}
42-
else
43-
{
44-
merchant.AvailableBalance += balanceUpdate.Amount;
13+
eventbus.dispatch(s, e);
4514
}
46-
47-
delete merchant.PendingBalanceUpdates[transactionId];
48-
}
49-
}
50-
15+
});
5116

5217
var eventbus = {
5318
dispatch: function (s, e) {
@@ -71,78 +36,157 @@ var eventbus = {
7136
transactionHasCompletedEventHandler(s, e);
7237
return;
7338
}
39+
40+
if (e.eventType === 'TransactionProcessor.Transaction.DomainEvents.MerchantFeeAddedToTransactionEvent') {
41+
merchantFeeAddedToTransactionEventHandler(s, e);
42+
return;
43+
}
7444
}
7545
}
7646

77-
var merchantCreatedEventHandler = function (s, e)
78-
{
79-
var merchantId = e.data.MerchantId;
80-
81-
if (s.merchants[merchantId] === undefined) {
82-
s.merchants[merchantId] = {
83-
MerchantId: e.data.MerchantId,
84-
MerchantName: e.data.MerchantName,
85-
AvailableBalance: 0,
86-
Balance: 0,
87-
LastDepositDateTime: null,
88-
LastSaleDateTime: null,
89-
PendingBalanceUpdates: []
90-
};
47+
function getStreamName(s) {
48+
return "MerchantBalanceHistory-" + s.merchantId.replace(/-/gi, "");
49+
}
50+
51+
function getEventTypeName() {
52+
return 'EstateReporting.BusinessLogic.Events.' + getEventType() + ', EstateReporting.BusinessLogic';
53+
}
54+
55+
function getEventType() { return "MerchantBalanceChangedEvent"; }
56+
57+
function generateEventId() {
58+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
59+
function (c) {
60+
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
61+
return v.toString(16);
62+
});
63+
}
64+
65+
var incrementBalanceFromDeposit = function (s, amount, dateTime) {
66+
s.balance += amount;
67+
s.availableBalance += amount;
68+
s.totalDeposits += amount;
69+
// protect against events coming in out of order
70+
if (s.lastDepositDateTime === null || dateTime > s.lastDepositDateTime) {
71+
s.lastDepositDateTime = dateTime;
72+
}
73+
};
74+
75+
var addPendingBalanceUpdate = function (s, amount, transactionId, dateTime) {
76+
s.availableBalance -= amount;
77+
s.pendingBalanceUpdates.push({
78+
amount: amount,
79+
transactionId: transactionId
80+
});
81+
// protect against events coming in out of order
82+
if (s.lastSaleDateTime === null || dateTime > s.lastSaleDateTime) {
83+
s.lastSaleDateTime = dateTime;
84+
}
85+
};
86+
87+
var incrementBalanceFromMerchantFee = function (s, amount, dateTime) {
88+
s.balance += amount;
89+
s.availableBalance += amount;
90+
s.totalFees += amount;
91+
92+
// protect against events coming in out of order
93+
if (s.lastFeeProcessedDateTime === null || dateTime > s.lastFeeProcessedDateTime) {
94+
s.lastFeeProcessedDateTime = dateTime;
9195
}
9296
}
9397

98+
var handlePendingBalanceUpdate = function (s, transactionId, isAuthorised) {
99+
// lookup the balance update
100+
//var balanceUpdate = s.pendingBalanceUpdates[transactionId];
101+
var balanceUpdateIndex = s.pendingBalanceUpdates.findIndex(element => element.transactionId === transactionId);
102+
var balanceUpdate = s.pendingBalanceUpdates[balanceUpdateIndex];
103+
if (balanceUpdate !== undefined) {
104+
if (isAuthorised) {
105+
s.balance -= balanceUpdate.amount;
106+
s.totalSales += balanceUpdate.amount;
107+
}
108+
else {
109+
s.availableBalance += balanceUpdate.amount;
110+
s.totalIncompleteSales += balanceUpdate.amount;
111+
}
112+
113+
s.pendingBalanceUpdates.splice(balanceUpdateIndex);
114+
return balanceUpdate.amount;
115+
}
116+
};
117+
118+
var merchantCreatedEventHandler = function (s, e) {
119+
120+
// Setup the state here
121+
s.estateId = e.data.EstateId;
122+
s.merchantId = e.data.MerchantId;
123+
s.merchantName = e.data.MerchantName;
124+
s.availableBalance = 0;
125+
s.balance = 0;
126+
s.lastDepositDateTime = null;
127+
s.lastSaleDateTime = null;
128+
s.lastFeeProcessedDateTime = null;
129+
s.pendingBalanceUpdates = [];
130+
s.totalDeposits = 0;
131+
s.totalSales = 0;
132+
s.totalIncompleteSales = 0;
133+
s.totalFees = 0;
134+
emitBalanceChangedEvent(s, 0, e.data.EventCreatedDateTime, "Merchant Created");
135+
};
136+
137+
var emitBalanceChangedEvent = function (s, changeAmount, dateTime, reference) {
138+
var balanceChangedEvent = {
139+
$type: getEventTypeName(),
140+
"merchantId": s.merchantId,
141+
"estateId": s.estateId,
142+
"availableBalance": s.availableBalance,
143+
"balance": s.balance,
144+
"changeAmount": changeAmount,
145+
"eventId": generateEventId(),
146+
"eventTimestamp": dateTime,
147+
"reference": reference
148+
}
149+
150+
// emit an balance changed event here
151+
emit(getStreamName(s), getEventType(), balanceChangedEvent);
152+
};
153+
94154
var depositMadeEventHandler = function (s, e) {
95-
var merchantId = e.data.MerchantId;
96-
var merchant = s.merchants[merchantId];
155+
incrementBalanceFromDeposit(s, e.data.Amount, e.data.DepositDateTime);
97156

98-
incrementBalanceFromDeposit(s, merchantId,e.data.Amount, e.data.DepositDateTime);
99-
}
157+
// emit an balance changed event here
158+
emitBalanceChangedEvent(s, e.data.Amount, e.data.DepositDateTime, "Merchant Deposit");
159+
};
100160

101-
var transactionHasStartedEventHandler = function(s, e)
102-
{
103-
// Add this to a pending balance update list
104-
var merchantId = e.data.MerchantId;
105-
var merchant = s.merchants[merchantId];
161+
var transactionHasStartedEventHandler = function (s, e) {
106162

107163
var amount = e.data.TransactionAmount;
108-
if (amount === undefined)
109-
{
164+
if (amount === undefined) {
110165
amount = 0;
111166
}
112167

113-
addPendingBalanceUpdate(s, merchantId,amount, e.data.TransactionId, e.data.TransactionDateTime);
114-
}
115-
116-
var transactionHasCompletedEventHandler = function(s, e)
117-
{
118168
// Add this to a pending balance update list
119-
var merchantId = e.data.MerchantId;
120-
var merchant = s.merchants[merchantId];
169+
addPendingBalanceUpdate(s, amount, e.data.TransactionId, e.data.TransactionDateTime);
121170

122-
decrementBalanceForSale(s, merchantId, e.data.TransactionId, e.data.IsAuthorised);
123-
}
171+
// emit an balance changed event here
172+
emitBalanceChangedEvent(s, 0, e.data.TransactionDateTime, "Transaction Started");
173+
};
124174

125-
fromStreams('$et-EstateManagement.Merchant.DomainEvents.MerchantCreatedEvent',
126-
'$et-EstateManagement.Merchant.DomainEvents.ManualDepositMadeEvent',
127-
'$et-TransactionProcessor.Transaction.DomainEvents.TransactionHasStartedEvent',
128-
'$et-TransactionProcessor.Transaction.DomainEvents.TransactionHasBeenCompletedEvent')
129-
.partitionBy(function(e)
130-
{
131-
return "MerchantBalanceHistory-" + e.data.MerchantId.replace(/-/gi, "");
132-
})
133-
.when({
134-
$init: function (s, e) {
135-
return {
136-
merchants: {},
137-
debug: []
138-
};
139-
},
175+
var transactionHasCompletedEventHandler = function (s, e) {
176+
// Handle the pending balance recorda
177+
var balanceUpdateValue = handlePendingBalanceUpdate(s, e.data.TransactionId, e.data.IsAuthorised);
178+
179+
// emit an balance changed event here
180+
emitBalanceChangedEvent(s, balanceUpdateValue, e.data.EventCreatedDateTime, "Transaction Completed");
181+
};
182+
183+
var merchantFeeAddedToTransactionEventHandler = function (s, e) {
184+
// increment the balance now
185+
incrementBalanceFromMerchantFee(s, e.data.CalculatedValue, e.data.EventCreatedDateTime);
186+
187+
// emit an balance changed event here
188+
emitBalanceChangedEvent(s, e.data.CalculatedValue, e.data.EventCreatedDateTime, "Transaction Fee Processed");
189+
}
140190

141-
$any: function (s, e) {
142191

143-
if (e === null || e.data === null || e.data.IsJson === false)
144-
return;
145192

146-
eventbus.dispatch(s, e);
147-
}
148-
});

0 commit comments

Comments
 (0)