@sneat/extension-debtus 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,196 +1,90 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, Injectable } from '@angular/core';
3
3
  import { SneatApiService } from '@sneat/api';
4
- import { debtDirectionToApiDirection, apiDirectionToDebtDirection, DEBTUS_SERVICE } from '@sneat/extension-debtus-contract';
5
- import { of, throwError, map } from 'rxjs';
4
+ import { parseRecordDebtusSourceRepaymentV1Request, parseRecordDebtusSourceRepaymentV1Response, parseDebtusSourceObligationDueDateV1, debtDirectionToApiDirection, apiDirectionToDebtDirection, parseDebtusTransferDueDateV1, parseDebtusTransferRepaymentV1, DEBTUS_SERVICE, DEBTUS_SOURCE_REPAYMENT_SERVICE_V1, DEBTUS_SOURCE_OBLIGATION_DUE_DATE_SERVICE_V1, DEBTUS_TRANSFER_DUE_DATE_SERVICE } from '@sneat/extension-debtus-contract';
5
+ import { map } from 'rxjs';
6
+ import { HttpParams } from '@angular/common/http';
6
7
 
7
- // ===========================================================================
8
- // Fable: prototype demo data
9
- // ---------------------------------------------------------------------------
10
- // These fixtures back the debtus web-UI flows that do NOT yet have a wired,
11
- // authenticated Go HTTP endpoint (balances summary, contacts list, per-contact
12
- // balance, transfer history). They are shaped exactly like the real contract
13
- // models so that when the backend endpoints are wired (see PR notes:
14
- // api4unsorted contacts CRUD + a balances endpoint), the internal service can
15
- // swap `of(demo…)` for a `sneatApiService.get(…)` call with no UI changes.
16
- //
17
- // Counterparties are modelled as contactus space contacts (contactID = a
18
- // contactus contact id) debtus does NOT own a separate contact list.
19
- // `bff-friend` is intentionally in a DIFFERENT space to exercise cross-space
20
- // lending in the UI.
21
- // ===========================================================================
22
- const DEMO_CONTACT_BALANCES = [
23
- {
24
- contactID: 'contact-alice',
25
- title: 'Alice Johnson',
26
- balance: { USD: 120, EUR: 0 },
27
- },
28
- {
29
- contactID: 'contact-bob',
30
- title: 'Bob Smith',
31
- balance: { USD: -45 },
32
- },
33
- {
34
- contactID: 'contact-carol',
35
- title: 'Carol Lee',
36
- balance: { EUR: 30 },
37
- },
38
- {
39
- // Cross-space counterparty: belongs to their own personal space.
40
- contactID: 'contact-dave',
41
- title: 'Dave (family friend)',
42
- balance: { USD: 200 },
43
- counterpartySpaceID: 'space-dave-personal',
44
- },
45
- {
46
- contactID: 'contact-erin',
47
- title: 'Erin Park',
48
- balance: { EUR: 0, USD: 0 }, // settled up
49
- },
50
- ];
51
- function demoTransfersForSpace(spaceID) {
52
- return [
53
- {
54
- id: 'transfer-1001',
55
- direction: 'lend',
56
- amount: { currency: 'USD', value: 120 },
57
- counterpartyContactID: 'contact-alice',
58
- counterpartyTitle: 'Alice Johnson',
59
- note: 'Concert tickets',
60
- created: '2026-06-20T10:15:00Z',
61
- dueOn: '2026-07-20T00:00:00Z',
62
- isReturn: false,
63
- isOutstanding: true,
64
- creatorSpaceID: spaceID,
65
- },
66
- {
67
- id: 'transfer-1002',
68
- direction: 'borrow',
69
- amount: { currency: 'USD', value: 45 },
70
- counterpartyContactID: 'contact-bob',
71
- counterpartyTitle: 'Bob Smith',
72
- note: 'Lunch',
73
- created: '2026-06-22T12:30:00Z',
74
- isReturn: false,
75
- isOutstanding: true,
76
- creatorSpaceID: spaceID,
77
- },
78
- {
79
- id: 'transfer-1003',
80
- direction: 'lend',
81
- amount: { currency: 'EUR', value: 30 },
82
- counterpartyContactID: 'contact-carol',
83
- counterpartyTitle: 'Carol Lee',
84
- created: '2026-06-25T09:00:00Z',
85
- isReturn: false,
86
- isOutstanding: true,
87
- creatorSpaceID: spaceID,
88
- },
89
- {
90
- id: 'transfer-1004',
91
- direction: 'lend',
92
- amount: { currency: 'USD', value: 200 },
93
- counterpartyContactID: 'contact-dave',
94
- counterpartyTitle: 'Dave (family friend)',
95
- note: 'Cross-space loan (different space)',
96
- created: '2026-06-18T08:00:00Z',
97
- isReturn: false,
98
- isOutstanding: true,
99
- creatorSpaceID: spaceID,
100
- counterpartySpaceID: 'space-dave-personal',
101
- },
102
- {
103
- id: 'transfer-1005',
104
- direction: 'borrow',
105
- amount: { currency: 'USD', value: 20 },
106
- counterpartyContactID: 'contact-erin',
107
- counterpartyTitle: 'Erin Park',
108
- note: 'Coffee (already returned)',
109
- created: '2026-06-10T08:00:00Z',
110
- isReturn: false,
111
- isOutstanding: false,
112
- creatorSpaceID: spaceID,
113
- },
114
- ];
8
+ class DebtusSourceRepaymentService {
9
+ api = inject(SneatApiService);
10
+ recordSourceObligationRepayment(request) {
11
+ const validatedRequest = parseRecordDebtusSourceRepaymentV1Request(request);
12
+ return this.api
13
+ .post('api4debtus/source-obligation-repayment', validatedRequest)
14
+ .pipe(map((value) => parseRecordDebtusSourceRepaymentV1Response(value, validatedRequest)));
15
+ }
16
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusSourceRepaymentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
17
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusSourceRepaymentService });
18
+ }
19
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusSourceRepaymentService, decorators: [{
20
+ type: Injectable
21
+ }] });
22
+
23
+ class DebtusSourceDueDateService {
24
+ api = inject(SneatApiService);
25
+ setSourceObligationDueDate(request) {
26
+ return this.api
27
+ .post('api4debtus/source-obligation-due-date', request)
28
+ .pipe(map((value) => parseDueDateResult(value, request)));
29
+ }
30
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusSourceDueDateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
31
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusSourceDueDateService });
32
+ }
33
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusSourceDueDateService, decorators: [{
34
+ type: Injectable
35
+ }] });
36
+ function parseDueDateResult(value, request) {
37
+ const result = parseDebtusSourceObligationDueDateV1(value, request.source, request.lineID);
38
+ if (request.dueDate && result['dueDate'] !== request.dueDate) {
39
+ throw new TypeError('Debtus due-date response changed the requested date');
40
+ }
41
+ if (request.todoListID && result['todoListID'] !== request.todoListID) {
42
+ throw new TypeError('Debtus due-date response changed the selected list');
43
+ }
44
+ return result;
115
45
  }
116
46
 
117
47
  class DebtusService {
118
48
  sneatApiService = inject(SneatApiService);
119
- // ----- REAL endpoint: legacy thin create (kept, backwards compatible) -----
120
49
  createDebtRecord(request) {
121
50
  return this.sneatApiService.post('debtus/create_debt_record', request);
122
51
  }
123
- // ===========================================================================
124
- // Fable: prototype demo data
125
- // No wired, authenticated Go HTTP endpoint exists yet for balances / contacts
126
- // / history (api4unsorted contacts CRUD is defined but not mounted in
127
- // backend/debtus/module.go; there is no balances endpoint). These read from
128
- // fixtures. SWAP POINT: replace each `of(...)` with a `sneatApiService.get`
129
- // once the endpoints are wired — the return types already match.
130
- // ===========================================================================
131
52
  getContactBalances(spaceID) {
132
- // SWAP: this.sneatApiService.get<IContactBalance[]>('api4debtus/user/contacts', new HttpParams().set('spaceID', spaceID))
133
- void spaceID;
134
- return of(DEMO_CONTACT_BALANCES.map((c) => ({ ...c })));
53
+ const params = new HttpParams().set('spaceID', spaceID);
54
+ return this.sneatApiService
55
+ .get('api4debtus/space/contact-balances', params)
56
+ .pipe(map((contacts) => contacts.map((contact) => ({
57
+ contactID: contact.contactID,
58
+ title: contact.title,
59
+ balance: centsBalanceToMajor(contact.balance),
60
+ counterpartySpaceID: contact.counterpartySpaceID,
61
+ }))));
135
62
  }
136
63
  getContactBalance(spaceID, contactID) {
137
- void spaceID;
138
- const found = DEMO_CONTACT_BALANCES.find((c) => c.contactID === contactID) ??
139
- {
140
- contactID,
141
- title: contactID,
142
- balance: {},
143
- };
144
- return of({ ...found });
64
+ return this.getContactBalances(spaceID).pipe(map((contacts) => contacts.find((c) => c.contactID === contactID)), map((contact) => {
65
+ if (!contact) {
66
+ throw new Error(`Debtus contact "${contactID}" was not found`);
67
+ }
68
+ return contact;
69
+ }));
145
70
  }
146
71
  getTransfers(spaceID, contactID) {
147
- // NOTE: GET /api4debtus/user/api4transfers exists but is currently broken
148
- // server-side (auth bug queries an empty userID). Using fixtures until the
149
- // backend fix lands. SWAP: this.sneatApiService.get('api4debtus/user/api4transfers', params).
150
- const all = demoTransfersForSpace(spaceID);
151
- return of(contactID
152
- ? all.filter((t) => t.counterpartyContactID === contactID)
153
- : all);
72
+ let params = new HttpParams().set('spaceID', spaceID);
73
+ if (contactID) {
74
+ params = params.set('contactID', contactID);
75
+ }
76
+ return this.sneatApiService
77
+ .get('api4debtus/space/transfers', params)
78
+ .pipe(map((dto) => dto.transfers.map(mapSpaceTransferDto)));
154
79
  }
155
- // ===========================================================================
156
- // REAL endpoints below.
157
- // ===========================================================================
158
- /** Reads from demo fixtures; unknown ids error (no fabricated receipts). */
159
80
  getTransfer(spaceID, transferID) {
160
- // The live GET transfer endpoint returns a perspective-resolved TransferDto.
161
- // For the prototype we resolve from fixtures so the receipt screen renders
162
- // without a live backend; SWAP to the real GET when running against a
163
- // deployed server:
164
- // const params = new HttpParams().set('id', transferID);
165
- // return this.sneatApiService
166
- // .get<IApiTransferDto>('api4debtus/transfer', params)
167
- // .pipe(map((dto) => this.mapTransferDto(dto, spaceID)));
168
- const found = demoTransfersForSpace(spaceID).find((t) => t.id === transferID);
169
- // Fable refactoring: a transfer that is not in the fixtures (i.e. any
170
- // REAL transfer just created via POST create-transfer) must be an error,
171
- // not a fabricated "Unknown / 0.00 USD / Outstanding" receipt — that was
172
- // presenting fiction as a financial record. The create/settle pages now
173
- // hand the created transfer to the details page via router state, so this
174
- // path is only hit on cold loads of unknown ids. The old synthesized
175
- // fallback is kept below (commented out) per the no-delete policy:
176
- // return of(
177
- // found ?? {
178
- // id: transferID,
179
- // direction: 'lend',
180
- // amount: { currency: 'USD', value: 0 },
181
- // counterpartyContactID: '',
182
- // counterpartyTitle: 'Unknown',
183
- // created: new Date().toISOString(),
184
- // isReturn: false,
185
- // isOutstanding: true,
186
- // creatorSpaceID: spaceID,
187
- // },
188
- // );
189
- return found
190
- ? of(found)
191
- : throwError(() => new Error(`Transfer "${transferID}" was not found (transfer reads are not wired to the live backend yet).`));
81
+ const params = new HttpParams()
82
+ .set('spaceID', spaceID)
83
+ .set('id', transferID);
84
+ return this.sneatApiService
85
+ .get('api4debtus/space/transfer', params)
86
+ .pipe(map(mapSpaceTransferDto));
192
87
  }
193
- /** REAL: POST /api4debtus/create-transfer (Firebase-authenticated). */
194
88
  createTransfer(request) {
195
89
  const apiDirection = debtDirectionToApiDirection(request.direction);
196
90
  const body = {
@@ -198,16 +92,10 @@ class DebtusService {
198
92
  direction: apiDirection,
199
93
  amount: {
200
94
  currency: request.amount.currency,
201
- value: request.amount.value,
95
+ value: majorToCents(request.amount.value),
202
96
  },
203
- // For u2c (lend) the counterparty is the recipient (toContactID); for
204
- // c2u (borrow) the counterparty is the source (fromContactID).
205
97
  toContactID: apiDirection === 'u2c' ? request.contactID : undefined,
206
98
  fromContactID: apiDirection === 'c2u' ? request.contactID : undefined,
207
- // The backend CreateTransferRequest accepts both `note` and
208
- // `counterpartySpaceID` (facade4debtus/transfers_create_transfer_dto.go);
209
- // omitting them silently discarded the user's typed note and the
210
- // cross-space marker on a financial write.
211
99
  note: request.note,
212
100
  counterpartySpaceID: request.counterpartySpaceID || undefined,
213
101
  isReturn: request.isReturn ?? false,
@@ -218,24 +106,10 @@ class DebtusService {
218
106
  .post('api4debtus/create-transfer', body)
219
107
  .pipe(map((resp) => this.mapCreateResponse(resp, request)));
220
108
  }
221
- /** Settle-up = a reverse-direction return transfer (mirrors the bot). */
222
109
  settleUp(request) {
223
- // Fable refactoring: the direction now comes from the request — the page
224
- // that shows the balance derives it via `settleDirectionForBalance` and is
225
- // the source of truth. Previously it was inferred from DEMO_CONTACT_BALANCES
226
- // fixtures, so any contact NOT in the fixtures got `'borrow'`
227
- // unconditionally and settling a debt the user owed recorded the WRONG
228
- // direction, increasing the imbalance. Old fixture-based inference kept
229
- // below per the no-delete policy:
230
- // const contact = DEMO_CONTACT_BALANCES.find(
231
- // (c) => c.contactID === request.contactID,
232
- // );
233
- // const currentValue = contact?.balance[request.amount.currency] ?? 0;
234
- // const direction = settleDirectionForBalance(currentValue || 1);
235
- const direction = request.direction;
236
110
  return this.createTransfer({
237
111
  spaceID: request.spaceID,
238
- direction,
112
+ direction: request.direction,
239
113
  amount: request.amount,
240
114
  contactID: request.contactID,
241
115
  contactTitle: request.contactTitle,
@@ -243,56 +117,37 @@ class DebtusService {
243
117
  counterpartySpaceID: request.counterpartySpaceID,
244
118
  });
245
119
  }
246
- // ----- mapping helpers -----
247
120
  mapCreateResponse(resp, request) {
248
121
  if (resp.Error) {
249
122
  throw new Error(resp.Error);
250
123
  }
251
- const transfer = resp.Transfer
252
- ? this.mapTransferDto(resp.Transfer, request.spaceID)
253
- : {
254
- // If the backend omits the transfer echo, synthesize from the request
255
- // so the UI can still navigate to a detail screen.
256
- id: `pending-${Date.now()}`,
124
+ if (!resp.Transfer) {
125
+ throw new Error('Debtus create-transfer response omitted the transfer');
126
+ }
127
+ const counterparty = resp.Transfer.To ?? resp.Transfer.From;
128
+ if (!counterparty) {
129
+ throw new Error('Debtus create-transfer response omitted the counterparty');
130
+ }
131
+ return {
132
+ transfer: {
133
+ id: resp.Transfer.Id,
257
134
  direction: request.direction,
258
- amount: request.amount,
259
- counterpartyContactID: request.contactID,
260
- counterpartyTitle: request.contactTitle ?? request.contactID,
135
+ amount: {
136
+ currency: request.amount.currency,
137
+ value: centsToMajor(resp.Transfer.Amount.value),
138
+ },
139
+ counterpartyContactID: counterparty.ID,
140
+ counterpartyTitle: counterparty.Name,
261
141
  note: request.note,
262
- created: new Date().toISOString(),
263
- dueOn: request.dueOn,
264
- isReturn: request.isReturn ?? false,
265
- isOutstanding: true,
142
+ created: resp.Transfer.Created,
143
+ dueOn: nonZeroDate(resp.Transfer.Due),
144
+ isReturn: resp.Transfer.IsReturn ?? false,
145
+ isOutstanding: resp.Transfer.IsOutstanding ?? !(resp.Transfer.IsReturn ?? false),
266
146
  creatorSpaceID: request.spaceID,
267
147
  counterpartySpaceID: request.counterpartySpaceID,
268
- };
269
- return {
270
- transfer,
271
- userBalance: (resp.UserBalance ?? {}),
272
- counterpartyBalance: (resp.CounterpartyBalance ??
273
- {}),
274
- };
275
- }
276
- mapTransferDto(dto, spaceID) {
277
- const counterparty = dto.To ?? dto.From;
278
- const direction = dto.Direction
279
- ? apiDirectionToDebtDirection(dto.Direction)
280
- : 'lend';
281
- return {
282
- id: dto.Id,
283
- direction,
284
- amount: {
285
- currency: (dto.Amount?.currency ?? 'USD'),
286
- value: dto.Amount?.value ?? 0,
287
148
  },
288
- counterpartyContactID: counterparty?.ID ?? '',
289
- counterpartyTitle: counterparty?.Name ?? 'Unknown',
290
- note: dto.Comment,
291
- created: dto.Created ?? new Date().toISOString(),
292
- dueOn: dto.Due,
293
- isReturn: dto.IsReturn ?? false,
294
- isOutstanding: dto.IsOutstanding ?? true,
295
- creatorSpaceID: spaceID,
149
+ userBalance: centsBalanceToMajor(resp.UserBalance ?? {}),
150
+ counterpartyBalance: centsBalanceToMajor(resp.CounterpartyBalance ?? {}),
296
151
  };
297
152
  }
298
153
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -301,17 +156,87 @@ class DebtusService {
301
156
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusService, decorators: [{
302
157
  type: Injectable
303
158
  }] });
159
+ function mapSpaceTransferDto(dto) {
160
+ return {
161
+ ...dto,
162
+ direction: apiDirectionToDebtDirection(dto.direction),
163
+ amount: {
164
+ currency: dto.amount.currency,
165
+ value: centsToMajor(dto.amount.value),
166
+ },
167
+ };
168
+ }
169
+ function centsBalanceToMajor(balance) {
170
+ return Object.fromEntries(Object.entries(balance).map(([currency, cents]) => [
171
+ currency,
172
+ centsToMajor(cents),
173
+ ]));
174
+ }
175
+ function majorToCents(value) {
176
+ return Math.round(value * 100);
177
+ }
178
+ function centsToMajor(value) {
179
+ return value / 100;
180
+ }
181
+ function nonZeroDate(value) {
182
+ return !value || value.startsWith('0001-01-01') ? undefined : value;
183
+ }
184
+
185
+ class DebtusTransferDueDateService {
186
+ api = inject(SneatApiService);
187
+ setTransferDueDate(request) {
188
+ return this.api
189
+ .post('api4debtus/transfer-due-date', request)
190
+ .pipe(map((value) => parseDebtusTransferDueDateV1(value, request.spaceID, request.transferID)));
191
+ }
192
+ getTransferDueDate(spaceID, transferID) {
193
+ const params = new HttpParams()
194
+ .set('spaceID', spaceID)
195
+ .set('transferID', transferID);
196
+ return this.api
197
+ .get('api4debtus/transfer-due-date-status', params)
198
+ .pipe(map((value) => parseDebtusTransferDueDateV1(value, spaceID, transferID)));
199
+ }
200
+ recordTransferRepayment(request) {
201
+ return this.api
202
+ .post('api4debtus/transfer-repayment', request)
203
+ .pipe(map((value) => parseDebtusTransferRepaymentV1(value, request)));
204
+ }
205
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusTransferDueDateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
206
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusTransferDueDateService });
207
+ }
208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: DebtusTransferDueDateService, decorators: [{
209
+ type: Injectable
210
+ }] });
304
211
 
305
212
  // Registers the concrete DebtusService and binds it to the DEBTUS_SERVICE token so
306
213
  // consumers depend only on the IDebtusService contract. Wired in at app
307
214
  // bootstrap (consumers do not import this factory directly).
308
215
  function provideDebtus() {
309
- return [DebtusService, { provide: DEBTUS_SERVICE, useExisting: DebtusService }];
216
+ return [
217
+ DebtusService,
218
+ DebtusSourceRepaymentService,
219
+ DebtusSourceDueDateService,
220
+ DebtusTransferDueDateService,
221
+ { provide: DEBTUS_SERVICE, useExisting: DebtusService },
222
+ {
223
+ provide: DEBTUS_SOURCE_REPAYMENT_SERVICE_V1,
224
+ useExisting: DebtusSourceRepaymentService,
225
+ },
226
+ {
227
+ provide: DEBTUS_SOURCE_OBLIGATION_DUE_DATE_SERVICE_V1,
228
+ useExisting: DebtusSourceDueDateService,
229
+ },
230
+ {
231
+ provide: DEBTUS_TRANSFER_DUE_DATE_SERVICE,
232
+ useExisting: DebtusTransferDueDateService,
233
+ },
234
+ ];
310
235
  }
311
236
 
312
237
  /**
313
238
  * Generated bundle index. Do not edit.
314
239
  */
315
240
 
316
- export { DebtusService, provideDebtus };
241
+ export { DebtusService, DebtusSourceDueDateService, DebtusSourceRepaymentService, DebtusTransferDueDateService, provideDebtus };
317
242
  //# sourceMappingURL=sneat-extension-debtus.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sneat-extension-debtus.mjs","sources":["../../../../../../libs/extensions/debtus/runtime/src/lib/services/demo-data.ts","../../../../../../libs/extensions/debtus/runtime/src/lib/services/debtus.service.ts","../../../../../../libs/extensions/debtus/runtime/src/lib/provide-debtus.ts","../../../../../../libs/extensions/debtus/runtime/src/sneat-extension-debtus.ts"],"sourcesContent":["import {\n IContactBalance,\n IDebtusTransfer,\n} from '@sneat/extension-debtus-contract';\n\n// ===========================================================================\n// Fable: prototype demo data\n// ---------------------------------------------------------------------------\n// These fixtures back the debtus web-UI flows that do NOT yet have a wired,\n// authenticated Go HTTP endpoint (balances summary, contacts list, per-contact\n// balance, transfer history). They are shaped exactly like the real contract\n// models so that when the backend endpoints are wired (see PR notes:\n// api4unsorted contacts CRUD + a balances endpoint), the internal service can\n// swap `of(demo…)` for a `sneatApiService.get(…)` call with no UI changes.\n//\n// Counterparties are modelled as contactus space contacts (contactID = a\n// contactus contact id) — debtus does NOT own a separate contact list.\n// `bff-friend` is intentionally in a DIFFERENT space to exercise cross-space\n// lending in the UI.\n// ===========================================================================\n\nexport const DEMO_CONTACT_BALANCES: readonly IContactBalance[] = [\n {\n contactID: 'contact-alice',\n title: 'Alice Johnson',\n balance: { USD: 120, EUR: 0 },\n },\n {\n contactID: 'contact-bob',\n title: 'Bob Smith',\n balance: { USD: -45 },\n },\n {\n contactID: 'contact-carol',\n title: 'Carol Lee',\n balance: { EUR: 30 },\n },\n {\n // Cross-space counterparty: belongs to their own personal space.\n contactID: 'contact-dave',\n title: 'Dave (family friend)',\n balance: { USD: 200 },\n counterpartySpaceID: 'space-dave-personal',\n },\n {\n contactID: 'contact-erin',\n title: 'Erin Park',\n balance: { EUR: 0, USD: 0 }, // settled up\n },\n];\n\nexport function demoTransfersForSpace(spaceID: string): IDebtusTransfer[] {\n return [\n {\n id: 'transfer-1001',\n direction: 'lend',\n amount: { currency: 'USD', value: 120 },\n counterpartyContactID: 'contact-alice',\n counterpartyTitle: 'Alice Johnson',\n note: 'Concert tickets',\n created: '2026-06-20T10:15:00Z',\n dueOn: '2026-07-20T00:00:00Z',\n isReturn: false,\n isOutstanding: true,\n creatorSpaceID: spaceID,\n },\n {\n id: 'transfer-1002',\n direction: 'borrow',\n amount: { currency: 'USD', value: 45 },\n counterpartyContactID: 'contact-bob',\n counterpartyTitle: 'Bob Smith',\n note: 'Lunch',\n created: '2026-06-22T12:30:00Z',\n isReturn: false,\n isOutstanding: true,\n creatorSpaceID: spaceID,\n },\n {\n id: 'transfer-1003',\n direction: 'lend',\n amount: { currency: 'EUR', value: 30 },\n counterpartyContactID: 'contact-carol',\n counterpartyTitle: 'Carol Lee',\n created: '2026-06-25T09:00:00Z',\n isReturn: false,\n isOutstanding: true,\n creatorSpaceID: spaceID,\n },\n {\n id: 'transfer-1004',\n direction: 'lend',\n amount: { currency: 'USD', value: 200 },\n counterpartyContactID: 'contact-dave',\n counterpartyTitle: 'Dave (family friend)',\n note: 'Cross-space loan (different space)',\n created: '2026-06-18T08:00:00Z',\n isReturn: false,\n isOutstanding: true,\n creatorSpaceID: spaceID,\n counterpartySpaceID: 'space-dave-personal',\n },\n {\n id: 'transfer-1005',\n direction: 'borrow',\n amount: { currency: 'USD', value: 20 },\n counterpartyContactID: 'contact-erin',\n counterpartyTitle: 'Erin Park',\n note: 'Coffee (already returned)',\n created: '2026-06-10T08:00:00Z',\n isReturn: false,\n isOutstanding: false,\n creatorSpaceID: spaceID,\n },\n ];\n}\n","import { Injectable, inject } from '@angular/core';\nimport { SneatApiService } from '@sneat/api';\nimport {\n IContactBalance,\n ICreateDebtRecordRequest,\n ICreateTransferRequest,\n ICreateTransferResponse,\n IDebtusService,\n IDebtusTransfer,\n ISettleUpRequest,\n apiDirectionToDebtDirection,\n debtDirectionToApiDirection,\n} from '@sneat/extension-debtus-contract';\nimport { Observable, map, of, throwError } from 'rxjs';\nimport { DEMO_CONTACT_BALANCES, demoTransfersForSpace } from './demo-data';\n\n// Backend DTO shapes (facade4debtus/dto4debtus). Only the fields the UI reads\n// are declared here.\ninterface IApiContactDto {\n readonly ID: string;\n readonly UserID?: string;\n readonly Name: string;\n readonly Comment?: string;\n}\n\ninterface IApiTransferDto {\n readonly Id: string;\n readonly Created: string;\n readonly Amount: { readonly currency: string; readonly value: number };\n readonly IsReturn?: boolean;\n readonly CreatorUserID?: string;\n readonly From?: IApiContactDto;\n readonly To?: IApiContactDto;\n readonly Due?: string;\n readonly Direction?: 'u2c' | 'c2u' | '3d-party';\n readonly IsOutstanding?: boolean;\n readonly Comment?: string;\n}\n\ninterface IApiCreateTransferResponse {\n readonly Error?: string;\n readonly Transfer?: IApiTransferDto;\n readonly UserBalance?: Record<string, number>;\n readonly CounterpartyBalance?: Record<string, number>;\n}\n\n@Injectable()\nexport class DebtusService implements IDebtusService {\n private readonly sneatApiService = inject(SneatApiService);\n\n // ----- REAL endpoint: legacy thin create (kept, backwards compatible) -----\n public createDebtRecord(\n request: ICreateDebtRecordRequest,\n ): Observable<string> {\n return this.sneatApiService.post('debtus/create_debt_record', request);\n }\n\n // ===========================================================================\n // Fable: prototype demo data\n // No wired, authenticated Go HTTP endpoint exists yet for balances / contacts\n // / history (api4unsorted contacts CRUD is defined but not mounted in\n // backend/debtus/module.go; there is no balances endpoint). These read from\n // fixtures. SWAP POINT: replace each `of(...)` with a `sneatApiService.get`\n // once the endpoints are wired — the return types already match.\n // ===========================================================================\n\n public getContactBalances(spaceID: string): Observable<IContactBalance[]> {\n // SWAP: this.sneatApiService.get<IContactBalance[]>('api4debtus/user/contacts', new HttpParams().set('spaceID', spaceID))\n void spaceID;\n return of(DEMO_CONTACT_BALANCES.map((c) => ({ ...c })));\n }\n\n public getContactBalance(\n spaceID: string,\n contactID: string,\n ): Observable<IContactBalance> {\n void spaceID;\n const found =\n DEMO_CONTACT_BALANCES.find((c) => c.contactID === contactID) ??\n ({\n contactID,\n title: contactID,\n balance: {},\n } as IContactBalance);\n return of({ ...found });\n }\n\n public getTransfers(\n spaceID: string,\n contactID?: string,\n ): Observable<IDebtusTransfer[]> {\n // NOTE: GET /api4debtus/user/api4transfers exists but is currently broken\n // server-side (auth bug queries an empty userID). Using fixtures until the\n // backend fix lands. SWAP: this.sneatApiService.get('api4debtus/user/api4transfers', params).\n const all = demoTransfersForSpace(spaceID);\n return of(\n contactID\n ? all.filter((t) => t.counterpartyContactID === contactID)\n : all,\n );\n }\n\n // ===========================================================================\n // REAL endpoints below.\n // ===========================================================================\n\n /** Reads from demo fixtures; unknown ids error (no fabricated receipts). */\n public getTransfer(\n spaceID: string,\n transferID: string,\n ): Observable<IDebtusTransfer> {\n // The live GET transfer endpoint returns a perspective-resolved TransferDto.\n // For the prototype we resolve from fixtures so the receipt screen renders\n // without a live backend; SWAP to the real GET when running against a\n // deployed server:\n // const params = new HttpParams().set('id', transferID);\n // return this.sneatApiService\n // .get<IApiTransferDto>('api4debtus/transfer', params)\n // .pipe(map((dto) => this.mapTransferDto(dto, spaceID)));\n const found = demoTransfersForSpace(spaceID).find(\n (t) => t.id === transferID,\n );\n // Fable refactoring: a transfer that is not in the fixtures (i.e. any\n // REAL transfer just created via POST create-transfer) must be an error,\n // not a fabricated \"Unknown / 0.00 USD / Outstanding\" receipt — that was\n // presenting fiction as a financial record. The create/settle pages now\n // hand the created transfer to the details page via router state, so this\n // path is only hit on cold loads of unknown ids. The old synthesized\n // fallback is kept below (commented out) per the no-delete policy:\n // return of(\n // found ?? {\n // id: transferID,\n // direction: 'lend',\n // amount: { currency: 'USD', value: 0 },\n // counterpartyContactID: '',\n // counterpartyTitle: 'Unknown',\n // created: new Date().toISOString(),\n // isReturn: false,\n // isOutstanding: true,\n // creatorSpaceID: spaceID,\n // },\n // );\n return found\n ? of(found)\n : throwError(\n () =>\n new Error(\n `Transfer \"${transferID}\" was not found (transfer reads are not wired to the live backend yet).`,\n ),\n );\n }\n\n /** REAL: POST /api4debtus/create-transfer (Firebase-authenticated). */\n public createTransfer(\n request: ICreateTransferRequest,\n ): Observable<ICreateTransferResponse> {\n const apiDirection = debtDirectionToApiDirection(request.direction);\n const body = {\n spaceID: request.spaceID,\n direction: apiDirection,\n amount: {\n currency: request.amount.currency,\n value: request.amount.value,\n },\n // For u2c (lend) the counterparty is the recipient (toContactID); for\n // c2u (borrow) the counterparty is the source (fromContactID).\n toContactID: apiDirection === 'u2c' ? request.contactID : undefined,\n fromContactID: apiDirection === 'c2u' ? request.contactID : undefined,\n // The backend CreateTransferRequest accepts both `note` and\n // `counterpartySpaceID` (facade4debtus/transfers_create_transfer_dto.go);\n // omitting them silently discarded the user's typed note and the\n // cross-space marker on a financial write.\n note: request.note,\n counterpartySpaceID: request.counterpartySpaceID || undefined,\n isReturn: request.isReturn ?? false,\n returnToTransferID: request.returnToTransferID,\n dueOn: request.dueOn,\n };\n return this.sneatApiService\n .post<IApiCreateTransferResponse>('api4debtus/create-transfer', body)\n .pipe(\n map((resp) => this.mapCreateResponse(resp, request)),\n );\n }\n\n /** Settle-up = a reverse-direction return transfer (mirrors the bot). */\n public settleUp(\n request: ISettleUpRequest,\n ): Observable<ICreateTransferResponse> {\n // Fable refactoring: the direction now comes from the request — the page\n // that shows the balance derives it via `settleDirectionForBalance` and is\n // the source of truth. Previously it was inferred from DEMO_CONTACT_BALANCES\n // fixtures, so any contact NOT in the fixtures got `'borrow'`\n // unconditionally and settling a debt the user owed recorded the WRONG\n // direction, increasing the imbalance. Old fixture-based inference kept\n // below per the no-delete policy:\n // const contact = DEMO_CONTACT_BALANCES.find(\n // (c) => c.contactID === request.contactID,\n // );\n // const currentValue = contact?.balance[request.amount.currency] ?? 0;\n // const direction = settleDirectionForBalance(currentValue || 1);\n const direction = request.direction;\n return this.createTransfer({\n spaceID: request.spaceID,\n direction,\n amount: request.amount,\n contactID: request.contactID,\n contactTitle: request.contactTitle,\n isReturn: true,\n counterpartySpaceID: request.counterpartySpaceID,\n });\n }\n\n // ----- mapping helpers -----\n\n private mapCreateResponse(\n resp: IApiCreateTransferResponse,\n request: ICreateTransferRequest,\n ): ICreateTransferResponse {\n if (resp.Error) {\n throw new Error(resp.Error);\n }\n const transfer: IDebtusTransfer = resp.Transfer\n ? this.mapTransferDto(resp.Transfer, request.spaceID)\n : {\n // If the backend omits the transfer echo, synthesize from the request\n // so the UI can still navigate to a detail screen.\n id: `pending-${Date.now()}`,\n direction: request.direction,\n amount: request.amount,\n counterpartyContactID: request.contactID,\n counterpartyTitle: request.contactTitle ?? request.contactID,\n note: request.note,\n created: new Date().toISOString(),\n dueOn: request.dueOn,\n isReturn: request.isReturn ?? false,\n isOutstanding: true,\n creatorSpaceID: request.spaceID,\n counterpartySpaceID: request.counterpartySpaceID,\n };\n return {\n transfer,\n userBalance: (resp.UserBalance ?? {}) as ICreateTransferResponse['userBalance'],\n counterpartyBalance: (resp.CounterpartyBalance ??\n {}) as ICreateTransferResponse['counterpartyBalance'],\n };\n }\n\n private mapTransferDto(\n dto: IApiTransferDto,\n spaceID: string,\n ): IDebtusTransfer {\n const counterparty = dto.To ?? dto.From;\n const direction = dto.Direction\n ? apiDirectionToDebtDirection(dto.Direction)\n : 'lend';\n return {\n id: dto.Id,\n direction,\n amount: {\n currency: (dto.Amount?.currency ?? 'USD') as\n | 'USD'\n | 'EUR',\n value: dto.Amount?.value ?? 0,\n },\n counterpartyContactID: counterparty?.ID ?? '',\n counterpartyTitle: counterparty?.Name ?? 'Unknown',\n note: dto.Comment,\n created: dto.Created ?? new Date().toISOString(),\n dueOn: dto.Due,\n isReturn: dto.IsReturn ?? false,\n isOutstanding: dto.IsOutstanding ?? true,\n creatorSpaceID: spaceID,\n };\n }\n}\n","import { Provider } from '@angular/core';\nimport { DEBTUS_SERVICE } from '@sneat/extension-debtus-contract';\nimport { DebtusService } from './services';\n\n// Registers the concrete DebtusService and binds it to the DEBTUS_SERVICE token so\n// consumers depend only on the IDebtusService contract. Wired in at app\n// bootstrap (consumers do not import this factory directly).\nexport function provideDebtus(): Provider[] {\n return [DebtusService, { provide: DEBTUS_SERVICE, useExisting: DebtusService }];\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sneat-extension-debtus.mjs","sources":["../../../../../../libs/extensions/debtus/runtime/src/lib/services/debtus-source-repayment.service.ts","../../../../../../libs/extensions/debtus/runtime/src/lib/services/debtus-source-due-date.service.ts","../../../../../../libs/extensions/debtus/runtime/src/lib/services/debtus.service.ts","../../../../../../libs/extensions/debtus/runtime/src/lib/services/debtus-transfer-due-date.service.ts","../../../../../../libs/extensions/debtus/runtime/src/lib/provide-debtus.ts","../../../../../../libs/extensions/debtus/runtime/src/sneat-extension-debtus.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\nimport { SneatApiService } from '@sneat/api';\nimport {\n type IDebtusSourceRepaymentServiceV1,\n type IRecordDebtusSourceRepaymentV1Request,\n type IRecordDebtusSourceRepaymentV1Response,\n parseRecordDebtusSourceRepaymentV1Request,\n parseRecordDebtusSourceRepaymentV1Response,\n} from '@sneat/extension-debtus-contract';\nimport { Observable, map } from 'rxjs';\n\n@Injectable()\nexport class DebtusSourceRepaymentService implements IDebtusSourceRepaymentServiceV1 {\n private readonly api = inject(SneatApiService);\n\n public recordSourceObligationRepayment(\n request: IRecordDebtusSourceRepaymentV1Request,\n ): Observable<IRecordDebtusSourceRepaymentV1Response> {\n const validatedRequest = parseRecordDebtusSourceRepaymentV1Request(request);\n return this.api\n .post<unknown>('api4debtus/source-obligation-repayment', validatedRequest)\n .pipe(\n map((value) =>\n parseRecordDebtusSourceRepaymentV1Response(value, validatedRequest),\n ),\n );\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport { SneatApiService } from '@sneat/api';\nimport {\n parseDebtusSourceObligationDueDateV1,\n type IDebtusSourceObligationDueDateServiceV1,\n type IDebtusSourceObligationDueDateV1,\n type ISetDebtusSourceObligationDueDateV1Request,\n} from '@sneat/extension-debtus-contract';\nimport { Observable, map } from 'rxjs';\n\n@Injectable()\nexport class DebtusSourceDueDateService implements IDebtusSourceObligationDueDateServiceV1 {\n private readonly api = inject(SneatApiService);\n\n public setSourceObligationDueDate(\n request: ISetDebtusSourceObligationDueDateV1Request,\n ): Observable<IDebtusSourceObligationDueDateV1> {\n return this.api\n .post<unknown>('api4debtus/source-obligation-due-date', request)\n .pipe(map((value) => parseDueDateResult(value, request)));\n }\n}\n\nfunction parseDueDateResult(\n value: unknown,\n request: ISetDebtusSourceObligationDueDateV1Request,\n): IDebtusSourceObligationDueDateV1 {\n const result = parseDebtusSourceObligationDueDateV1(\n value,\n request.source,\n request.lineID,\n );\n if (request.dueDate && result['dueDate'] !== request.dueDate) {\n throw new TypeError('Debtus due-date response changed the requested date');\n }\n if (request.todoListID && result['todoListID'] !== request.todoListID) {\n throw new TypeError('Debtus due-date response changed the selected list');\n }\n return result;\n}\n","import { HttpParams } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { SneatApiService } from '@sneat/api';\nimport {\n IContactBalance,\n ICreateDebtRecordRequest,\n ICreateTransferRequest,\n ICreateTransferResponse,\n IDebtusService,\n IDebtusTransfer,\n ISettleUpRequest,\n apiDirectionToDebtDirection,\n debtDirectionToApiDirection,\n} from '@sneat/extension-debtus-contract';\nimport { Observable, map } from 'rxjs';\n\ninterface IApiContactBalanceDto {\n readonly contactID: string;\n readonly title: string;\n readonly balance: Record<string, number>;\n readonly counterpartySpaceID?: string;\n}\n\ninterface IApiSpaceTransferDto {\n readonly id: string;\n readonly direction: 'u2c' | 'c2u';\n readonly amount: { readonly currency: string; readonly value: number };\n readonly counterpartyContactID: string;\n readonly counterpartyTitle: string;\n readonly note?: string;\n readonly created: string;\n readonly dueOn?: string;\n readonly isReturn: boolean;\n readonly isOutstanding: boolean;\n readonly creatorSpaceID: string;\n readonly counterpartySpaceID?: string;\n}\n\ninterface IApiSpaceTransfersDto {\n readonly transfers: IApiSpaceTransferDto[];\n}\n\ninterface IApiContactDto {\n readonly ID: string;\n readonly UserID?: string;\n readonly Name: string;\n}\n\ninterface IApiCreatedTransferDto {\n readonly Id: string;\n readonly Created: string;\n readonly Amount: { readonly currency: string; readonly value: number };\n readonly IsReturn?: boolean;\n readonly IsOutstanding?: boolean;\n readonly From?: IApiContactDto;\n readonly To?: IApiContactDto;\n readonly Due?: string;\n}\n\ninterface IApiCreateTransferResponse {\n readonly Error?: string;\n readonly Transfer?: IApiCreatedTransferDto;\n readonly UserBalance?: Record<string, number>;\n readonly CounterpartyBalance?: Record<string, number>;\n}\n\n@Injectable()\nexport class DebtusService implements IDebtusService {\n private readonly sneatApiService = inject(SneatApiService);\n\n public createDebtRecord(\n request: ICreateDebtRecordRequest,\n ): Observable<string> {\n return this.sneatApiService.post('debtus/create_debt_record', request);\n }\n\n public getContactBalances(spaceID: string): Observable<IContactBalance[]> {\n const params = new HttpParams().set('spaceID', spaceID);\n return this.sneatApiService\n .get<IApiContactBalanceDto[]>(\n 'api4debtus/space/contact-balances',\n params,\n )\n .pipe(\n map((contacts) =>\n contacts.map((contact) => ({\n contactID: contact.contactID,\n title: contact.title,\n balance: centsBalanceToMajor(contact.balance),\n counterpartySpaceID: contact.counterpartySpaceID,\n })),\n ),\n );\n }\n\n public getContactBalance(\n spaceID: string,\n contactID: string,\n ): Observable<IContactBalance> {\n return this.getContactBalances(spaceID).pipe(\n map((contacts) => contacts.find((c) => c.contactID === contactID)),\n map((contact) => {\n if (!contact) {\n throw new Error(`Debtus contact \"${contactID}\" was not found`);\n }\n return contact;\n }),\n );\n }\n\n public getTransfers(\n spaceID: string,\n contactID?: string,\n ): Observable<IDebtusTransfer[]> {\n let params = new HttpParams().set('spaceID', spaceID);\n if (contactID) {\n params = params.set('contactID', contactID);\n }\n return this.sneatApiService\n .get<IApiSpaceTransfersDto>('api4debtus/space/transfers', params)\n .pipe(map((dto) => dto.transfers.map(mapSpaceTransferDto)));\n }\n\n public getTransfer(\n spaceID: string,\n transferID: string,\n ): Observable<IDebtusTransfer> {\n const params = new HttpParams()\n .set('spaceID', spaceID)\n .set('id', transferID);\n return this.sneatApiService\n .get<IApiSpaceTransferDto>('api4debtus/space/transfer', params)\n .pipe(map(mapSpaceTransferDto));\n }\n\n public createTransfer(\n request: ICreateTransferRequest,\n ): Observable<ICreateTransferResponse> {\n const apiDirection = debtDirectionToApiDirection(request.direction);\n const body = {\n spaceID: request.spaceID,\n direction: apiDirection,\n amount: {\n currency: request.amount.currency,\n value: majorToCents(request.amount.value),\n },\n toContactID: apiDirection === 'u2c' ? request.contactID : undefined,\n fromContactID: apiDirection === 'c2u' ? request.contactID : undefined,\n note: request.note,\n counterpartySpaceID: request.counterpartySpaceID || undefined,\n isReturn: request.isReturn ?? false,\n returnToTransferID: request.returnToTransferID,\n dueOn: request.dueOn,\n };\n return this.sneatApiService\n .post<IApiCreateTransferResponse>('api4debtus/create-transfer', body)\n .pipe(map((resp) => this.mapCreateResponse(resp, request)));\n }\n\n public settleUp(\n request: ISettleUpRequest,\n ): Observable<ICreateTransferResponse> {\n return this.createTransfer({\n spaceID: request.spaceID,\n direction: request.direction,\n amount: request.amount,\n contactID: request.contactID,\n contactTitle: request.contactTitle,\n isReturn: true,\n counterpartySpaceID: request.counterpartySpaceID,\n });\n }\n\n private mapCreateResponse(\n resp: IApiCreateTransferResponse,\n request: ICreateTransferRequest,\n ): ICreateTransferResponse {\n if (resp.Error) {\n throw new Error(resp.Error);\n }\n if (!resp.Transfer) {\n throw new Error('Debtus create-transfer response omitted the transfer');\n }\n const counterparty = resp.Transfer.To ?? resp.Transfer.From;\n if (!counterparty) {\n throw new Error('Debtus create-transfer response omitted the counterparty');\n }\n return {\n transfer: {\n id: resp.Transfer.Id,\n direction: request.direction,\n amount: {\n currency: request.amount.currency,\n value: centsToMajor(resp.Transfer.Amount.value),\n },\n counterpartyContactID: counterparty.ID,\n counterpartyTitle: counterparty.Name,\n note: request.note,\n created: resp.Transfer.Created,\n dueOn: nonZeroDate(resp.Transfer.Due),\n isReturn: resp.Transfer.IsReturn ?? false,\n isOutstanding:\n resp.Transfer.IsOutstanding ?? !(resp.Transfer.IsReturn ?? false),\n creatorSpaceID: request.spaceID,\n counterpartySpaceID: request.counterpartySpaceID,\n },\n userBalance: centsBalanceToMajor(resp.UserBalance ?? {}),\n counterpartyBalance: centsBalanceToMajor(\n resp.CounterpartyBalance ?? {},\n ),\n };\n }\n}\n\nfunction mapSpaceTransferDto(dto: IApiSpaceTransferDto): IDebtusTransfer {\n return {\n ...dto,\n direction: apiDirectionToDebtDirection(dto.direction),\n amount: {\n currency: dto.amount.currency as IDebtusTransfer['amount']['currency'],\n value: centsToMajor(dto.amount.value),\n },\n };\n}\n\nfunction centsBalanceToMajor(\n balance: Record<string, number>,\n): IContactBalance['balance'] {\n return Object.fromEntries(\n Object.entries(balance).map(([currency, cents]) => [\n currency,\n centsToMajor(cents),\n ]),\n ) as IContactBalance['balance'];\n}\n\nfunction majorToCents(value: number): number {\n return Math.round(value * 100);\n}\n\nfunction centsToMajor(value: number): number {\n return value / 100;\n}\n\nfunction nonZeroDate(value?: string): string | undefined {\n return !value || value.startsWith('0001-01-01') ? undefined : value;\n}\n","import { HttpParams } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { SneatApiService } from '@sneat/api';\nimport {\n type IDebtusTransferDueDateServiceV1,\n type IDebtusTransferDueDateV1,\n type IDebtusTransferRepaymentV1,\n type IRecordDebtusTransferRepaymentV1Request,\n type ISetDebtusTransferDueDateV1Request,\n parseDebtusTransferDueDateV1,\n parseDebtusTransferRepaymentV1,\n} from '@sneat/extension-debtus-contract';\nimport { Observable, map } from 'rxjs';\n\n@Injectable()\nexport class DebtusTransferDueDateService implements IDebtusTransferDueDateServiceV1 {\n private readonly api = inject(SneatApiService);\n\n public setTransferDueDate(\n request: ISetDebtusTransferDueDateV1Request,\n ): Observable<IDebtusTransferDueDateV1> {\n return this.api\n .post<unknown>('api4debtus/transfer-due-date', request)\n .pipe(\n map((value) =>\n parseDebtusTransferDueDateV1(\n value,\n request.spaceID,\n request.transferID,\n ),\n ),\n );\n }\n\n public getTransferDueDate(\n spaceID: string,\n transferID: string,\n ): Observable<IDebtusTransferDueDateV1> {\n const params = new HttpParams()\n .set('spaceID', spaceID)\n .set('transferID', transferID);\n return this.api\n .get<unknown>('api4debtus/transfer-due-date-status', params)\n .pipe(\n map((value) =>\n parseDebtusTransferDueDateV1(value, spaceID, transferID),\n ),\n );\n }\n\n public recordTransferRepayment(\n request: IRecordDebtusTransferRepaymentV1Request,\n ): Observable<IDebtusTransferRepaymentV1> {\n return this.api\n .post<unknown>('api4debtus/transfer-repayment', request)\n .pipe(map((value) => parseDebtusTransferRepaymentV1(value, request)));\n }\n}\n","import { Provider } from '@angular/core';\nimport {\n DEBTUS_SERVICE,\n DEBTUS_SOURCE_REPAYMENT_SERVICE_V1,\n DEBTUS_SOURCE_OBLIGATION_DUE_DATE_SERVICE_V1,\n DEBTUS_TRANSFER_DUE_DATE_SERVICE,\n} from '@sneat/extension-debtus-contract';\nimport {\n DebtusService,\n DebtusSourceDueDateService,\n DebtusSourceRepaymentService,\n DebtusTransferDueDateService,\n} from './services';\n\n// Registers the concrete DebtusService and binds it to the DEBTUS_SERVICE token so\n// consumers depend only on the IDebtusService contract. Wired in at app\n// bootstrap (consumers do not import this factory directly).\nexport function provideDebtus(): Provider[] {\n return [\n DebtusService,\n DebtusSourceRepaymentService,\n DebtusSourceDueDateService,\n DebtusTransferDueDateService,\n { provide: DEBTUS_SERVICE, useExisting: DebtusService },\n {\n provide: DEBTUS_SOURCE_REPAYMENT_SERVICE_V1,\n useExisting: DebtusSourceRepaymentService,\n },\n {\n provide: DEBTUS_SOURCE_OBLIGATION_DUE_DATE_SERVICE_V1,\n useExisting: DebtusSourceDueDateService,\n },\n {\n provide: DEBTUS_TRANSFER_DUE_DATE_SERVICE,\n useExisting: DebtusTransferDueDateService,\n },\n ];\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@sneat/extension-debtus",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "peerDependencies": {
5
5
  "@angular/core": ">=22.0.0 <23.0.0",
6
6
  "rxjs": "^7.0.0",
7
7
  "@sneat/api": "^0.27.0",
8
- "@sneat/extension-debtus-contract": "^0.2.0"
8
+ "@sneat/extension-debtus-contract": "^0.2.3"
9
9
  },
10
10
  "dependencies": {
11
11
  "tslib": "^2.3.0"
@@ -1,26 +1,45 @@
1
- import { IDebtusService, ICreateDebtRecordRequest, IContactBalance, IDebtusTransfer, ICreateTransferRequest, ICreateTransferResponse, ISettleUpRequest } from '@sneat/extension-debtus-contract';
1
+ import { IDebtusSourceRepaymentServiceV1, IRecordDebtusSourceRepaymentV1Request, IRecordDebtusSourceRepaymentV1Response, IDebtusSourceObligationDueDateServiceV1, ISetDebtusSourceObligationDueDateV1Request, IDebtusSourceObligationDueDateV1, IDebtusService, ICreateDebtRecordRequest, IContactBalance, IDebtusTransfer, ICreateTransferRequest, ICreateTransferResponse, ISettleUpRequest, IDebtusTransferDueDateServiceV1, ISetDebtusTransferDueDateV1Request, IDebtusTransferDueDateV1, IRecordDebtusTransferRepaymentV1Request, IDebtusTransferRepaymentV1 } from '@sneat/extension-debtus-contract';
2
2
  import { Observable } from 'rxjs';
3
3
  import * as i0 from '@angular/core';
4
4
  import { Provider } from '@angular/core';
5
5
 
6
+ declare class DebtusSourceRepaymentService implements IDebtusSourceRepaymentServiceV1 {
7
+ private readonly api;
8
+ recordSourceObligationRepayment(request: IRecordDebtusSourceRepaymentV1Request): Observable<IRecordDebtusSourceRepaymentV1Response>;
9
+ static ɵfac: i0.ɵɵFactoryDeclaration<DebtusSourceRepaymentService, never>;
10
+ static ɵprov: i0.ɵɵInjectableDeclaration<DebtusSourceRepaymentService>;
11
+ }
12
+
13
+ declare class DebtusSourceDueDateService implements IDebtusSourceObligationDueDateServiceV1 {
14
+ private readonly api;
15
+ setSourceObligationDueDate(request: ISetDebtusSourceObligationDueDateV1Request): Observable<IDebtusSourceObligationDueDateV1>;
16
+ static ɵfac: i0.ɵɵFactoryDeclaration<DebtusSourceDueDateService, never>;
17
+ static ɵprov: i0.ɵɵInjectableDeclaration<DebtusSourceDueDateService>;
18
+ }
19
+
6
20
  declare class DebtusService implements IDebtusService {
7
21
  private readonly sneatApiService;
8
22
  createDebtRecord(request: ICreateDebtRecordRequest): Observable<string>;
9
23
  getContactBalances(spaceID: string): Observable<IContactBalance[]>;
10
24
  getContactBalance(spaceID: string, contactID: string): Observable<IContactBalance>;
11
25
  getTransfers(spaceID: string, contactID?: string): Observable<IDebtusTransfer[]>;
12
- /** Reads from demo fixtures; unknown ids error (no fabricated receipts). */
13
26
  getTransfer(spaceID: string, transferID: string): Observable<IDebtusTransfer>;
14
- /** REAL: POST /api4debtus/create-transfer (Firebase-authenticated). */
15
27
  createTransfer(request: ICreateTransferRequest): Observable<ICreateTransferResponse>;
16
- /** Settle-up = a reverse-direction return transfer (mirrors the bot). */
17
28
  settleUp(request: ISettleUpRequest): Observable<ICreateTransferResponse>;
18
29
  private mapCreateResponse;
19
- private mapTransferDto;
20
30
  static ɵfac: i0.ɵɵFactoryDeclaration<DebtusService, never>;
21
31
  static ɵprov: i0.ɵɵInjectableDeclaration<DebtusService>;
22
32
  }
23
33
 
34
+ declare class DebtusTransferDueDateService implements IDebtusTransferDueDateServiceV1 {
35
+ private readonly api;
36
+ setTransferDueDate(request: ISetDebtusTransferDueDateV1Request): Observable<IDebtusTransferDueDateV1>;
37
+ getTransferDueDate(spaceID: string, transferID: string): Observable<IDebtusTransferDueDateV1>;
38
+ recordTransferRepayment(request: IRecordDebtusTransferRepaymentV1Request): Observable<IDebtusTransferRepaymentV1>;
39
+ static ɵfac: i0.ɵɵFactoryDeclaration<DebtusTransferDueDateService, never>;
40
+ static ɵprov: i0.ɵɵInjectableDeclaration<DebtusTransferDueDateService>;
41
+ }
42
+
24
43
  declare function provideDebtus(): Provider[];
25
44
 
26
- export { DebtusService, provideDebtus };
45
+ export { DebtusService, DebtusSourceDueDateService, DebtusSourceRepaymentService, DebtusTransferDueDateService, provideDebtus };