@autobusal/admin-api-consumers 1.1.0 → 1.2.1
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.
- package/CHANGELOG.md +19 -0
- package/Manage.tsx +10 -0
- package/Receivables.tsx +7 -0
- package/TokenManager.tsx +1 -1
- package/package.json +1 -1
- package/services.ts +38 -16
- package/types.ts +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.1
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **The token panel updates without a reload** - toggle/revoke/regenerate invalidate the consumer they changed. The button also reads "Generate Token" while no token exists. (Audit ADM-04f.)
|
|
8
|
+
|
|
9
|
+
## 1.2.0
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Credit limit on the partner form, running balance on receivables.** A
|
|
14
|
+
Mode 1 partner now sells against a running account (obtapi Payments\
|
|
15
|
+
External\Charge): every sale debits the net they owe, cancellations
|
|
16
|
+
credit it back, and recorded settlements raise it. `credit_limit` is the
|
|
17
|
+
floor - 0 means prepaid (deposit before selling), a positive number means
|
|
18
|
+
postpaid down to -that-much. The receivables table shows the live
|
|
19
|
+
`balance` and `headroom` alongside the statement figures, deliberately
|
|
20
|
+
from two books: when they disagree, something needs investigating.
|
|
21
|
+
|
|
3
22
|
All notable changes to `@autobusal/admin-api-consumers` are documented here.
|
|
4
23
|
This project adheres to [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
5
24
|
and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
package/Manage.tsx
CHANGED
|
@@ -131,6 +131,16 @@ const Manage = ({ url, t }: Props): JSX.Element => {
|
|
|
131
131
|
type: 'select',
|
|
132
132
|
value: data?.user.comissions?.unique ?? 0,
|
|
133
133
|
values: getAllowed(t)
|
|
134
|
+
}, {
|
|
135
|
+
// Claude - 2026-08-22: the floor of the partner's running
|
|
136
|
+
// account. 0 = prepaid (they deposit before they can sell);
|
|
137
|
+
// a positive number = postpaid down to -that-much. "Unlimited"
|
|
138
|
+
// is a big number typed on purpose, never a switch.
|
|
139
|
+
label: t('admin_api_consumers.manage.credit_limit', { ns: 'common' }),
|
|
140
|
+
name: 'credit_limit',
|
|
141
|
+
type: 'text',
|
|
142
|
+
value: data?.credit_limit ?? 0,
|
|
143
|
+
rules: 'required|numeric'
|
|
134
144
|
}, {
|
|
135
145
|
label: t('admin_api_consumers.manage.status', { ns: 'common' }),
|
|
136
146
|
name: 'status',
|
package/Receivables.tsx
CHANGED
|
@@ -50,6 +50,8 @@ const Receivables = ({ url, t }: Props): JSX.Element => {
|
|
|
50
50
|
<th>{ t('admin_api_consumers.receivables.net', { ns: 'common' }) }</th>
|
|
51
51
|
<th>{ t('admin_api_consumers.receivables.settled', { ns: 'common' }) }</th>
|
|
52
52
|
<th>{ t('admin_api_consumers.receivables.outstanding', { ns: 'common' }) }</th>
|
|
53
|
+
<th>{ t('admin_api_consumers.receivables.balance', { ns: 'common' }) }</th>
|
|
54
|
+
<th>{ t('admin_api_consumers.receivables.headroom', { ns: 'common' }) }</th>
|
|
53
55
|
<th />
|
|
54
56
|
</tr>
|
|
55
57
|
</thead>
|
|
@@ -65,6 +67,11 @@ const Receivables = ({ url, t }: Props): JSX.Element => {
|
|
|
65
67
|
<td>{ row.net.toFixed(2) }</td>
|
|
66
68
|
<td>{ row.settled.toFixed(2) }</td>
|
|
67
69
|
<td>{ row.outstanding.toFixed(2) }</td>
|
|
70
|
+
{ /* the running account: negative is what they owe right
|
|
71
|
+
now; headroom is what they can still sell before
|
|
72
|
+
their credit floor refuses them */ }
|
|
73
|
+
<td>{ row.balance.toFixed(2) }</td>
|
|
74
|
+
<td>{ row.headroom.toFixed(2) }</td>
|
|
68
75
|
<td>
|
|
69
76
|
<Link to={ `${ url }/receivables/${ row.agent_id }?from=${ from }&to=${ to }` }>
|
|
70
77
|
{ t('admin_api_consumers.receivables.view', { ns: 'common' }) }
|
package/TokenManager.tsx
CHANGED
|
@@ -78,7 +78,7 @@ const TokenManager = ({ id, hasToken, enabled, t }: Props): JSX.Element => {
|
|
|
78
78
|
subtype="secondary"
|
|
79
79
|
noMargin
|
|
80
80
|
loading={ isPendingRegenerate }
|
|
81
|
-
text={ <><FiRefreshCw /> { t('admin_api_consumers.token.regenerate', { ns: 'common' }) }</> }
|
|
81
|
+
text={ <><FiRefreshCw /> { t(hasToken ? 'admin_api_consumers.token.regenerate' : 'admin_api_consumers.token.generate', { ns: 'common' }) }</> }
|
|
82
82
|
onClick={ onRegenerate }
|
|
83
83
|
/>
|
|
84
84
|
|
package/package.json
CHANGED
package/services.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { UseMutationResult, UseQueryResult, UseSuspenseQueryResult, useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
|
1
|
+
import { UseMutationResult, UseQueryResult, UseSuspenseQueryResult, useMutation, useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
|
|
2
2
|
import { apiClient } from '@autobusal/providers';
|
|
3
3
|
import { PaginationData } from '@autobusal/providers/types/pagination';
|
|
4
4
|
import { TableParamsData } from '@autobusal/providers/types/other';
|
|
@@ -106,8 +106,17 @@ export const useDeleteApiConsumer = (): UseMutationResult<void, Error, number, u
|
|
|
106
106
|
})
|
|
107
107
|
);
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
/*
|
|
110
|
+
* Claude - 2026-08-22 (audit finding ADM-04f): the token panel only showed
|
|
111
|
+
* a toggle/revoke/regenerate's effect after a full page reload - an admin
|
|
112
|
+
* could reasonably believe Revoke had failed. Each mutation now
|
|
113
|
+
* invalidates the consumer it changed, so the panel redraws from the
|
|
114
|
+
* server's answer immediately.
|
|
115
|
+
*/
|
|
116
|
+
export const useToggleApiConsumer = (): UseMutationResult<void, Error, { id: number, api: number }, unknown> => {
|
|
117
|
+
const client = useQueryClient();
|
|
118
|
+
|
|
119
|
+
return useMutation({
|
|
111
120
|
mutationKey: ['admin-api-consumers-toggle'],
|
|
112
121
|
mutationFn: async ({ id, api }: { id: number, api: number }) => (
|
|
113
122
|
await apiClient
|
|
@@ -115,12 +124,17 @@ export const useToggleApiConsumer = (): UseMutationResult<void, Error, { id: num
|
|
|
115
124
|
.then(response => (
|
|
116
125
|
response.data
|
|
117
126
|
))
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
);
|
|
127
|
+
),
|
|
128
|
+
onSuccess: (_, { id }): void => {
|
|
129
|
+
client.invalidateQueries({ queryKey: ['admin-api-consumers-manage', { id }] });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
};
|
|
121
133
|
|
|
122
|
-
export const useRevokeApiConsumerToken = (): UseMutationResult<void, Error, number, unknown> =>
|
|
123
|
-
|
|
134
|
+
export const useRevokeApiConsumerToken = (): UseMutationResult<void, Error, number, unknown> => {
|
|
135
|
+
const client = useQueryClient();
|
|
136
|
+
|
|
137
|
+
return useMutation({
|
|
124
138
|
mutationKey: ['admin-api-consumers-revoke'],
|
|
125
139
|
mutationFn: async (id: number) => (
|
|
126
140
|
await apiClient
|
|
@@ -128,12 +142,17 @@ export const useRevokeApiConsumerToken = (): UseMutationResult<void, Error, numb
|
|
|
128
142
|
.then(response => (
|
|
129
143
|
response.data
|
|
130
144
|
))
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
);
|
|
145
|
+
),
|
|
146
|
+
onSuccess: (_, id): void => {
|
|
147
|
+
client.invalidateQueries({ queryKey: ['admin-api-consumers-manage', { id }] });
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
};
|
|
134
151
|
|
|
135
|
-
export const useRegenerateApiConsumerToken = (): UseMutationResult<{ api_token: string }, Error, number, unknown> =>
|
|
136
|
-
|
|
152
|
+
export const useRegenerateApiConsumerToken = (): UseMutationResult<{ api_token: string }, Error, number, unknown> => {
|
|
153
|
+
const client = useQueryClient();
|
|
154
|
+
|
|
155
|
+
return useMutation({
|
|
137
156
|
mutationKey: ['admin-api-consumers-regenerate'],
|
|
138
157
|
mutationFn: async (id: number) => (
|
|
139
158
|
await apiClient
|
|
@@ -141,9 +160,12 @@ export const useRegenerateApiConsumerToken = (): UseMutationResult<{ api_token:
|
|
|
141
160
|
.then(response => (
|
|
142
161
|
response.data
|
|
143
162
|
))
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
);
|
|
163
|
+
),
|
|
164
|
+
onSuccess: (_, id): void => {
|
|
165
|
+
client.invalidateQueries({ queryKey: ['admin-api-consumers-manage', { id }] });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
};
|
|
147
169
|
|
|
148
170
|
// Edited: Ferjolt Ozuni - Date: 2026-07-27
|
|
149
171
|
// Package 3 - API partner receivables reports + settlements
|
package/types.ts
CHANGED
|
@@ -6,6 +6,10 @@ export interface ApiConsumerData {
|
|
|
6
6
|
operators: (number | string)[]
|
|
7
7
|
external_providers: (number | string)[]
|
|
8
8
|
is_api_consumer: boolean
|
|
9
|
+
// Claude - 2026-08-22: the running account and its floor - see
|
|
10
|
+
// ReceivableData below for what they mean
|
|
11
|
+
funds?: number
|
|
12
|
+
credit_limit?: number
|
|
9
13
|
user: {
|
|
10
14
|
id: number
|
|
11
15
|
email: string
|
|
@@ -31,6 +35,13 @@ export interface ReceivableData {
|
|
|
31
35
|
net: number
|
|
32
36
|
settled: number
|
|
33
37
|
outstanding: number
|
|
38
|
+
// Claude - 2026-08-22: the LIVE running account (debited per sale,
|
|
39
|
+
// credited by settlements) and its floor - alongside the statement
|
|
40
|
+
// figures, which describe the same debt from the frozen columns. When
|
|
41
|
+
// balance and -outstanding disagree, something needs investigating.
|
|
42
|
+
balance: number
|
|
43
|
+
credit_limit: number
|
|
44
|
+
headroom: number
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
export interface ReceivableOrderData {
|