@sincpro/mobile 0.4.4 → 1.0.0
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/README.md +3 -3
- package/dist/adapters/JsonSerializer.adapter.d.ts +1 -1
- package/dist/adapters/JsonSerializer.adapter.js +2 -2
- package/dist/adapters/repositories/database_table.repository.d.ts +3 -2
- package/dist/adapters/repositories/database_table.repository.js +1 -1
- package/dist/adapters/repositories/document.repository.d.ts +81 -0
- package/dist/adapters/repositories/document.repository.js +653 -0
- package/dist/adapters/repositories/domain_event.repository.d.ts +17 -17
- package/dist/adapters/repositories/domain_event.repository.js +25 -31
- package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +10 -10
- package/dist/adapters/repositories/domain_event_dead_letter.repository.js +14 -13
- package/dist/adapters/repositories/event_row.d.ts +13 -0
- package/dist/adapters/repositories/event_row.js +22 -0
- package/dist/adapters/repositories/sqlite_document_store.d.ts +33 -0
- package/dist/adapters/repositories/sqlite_document_store.js +201 -0
- package/dist/domain/connectivity/events.d.ts +5 -5
- package/dist/domain/connectivity/events.js +3 -3
- package/dist/domain/database/criteria.d.ts +19 -0
- package/dist/domain/database/criteria.js +36 -0
- package/dist/domain/database/criteria_clock.d.ts +8 -0
- package/dist/domain/database/criteria_clock.js +305 -0
- package/dist/domain/database/criteria_sql.d.ts +61 -0
- package/dist/domain/database/criteria_sql.js +476 -0
- package/dist/domain/database/database.d.ts +1 -0
- package/dist/domain/database/index.d.ts +3 -1
- package/dist/domain/database/index.js +3 -1
- package/dist/domain/database/migration_plan.d.ts +14 -0
- package/dist/domain/database/migration_plan.js +44 -0
- package/dist/domain/entity/change_tracking.d.ts +21 -0
- package/dist/domain/entity/change_tracking.js +71 -0
- package/dist/domain/entity/checks.d.ts +8 -0
- package/dist/domain/entity/checks.js +82 -0
- package/dist/domain/entity/entity.d.ts +39 -32
- package/dist/domain/entity/entity.js +94 -105
- package/dist/domain/entity/entity_collection.d.ts +15 -30
- package/dist/domain/entity/entity_collection.js +30 -121
- package/dist/domain/entity/index.d.ts +5 -0
- package/dist/domain/entity/index.js +5 -0
- package/dist/domain/entity/reconcile.d.ts +7 -0
- package/dist/domain/entity/reconcile.js +12 -0
- package/dist/domain/entity/relations.d.ts +27 -0
- package/dist/domain/entity/relations.js +69 -0
- package/dist/domain/entity/remote_sync.d.ts +4 -0
- package/dist/domain/entity/remote_sync.js +19 -0
- package/dist/domain/entity/values.d.ts +6 -0
- package/dist/domain/entity/values.js +13 -0
- package/dist/domain/events/catalog.d.ts +29 -0
- package/dist/domain/{events.js → events/catalog.js} +7 -11
- package/dist/domain/events/chain.d.ts +5 -0
- package/dist/domain/events/chain.js +6 -0
- package/dist/domain/{event_sourcing → events}/domain_event.d.ts +20 -22
- package/dist/domain/events/domain_event.js +227 -0
- package/dist/domain/events/index.d.ts +8 -0
- package/dist/domain/events/index.js +8 -0
- package/dist/domain/events/integration_event.d.ts +103 -0
- package/dist/domain/events/integration_event.js +72 -0
- package/dist/domain/events/label.d.ts +2 -0
- package/dist/domain/events/label.js +26 -0
- package/dist/domain/index.d.ts +0 -1
- package/dist/domain/index.js +0 -1
- package/dist/domain/print/events.d.ts +8 -4
- package/dist/domain/print/events.js +9 -4
- package/dist/domain/repositories/document_store.d.ts +33 -0
- package/dist/domain/repositories/document_store.js +5 -0
- package/dist/domain/repositories/hooks.d.ts +23 -0
- package/dist/domain/repositories/hooks.js +32 -0
- package/dist/domain/repositories/index.d.ts +4 -0
- package/dist/domain/repositories/index.js +4 -0
- package/dist/domain/{database → repositories}/repository.d.ts +9 -3
- package/dist/domain/settings.d.ts +4 -1
- package/dist/domain/settings.js +3 -0
- package/dist/domain/webview/events.d.ts +2 -2
- package/dist/domain/webview/events.js +2 -2
- package/dist/entrypoints/db/migrations.js +10 -10
- package/dist/entrypoints/queue/QueueProcessor.d.ts +1 -1
- package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +2 -2
- package/dist/entrypoints/queue/activateDomain.subscriber.js +2 -2
- package/dist/entrypoints/queue/newAppSettings.handler.d.ts +2 -2
- package/dist/entrypoints/queue/newAppSettings.handler.js +1 -1
- package/dist/entrypoints/queue/printImage.subscriber.d.ts +1 -1
- package/dist/entrypoints/queue/printImage.subscriber.js +2 -2
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +1 -1
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +1 -1
- package/dist/entrypoints/ui/AppShell.js +2 -2
- package/dist/entrypoints/ui/common_provider.d.ts +0 -12
- package/dist/entrypoints/ui/common_provider.js +2 -131
- package/dist/event_driven/index.d.ts +1 -0
- package/dist/event_driven/index.js +1 -0
- package/dist/{domain/event_sourcing/event_handler.d.ts → event_driven/subscriber.d.ts} +1 -1
- package/dist/exceptions.d.ts +21 -0
- package/dist/exceptions.js +30 -0
- package/dist/framework/base_module.d.ts +1 -1
- package/dist/framework/createApp.d.ts +3 -3
- package/dist/framework/domain_module.d.ts +1 -1
- package/dist/framework/kernel.d.ts +1 -1
- package/dist/framework/kernel.js +17 -8
- package/dist/infrastructure/database/connector.d.ts +2 -0
- package/dist/infrastructure/database/connector.js +22 -0
- package/dist/infrastructure/database/index.d.ts +1 -0
- package/dist/infrastructure/database/index.js +1 -0
- package/dist/infrastructure/database/schema.d.ts +9 -0
- package/dist/infrastructure/database/schema.js +61 -0
- package/dist/infrastructure/database/utils.d.ts +2 -0
- package/dist/infrastructure/database/utils.js +12 -4
- package/dist/infrastructure/event_chain.d.ts +6 -0
- package/dist/infrastructure/event_chain.js +25 -0
- package/dist/infrastructure/telemetry/tracing/tracing_hooks.js +8 -5
- package/dist/infrastructure/ui/UIEventBus.d.ts +3 -1
- package/dist/infrastructure/ui/UIEventBus.js +8 -1
- package/dist/infrastructure/ui/activity.d.ts +37 -0
- package/dist/infrastructure/ui/activity.js +84 -0
- package/dist/infrastructure/workers/CronWorker.d.ts +6 -4
- package/dist/infrastructure/workers/CronWorker.js +24 -18
- package/dist/infrastructure/workers/EventBus.d.ts +9 -5
- package/dist/infrastructure/workers/EventBus.js +68 -33
- package/dist/services/bluetooth.service.js +16 -14
- package/dist/services/dead_letter_queue.service.d.ts +7 -7
- package/dist/services/dead_letter_queue.service.js +0 -2
- package/dist/services/event.service.d.ts +3 -3
- package/dist/services/event.service.js +1 -1
- package/dist/services/network.service.d.ts +1 -1
- package/dist/services/network.service.js +17 -15
- package/dist/services/printer.service.d.ts +1 -1
- package/dist/services/printer.service.js +50 -44
- package/dist/tools/utils/date.js +4 -3
- package/dist/tools/utils/monetary.d.ts +6 -3
- package/dist/tools/utils/monetary.js +33 -21
- package/dist/tools/utils/serializer.d.ts +1 -1
- package/dist/tools/utils/serializer.js +32 -35
- package/dist/ui/activity/DeviceNotices.d.ts +1 -0
- package/dist/ui/activity/DeviceNotices.js +29 -0
- package/dist/ui/activity/ProcessToast.d.ts +2 -0
- package/dist/ui/activity/ProcessToast.js +71 -0
- package/dist/ui/activity/index.d.ts +4 -0
- package/dist/ui/activity/index.js +4 -0
- package/dist/ui/activity/useActivity.d.ts +9 -0
- package/dist/ui/activity/useActivity.js +48 -0
- package/dist/ui/components/molecules/EventTimelineItem.d.ts +2 -2
- package/dist/ui/components/molecules/EventTimelineItem.js +1 -1
- package/dist/ui/components/molecules/index.d.ts +1 -2
- package/dist/ui/components/molecules/index.js +1 -2
- package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +3 -3
- package/dist/ui/components/organisms/EventRow.d.ts +3 -3
- package/dist/ui/components/organisms/EventRow.js +1 -1
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +5 -5
- package/dist/ui/screens/events/events.context.d.ts +4 -4
- package/package.json +13 -8
- package/dist/domain/event_sourcing/domain_event.js +0 -164
- package/dist/domain/event_sourcing/event.d.ts +0 -25
- package/dist/domain/event_sourcing/event.js +0 -25
- package/dist/domain/event_sourcing/index.d.ts +0 -2
- package/dist/domain/event_sourcing/index.js +0 -2
- package/dist/domain/events.d.ts +0 -33
- package/dist/infrastructure/ui/ToastHost.d.ts +0 -6
- package/dist/infrastructure/ui/ToastHost.js +0 -28
- package/dist/infrastructure/ui/events.d.ts +0 -1
- package/dist/infrastructure/ui/events.js +0 -1
- package/dist/ui/components/molecules/ProcessToast.d.ts +0 -8
- package/dist/ui/components/molecules/ProcessToast.js +0 -52
- /package/dist/domain/{repositories.d.ts → repositories/catalog.d.ts} +0 -0
- /package/dist/domain/{repositories.js → repositories/catalog.js} +0 -0
- /package/dist/domain/{database → repositories}/repository.js +0 -0
- /package/dist/{domain/event_sourcing/event_handler.js → event_driven/subscriber.js} +0 -0
- /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.d.ts +0 -0
- /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.js +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { DomainEventRepository } from "../../adapters/repositories/domain_event.repository";
|
|
2
2
|
import { DomainEventDeadLetterRepository } from "../../adapters/repositories/domain_event_dead_letter.repository";
|
|
3
|
-
import { InternetIsDownEvent, InternetIsUpEvent
|
|
4
|
-
import { DomainNetworkError } from "../../exceptions";
|
|
3
|
+
import { InternetIsDownEvent, InternetIsUpEvent } from "../../domain/events";
|
|
4
|
+
import { DomainNetworkError, RepeatableFailure } from "../../exceptions";
|
|
5
|
+
import { runWithChain } from "../../infrastructure/event_chain";
|
|
5
6
|
import { loggerQueueProcessor } from "../../infrastructure/logger";
|
|
7
|
+
import { declaresUi, publishActivity } from "../../infrastructure/ui/activity";
|
|
6
8
|
import { UIEventBus } from "../../infrastructure/ui/UIEventBus";
|
|
7
9
|
export const PROCESS_WORKER_MAX_ATTEMPTS = 1;
|
|
8
10
|
export class EventBus {
|
|
@@ -12,11 +14,15 @@ export class EventBus {
|
|
|
12
14
|
static BACKOFF_MULTIPLIER = 1.5;
|
|
13
15
|
static subscribers = new Map();
|
|
14
16
|
static isDraining = false;
|
|
17
|
+
static connectivityReady = false;
|
|
15
18
|
static intervalId = null;
|
|
16
19
|
static internetConnected = true;
|
|
17
20
|
static consecutiveFailures = 0;
|
|
18
21
|
static currentInterval = EventBus.INTERVAL_MS;
|
|
19
22
|
static initConnectivityListeners() {
|
|
23
|
+
if (this.connectivityReady)
|
|
24
|
+
return;
|
|
25
|
+
this.connectivityReady = true;
|
|
20
26
|
UIEventBus.on(InternetIsDownEvent.name, () => {
|
|
21
27
|
this.internetConnected = false;
|
|
22
28
|
this.consecutiveFailures++;
|
|
@@ -102,27 +108,22 @@ export class EventBus {
|
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
/**
|
|
105
|
-
*
|
|
111
|
+
* Logs the start and publishes a running activity when a subscriber exists.
|
|
106
112
|
* Returns false if no subscribers (caller should return early).
|
|
107
113
|
*/
|
|
108
114
|
static preProcess(event) {
|
|
109
115
|
const hasSubscribers = this.subscribers.has(event.name);
|
|
110
116
|
loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - STARTED`);
|
|
111
117
|
loggerQueueProcessor.debug(`EVENT=${event.name} uuid=${event.uuid} payload=${event.asJSON()}`);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
event: event.name,
|
|
115
|
-
label: event.label,
|
|
116
|
-
attempts: event.attempts,
|
|
117
|
-
attemptLimit: EventBus.MAX_ATTEMPTS,
|
|
118
|
-
});
|
|
118
|
+
if (hasSubscribers)
|
|
119
|
+
this.publishQueue(event, "running");
|
|
119
120
|
if (!hasSubscribers) {
|
|
120
121
|
loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] - No subscribers registered`);
|
|
121
122
|
}
|
|
122
123
|
return hasSubscribers;
|
|
123
124
|
}
|
|
124
125
|
/**
|
|
125
|
-
* Handles persistence, emits event
|
|
126
|
+
* Handles persistence, emits the event for screens, publishes the activity, logs result.
|
|
126
127
|
* If errors is empty -> success, otherwise -> failure + dead letter + throws.
|
|
127
128
|
* @throws Error if there are any errors
|
|
128
129
|
*/
|
|
@@ -141,14 +142,7 @@ export class EventBus {
|
|
|
141
142
|
loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - FAILED: ${errorMessage}`);
|
|
142
143
|
}
|
|
143
144
|
UIEventBus.emit(event.name, event);
|
|
144
|
-
|
|
145
|
-
event: event.name,
|
|
146
|
-
label: event.label,
|
|
147
|
-
success,
|
|
148
|
-
attempts: event.attempts,
|
|
149
|
-
attemptLimit: EventBus.MAX_ATTEMPTS,
|
|
150
|
-
error: errorMessage,
|
|
151
|
-
});
|
|
145
|
+
this.publishQueue(event, success ? "succeeded" : "failed", errorMessage);
|
|
152
146
|
if (!success) {
|
|
153
147
|
throw new Error(errorMessage);
|
|
154
148
|
}
|
|
@@ -162,12 +156,15 @@ export class EventBus {
|
|
|
162
156
|
}
|
|
163
157
|
catch (err) {
|
|
164
158
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
165
|
-
errors.push(errorMessage);
|
|
166
159
|
loggerQueueProcessor.warn(`EVENT=${event.name} - Subscriber failed: ${errorMessage}`);
|
|
167
|
-
if (err instanceof DomainNetworkError) {
|
|
168
|
-
|
|
169
|
-
|
|
160
|
+
if (err instanceof DomainNetworkError || err instanceof RepeatableFailure) {
|
|
161
|
+
if (err instanceof DomainNetworkError) {
|
|
162
|
+
this.internetConnected = false;
|
|
163
|
+
UIEventBus.emit(InternetIsDownEvent.name);
|
|
164
|
+
}
|
|
165
|
+
throw new RepeatableFailure(errorMessage);
|
|
170
166
|
}
|
|
167
|
+
errors.push(errorMessage);
|
|
171
168
|
}
|
|
172
169
|
}
|
|
173
170
|
return errors;
|
|
@@ -220,7 +217,12 @@ export class EventBus {
|
|
|
220
217
|
/**
|
|
221
218
|
* Publishes a DomainEvent asynchronously - enqueues for later processing.
|
|
222
219
|
*/
|
|
220
|
+
static schedule() {
|
|
221
|
+
this.triggerProcessing();
|
|
222
|
+
}
|
|
223
223
|
static async publish(event) {
|
|
224
|
+
if (!event.correlationId)
|
|
225
|
+
event.applyChain(event.uuid);
|
|
224
226
|
loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published ASYNC`);
|
|
225
227
|
await DomainEventRepository.save(event);
|
|
226
228
|
this.triggerProcessing();
|
|
@@ -231,6 +233,8 @@ export class EventBus {
|
|
|
231
233
|
* @throws Error if any subscriber fails or no subscribers registered
|
|
232
234
|
*/
|
|
233
235
|
static async publishSync(event) {
|
|
236
|
+
if (!event.correlationId)
|
|
237
|
+
event.applyChain(event.uuid);
|
|
234
238
|
loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published SYNC`);
|
|
235
239
|
event.markAsProcessing();
|
|
236
240
|
await DomainEventRepository.save(event);
|
|
@@ -239,8 +243,18 @@ export class EventBus {
|
|
|
239
243
|
return;
|
|
240
244
|
}
|
|
241
245
|
const subscriberList = this.subscribers.get(event.name);
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
try {
|
|
247
|
+
const errors = await this.executeSubscribers(event, subscriberList);
|
|
248
|
+
await this.postProcess(event, errors);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
if (err instanceof RepeatableFailure) {
|
|
252
|
+
event.retry();
|
|
253
|
+
await DomainEventRepository.save(event);
|
|
254
|
+
this.publishQueue(event, "idle");
|
|
255
|
+
}
|
|
256
|
+
throw err;
|
|
257
|
+
}
|
|
244
258
|
}
|
|
245
259
|
/**
|
|
246
260
|
* Processes all pending DomainEvents from the domain_events table.
|
|
@@ -250,18 +264,29 @@ export class EventBus {
|
|
|
250
264
|
static async drainAll() {
|
|
251
265
|
let event;
|
|
252
266
|
while ((event = await DomainEventRepository.findNextPending(this.internetConnected))) {
|
|
267
|
+
const current = event;
|
|
253
268
|
try {
|
|
254
|
-
|
|
255
|
-
await DomainEventRepository.save(
|
|
256
|
-
if (!this.preProcess(
|
|
257
|
-
await this.postProcess(
|
|
269
|
+
current.markAsProcessing();
|
|
270
|
+
await DomainEventRepository.save(current);
|
|
271
|
+
if (!this.preProcess(current)) {
|
|
272
|
+
await this.postProcess(current, ["No subscribers registered"]);
|
|
258
273
|
continue;
|
|
259
274
|
}
|
|
260
|
-
const subscriberList = this.subscribers.get(
|
|
261
|
-
const errors = await
|
|
262
|
-
|
|
275
|
+
const subscriberList = this.subscribers.get(current.name);
|
|
276
|
+
const errors = await runWithChain({
|
|
277
|
+
causationId: current.uuid,
|
|
278
|
+
correlationId: current.correlationId ?? current.uuid,
|
|
279
|
+
}, () => this.executeSubscribers(current, subscriberList));
|
|
280
|
+
await this.postProcess(current, errors);
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
if (err instanceof RepeatableFailure) {
|
|
284
|
+
current.retry();
|
|
285
|
+
await DomainEventRepository.save(current);
|
|
286
|
+
this.publishQueue(current, "idle");
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
263
289
|
}
|
|
264
|
-
catch { }
|
|
265
290
|
}
|
|
266
291
|
}
|
|
267
292
|
/**
|
|
@@ -276,4 +301,14 @@ export class EventBus {
|
|
|
276
301
|
loggerQueueProcessor.warn("Failed to clear ProcessWorker queue:", error);
|
|
277
302
|
}
|
|
278
303
|
}
|
|
304
|
+
static publishQueue(event, status, detail) {
|
|
305
|
+
publishActivity({
|
|
306
|
+
channel: "queue",
|
|
307
|
+
name: event.name,
|
|
308
|
+
label: event.labelText(),
|
|
309
|
+
detail,
|
|
310
|
+
status,
|
|
311
|
+
ui: declaresUi(event),
|
|
312
|
+
});
|
|
313
|
+
}
|
|
279
314
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BluetoothAdapter } from "../adapters/Bluetooth.adapter";
|
|
2
2
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
3
|
-
import {
|
|
4
|
-
import { UIEventBus } from "../infrastructure/ui/UIEventBus";
|
|
3
|
+
import { notifyDevice } from "../infrastructure/ui/activity";
|
|
5
4
|
class BluetoothService {
|
|
6
5
|
permissionStatus = null;
|
|
7
6
|
async requestPermissions() {
|
|
@@ -36,10 +35,11 @@ class BluetoothService {
|
|
|
36
35
|
loggerUseCases.info("Ensuring Bluetooth permissions for printer connection");
|
|
37
36
|
const permissions = await this.ensurePermissions();
|
|
38
37
|
if (!permissions) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
notifyDevice({
|
|
39
|
+
name: "bluetooth.required",
|
|
40
|
+
title: "Permisos de Bluetooth requeridos",
|
|
41
|
+
message: "Habilita los permisos de Bluetooth en configuración",
|
|
42
|
+
variant: "danger",
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
return permissions;
|
|
@@ -52,18 +52,20 @@ class BluetoothService {
|
|
|
52
52
|
}
|
|
53
53
|
showPermissionToast(permissions) {
|
|
54
54
|
if (permissions.isGranted) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
notifyDevice({
|
|
56
|
+
name: "bluetooth.enabled",
|
|
57
|
+
title: "Bluetooth habilitado",
|
|
58
|
+
message: "Permisos de Bluetooth concedidos",
|
|
59
|
+
variant: "success",
|
|
59
60
|
});
|
|
60
61
|
loggerUseCases.info("Bluetooth permissions granted");
|
|
61
62
|
}
|
|
62
63
|
else {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
notifyDevice({
|
|
65
|
+
name: "bluetooth.denied",
|
|
66
|
+
title: "Bluetooth no disponible",
|
|
67
|
+
message: "Los permisos de Bluetooth fueron denegados",
|
|
68
|
+
variant: "danger",
|
|
67
69
|
});
|
|
68
70
|
loggerUseCases.warn("Bluetooth permissions denied", { permissions });
|
|
69
71
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IntegrationEvent } from "../domain/events";
|
|
2
2
|
declare class DeadLetterQueueUseCases {
|
|
3
3
|
private get repository();
|
|
4
4
|
/**
|
|
5
5
|
* Retrieves all failed events from the dead letter queue.
|
|
6
6
|
*/
|
|
7
|
-
getFailedEvents(): Promise<
|
|
7
|
+
getFailedEvents(): Promise<IntegrationEvent[]>;
|
|
8
8
|
/**
|
|
9
9
|
* Retrieves a specific failed event by uuid.
|
|
10
10
|
*/
|
|
11
|
-
getFailedEventById(uuid: string): Promise<
|
|
11
|
+
getFailedEventById(uuid: string): Promise<IntegrationEvent | null>;
|
|
12
12
|
/**
|
|
13
13
|
* Manually retries a failed event by re-queuing it for processing.
|
|
14
14
|
* This removes the event from the dead letter queue and adds it back to the processing queue.
|
|
15
15
|
*/
|
|
16
|
-
retryFailedEvent(event:
|
|
16
|
+
retryFailedEvent(event: IntegrationEvent): Promise<void>;
|
|
17
17
|
/**
|
|
18
18
|
* Retries multiple failed events in batch.
|
|
19
19
|
*/
|
|
20
|
-
retryMultipleFailedEvents(events:
|
|
20
|
+
retryMultipleFailedEvents(events: IntegrationEvent[]): Promise<{
|
|
21
21
|
success: number;
|
|
22
22
|
failed: number;
|
|
23
23
|
}>;
|
|
@@ -25,11 +25,11 @@ declare class DeadLetterQueueUseCases {
|
|
|
25
25
|
* Permanently deletes a failed event from the dead letter queue.
|
|
26
26
|
* Use with caution as this action cannot be undone.
|
|
27
27
|
*/
|
|
28
|
-
deleteFailedEvent(event:
|
|
28
|
+
deleteFailedEvent(event: IntegrationEvent): Promise<void>;
|
|
29
29
|
/**
|
|
30
30
|
* Deletes multiple failed events in batch.
|
|
31
31
|
*/
|
|
32
|
-
deleteMultipleFailedEvents(events:
|
|
32
|
+
deleteMultipleFailedEvents(events: IntegrationEvent[]): Promise<{
|
|
33
33
|
success: number;
|
|
34
34
|
failed: number;
|
|
35
35
|
}>;
|
|
@@ -27,9 +27,7 @@ class DeadLetterQueueUseCases {
|
|
|
27
27
|
async retryFailedEvent(event) {
|
|
28
28
|
loggerUseCases.info(`Manually retrying failed event: ${event.name} (uuid: ${event.uuid})`);
|
|
29
29
|
try {
|
|
30
|
-
// Reset the event for retry
|
|
31
30
|
event.retry();
|
|
32
|
-
// Re-queue the event using V2 API
|
|
33
31
|
await EventBus.publish(event);
|
|
34
32
|
// Remove from dead letter queue only after successful re-queuing
|
|
35
33
|
await this.repository.remove(event.uuid);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type IntegrationEvent } from "../domain/events";
|
|
2
2
|
declare class EventService {
|
|
3
|
-
listAllEvents(): Promise<
|
|
4
|
-
republishSync(event:
|
|
3
|
+
listAllEvents(): Promise<IntegrationEvent[]>;
|
|
4
|
+
republishSync(event: IntegrationEvent): Promise<void>;
|
|
5
5
|
}
|
|
6
6
|
export declare const eventService: EventService;
|
|
7
7
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DomainEventRepository } from "../adapters/repositories/domain_event.repository";
|
|
2
|
-
import { EEventStatus } from "../domain/
|
|
2
|
+
import { EEventStatus } from "../domain/events";
|
|
3
3
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
4
4
|
import { EventBus } from "../infrastructure/workers/EventBus";
|
|
5
5
|
class EventService {
|
|
@@ -2,6 +2,6 @@ import { NetworkStatus } from "../domain/connectivity";
|
|
|
2
2
|
export declare class NetworkUseCases {
|
|
3
3
|
private networkStatus;
|
|
4
4
|
getNetworkStatus(): Promise<NetworkStatus>;
|
|
5
|
-
|
|
5
|
+
private notifyOnChange;
|
|
6
6
|
}
|
|
7
7
|
export declare const networkUseCases: NetworkUseCases;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NetworkAdapter } from "../adapters/Network.adapter";
|
|
2
2
|
import { InternetIsDownEvent, InternetIsUpEvent } from "../domain/events";
|
|
3
3
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
4
|
-
import {
|
|
4
|
+
import { notifyDevice } from "../infrastructure/ui/activity";
|
|
5
5
|
import { UIEventBus } from "../infrastructure/ui/UIEventBus";
|
|
6
6
|
export class NetworkUseCases {
|
|
7
7
|
networkStatus = null;
|
|
@@ -13,29 +13,31 @@ export class NetworkUseCases {
|
|
|
13
13
|
else {
|
|
14
14
|
UIEventBus.emit(InternetIsDownEvent.name, false);
|
|
15
15
|
}
|
|
16
|
-
this.
|
|
16
|
+
this.notifyOnChange(networkStatus);
|
|
17
17
|
this.networkStatus = networkStatus;
|
|
18
18
|
return this.networkStatus;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
if (!
|
|
20
|
+
notifyOnChange(networkStatus) {
|
|
21
|
+
const changed = networkStatus.isConnected !== this.networkStatus?.isConnected;
|
|
22
|
+
if (!changed) {
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
if (!networkStatus.isConnected) {
|
|
26
|
-
loggerUseCases.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
loggerUseCases.warn(`Network is down: ${networkStatus.type}`);
|
|
27
|
+
notifyDevice({
|
|
28
|
+
name: "network.offline",
|
|
29
|
+
title: "Estas desconectado",
|
|
30
|
+
message: "Sin conexión a internet",
|
|
31
|
+
variant: "danger",
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
else {
|
|
34
|
-
loggerUseCases.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
loggerUseCases.info(`Network is up: ${networkStatus.type}`);
|
|
36
|
+
notifyDevice({
|
|
37
|
+
name: "network.online",
|
|
38
|
+
title: "Conectado",
|
|
39
|
+
message: `Conexión a través de ${networkStatus.type}`,
|
|
40
|
+
variant: "success",
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
}
|
|
@@ -9,7 +9,7 @@ declare class PrinterService {
|
|
|
9
9
|
getPairedDevices(): BluetoothDevice[];
|
|
10
10
|
getPairedPrinters(): PairedPrinter[];
|
|
11
11
|
isConnected(): boolean;
|
|
12
|
-
connect(address: string, name: string): Promise<boolean>;
|
|
12
|
+
connect(address: string, name: string, notify?: boolean): Promise<boolean>;
|
|
13
13
|
disconnect(): Promise<void>;
|
|
14
14
|
getSelectedPrinter(): Promise<ISelectedPrinter | null>;
|
|
15
15
|
saveSelectedPrinter(printer: ISelectedPrinter): Promise<void>;
|
|
@@ -3,8 +3,7 @@ import { SettingsRepository } from "../adapters/repositories/setting.repository"
|
|
|
3
3
|
import { getPrinterDriver, hasPrinterDriver, setPrinterDriver, } from "../domain/print";
|
|
4
4
|
import { ECommonSetting } from "../domain/settings";
|
|
5
5
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
6
|
-
import {
|
|
7
|
-
import { UIEventBus } from "../infrastructure/ui/UIEventBus";
|
|
6
|
+
import { notifyDevice } from "../infrastructure/ui/activity";
|
|
8
7
|
import { File } from "expo-file-system";
|
|
9
8
|
import * as Print from "expo-print";
|
|
10
9
|
import { bluetoothService } from "./bluetooth.service";
|
|
@@ -26,7 +25,7 @@ class PrinterService {
|
|
|
26
25
|
isConnected() {
|
|
27
26
|
return getPrinterDriver().isConnected();
|
|
28
27
|
}
|
|
29
|
-
async connect(address, name) {
|
|
28
|
+
async connect(address, name, notify = true) {
|
|
30
29
|
const hasPermissions = await this.bluetooth.ensurePermissionsForPrinter();
|
|
31
30
|
if (!hasPermissions) {
|
|
32
31
|
return false;
|
|
@@ -39,30 +38,37 @@ class PrinterService {
|
|
|
39
38
|
selectedAt: new Date().toISOString(),
|
|
40
39
|
};
|
|
41
40
|
await this.saveSelectedPrinter(printer);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
if (notify) {
|
|
42
|
+
notifyDevice({
|
|
43
|
+
name: "printer.connected",
|
|
44
|
+
title: "Impresora conectada",
|
|
45
|
+
message: `Conectado a ${name}`,
|
|
46
|
+
variant: "success",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
47
49
|
return true;
|
|
48
50
|
}
|
|
49
51
|
catch (error) {
|
|
50
52
|
loggerUseCases.error(`Failed to connect to printer: ${name}`, error);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
if (notify) {
|
|
54
|
+
notifyDevice({
|
|
55
|
+
name: "printer.connect_failed",
|
|
56
|
+
title: "Error de conexión",
|
|
57
|
+
message: `No se pudo conectar a ${name}`,
|
|
58
|
+
variant: "danger",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
56
61
|
return false;
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
async disconnect() {
|
|
60
65
|
try {
|
|
61
66
|
await getPrinterDriver().disconnect();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
notifyDevice({
|
|
68
|
+
name: "printer.disconnected",
|
|
69
|
+
title: "Desconectado",
|
|
70
|
+
message: "Impresora desconectada",
|
|
71
|
+
variant: "info",
|
|
66
72
|
});
|
|
67
73
|
}
|
|
68
74
|
catch (error) {
|
|
@@ -87,10 +93,11 @@ class PrinterService {
|
|
|
87
93
|
}
|
|
88
94
|
async printTestPage() {
|
|
89
95
|
if (!this.isConnected()) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
notifyDevice({
|
|
97
|
+
name: "printer.not_connected",
|
|
98
|
+
title: "Sin conexión",
|
|
99
|
+
message: "Conecta una impresora primero",
|
|
100
|
+
variant: "danger",
|
|
94
101
|
});
|
|
95
102
|
return false;
|
|
96
103
|
}
|
|
@@ -108,19 +115,21 @@ class PrinterService {
|
|
|
108
115
|
alignment: "center",
|
|
109
116
|
fontSize: "small",
|
|
110
117
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
notifyDevice({
|
|
119
|
+
name: "printer.test_ok",
|
|
120
|
+
title: "Impresión exitosa",
|
|
121
|
+
message: "Página de prueba impresa",
|
|
122
|
+
variant: "success",
|
|
115
123
|
});
|
|
116
124
|
return true;
|
|
117
125
|
}
|
|
118
126
|
catch (error) {
|
|
119
127
|
loggerUseCases.error("Error printing test page", error);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
notifyDevice({
|
|
129
|
+
name: "printer.test_failed",
|
|
130
|
+
title: "Error de impresión",
|
|
131
|
+
message: "No se pudo imprimir la página de prueba",
|
|
132
|
+
variant: "danger",
|
|
124
133
|
});
|
|
125
134
|
return false;
|
|
126
135
|
}
|
|
@@ -137,18 +146,13 @@ class PrinterService {
|
|
|
137
146
|
loggerUseCases.warn("Print failed — attempting grace reconnect", firstError);
|
|
138
147
|
const reconnected = await this.forceReconnect();
|
|
139
148
|
if (!reconnected)
|
|
140
|
-
return false;
|
|
149
|
+
return false;
|
|
141
150
|
try {
|
|
142
151
|
await getPrinterDriver().printImageBase64(base64Data);
|
|
143
152
|
return true;
|
|
144
153
|
}
|
|
145
154
|
catch (retryError) {
|
|
146
155
|
loggerUseCases.error("Print retry after reconnect also failed", retryError);
|
|
147
|
-
UIEventBus.emit(UI_NOTIFICATION_EVENT, {
|
|
148
|
-
type: "error",
|
|
149
|
-
text1: "Error de impresión",
|
|
150
|
-
text2: "No se pudo imprimir incluso tras reconectar la impresora",
|
|
151
|
-
});
|
|
152
156
|
return false;
|
|
153
157
|
}
|
|
154
158
|
}
|
|
@@ -164,10 +168,11 @@ class PrinterService {
|
|
|
164
168
|
return false;
|
|
165
169
|
}
|
|
166
170
|
await getPrinterDriver().printImageBase64(imageBase64);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
notifyDevice({
|
|
172
|
+
name: "printer.sent",
|
|
173
|
+
title: "Impresión enviada",
|
|
174
|
+
message: "Documento enviado a la impresora",
|
|
175
|
+
variant: "success",
|
|
171
176
|
});
|
|
172
177
|
return true;
|
|
173
178
|
}
|
|
@@ -233,7 +238,7 @@ class PrinterService {
|
|
|
233
238
|
if (!printer)
|
|
234
239
|
return false;
|
|
235
240
|
loggerUseCases.info(`Grace reconnect: reconnecting to ${printer.name} (${printer.address})`);
|
|
236
|
-
return this.connect(printer.address, printer.name);
|
|
241
|
+
return this.connect(printer.address, printer.name, false);
|
|
237
242
|
}
|
|
238
243
|
async ensureConnected() {
|
|
239
244
|
if (this.isConnected()) {
|
|
@@ -241,10 +246,11 @@ class PrinterService {
|
|
|
241
246
|
}
|
|
242
247
|
const printer = await this.getSelectedPrinter();
|
|
243
248
|
if (!printer) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
249
|
+
notifyDevice({
|
|
250
|
+
name: "printer.missing",
|
|
251
|
+
title: "Sin impresora",
|
|
252
|
+
message: "Selecciona una impresora primero",
|
|
253
|
+
variant: "danger",
|
|
248
254
|
});
|
|
249
255
|
return false;
|
|
250
256
|
}
|
package/dist/tools/utils/date.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { dayOf, isDay } from "@sincpro/client-framework";
|
|
1
2
|
import dayjs from "dayjs";
|
|
2
3
|
import timezone from "dayjs/plugin/timezone";
|
|
3
4
|
import utc from "dayjs/plugin/utc";
|
|
@@ -53,7 +54,7 @@ export function formatDate(input, timezone, options) {
|
|
|
53
54
|
const usedLocale = options?.locale ?? deviceLocale;
|
|
54
55
|
try {
|
|
55
56
|
const rawStr = typeof input === "string" ? input : input.toISOString();
|
|
56
|
-
const isDateOnly =
|
|
57
|
+
const isDateOnly = typeof input === "string" && isDay(input);
|
|
57
58
|
// Auto-detect showTime si no se pasa explicitamente
|
|
58
59
|
const effectiveShowTime = options?.showTime !== undefined
|
|
59
60
|
? options.showTime
|
|
@@ -100,11 +101,11 @@ export function formatDateWithDefaultTimezone(input, options) {
|
|
|
100
101
|
export function getCurrentDateInTimezone(timezone) {
|
|
101
102
|
const effectiveTimezone = timezone || DEFAULT_TIMEZONE;
|
|
102
103
|
try {
|
|
103
|
-
return
|
|
104
|
+
return dayOf(new Date().toISOString(), effectiveTimezone) ?? dayjs().format("YYYY-MM-DD");
|
|
104
105
|
}
|
|
105
106
|
catch (error) {
|
|
106
107
|
console.warn("Error obteniendo fecha actual en timezone:", error);
|
|
107
|
-
return dayjs().format("YYYY-MM-DD");
|
|
108
|
+
return dayjs().format("YYYY-MM-DD");
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
/**
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
1
|
+
import { Decimal, type DecimalLike } from "@sincpro/client-framework";
|
|
2
|
+
export declare function toDecimal(input?: DecimalLike | null): Decimal;
|
|
3
|
+
export declare function parseToMonetaryNumber(input?: DecimalLike | null): Decimal;
|
|
4
|
+
export declare function formatTwoDecimals(value?: DecimalLike | null): string;
|
|
5
|
+
export declare function discountOf(total: DecimalLike, discount: DecimalLike): Decimal;
|
|
6
|
+
export declare function calculateDiscountedTotal(total: DecimalLike, discount: DecimalLike): Decimal;
|