This commit is contained in:
2026-08-07 14:34:25 +05:30
parent 829e5a8188
commit 0988d39d8b
19 changed files with 850 additions and 932 deletions

View File

@@ -0,0 +1,41 @@
/// Where the back office lives, and the fixed parts of a request to it.
///
/// Kept apart from [SyncConfig] on purpose. That one describes how *this
/// terminal* was configured — which broker, which store, which credentials —
/// and can be re-pointed from Settings without a rebuild. This one is the
/// deployment's own address, needed before anyone has signed in and therefore
/// before there is a configuration to read.
class ApiConfig {
const ApiConfig._();
/// Root of the POS API. Every other path below hangs off it.
///
/// The same base the catalogue and order endpoints already use, so pointing
/// a build at staging is one edit rather than three.
static const String baseUrl = 'https://fiesta.nearle.app/live/api/v1/pos';
/// `POST {baseUrl}{loginPath}`
///
/// ```json
/// { "authname": "…", "password": "…", "device_id": "…", "configid": 1 }
/// ```
static const String loginPath = '/login';
/// Which configuration profile the back office should answer with. Fixed for
/// this build; the server rejects a value it does not recognise.
static const int configId = 1;
/// Sign-in is the one call a person is watching, so it fails faster than the
/// catalogue pull does — thirty seconds of a spinner at the start of a shift
/// reads as a hung terminal.
static const Duration timeout = Duration(seconds: 25);
/// Whether the built-in demo accounts still work when the back office cannot
/// be reached at all.
///
/// Set false for a real deployment. It exists so the app can be run against
/// no server during development; it deliberately does **not** trigger on a
/// rejected password, only on a network fault, so a wrong password never
/// silently falls through to a local account.
static const bool allowOfflineDemoLogin = true;
}

View File

@@ -35,7 +35,6 @@ class SyncConfig {
this.password,
this.httpBaseUrl = '',
this.apiKey,
this.sessionToken,
this.ackTimeout = const Duration(seconds: 20),
this.batchSize = 50,
});
@@ -53,38 +52,8 @@ class SyncConfig {
final String? password;
final String httpBaseUrl;
/// A static key shared by every terminal at a deployment, if one is set.
///
/// Predates sign-in and says nothing about *who* is at the till, so it cannot
/// scope a request to an outlet. Kept for deployments that put one in front
/// of the endpoint.
final String? apiKey;
/// The signed session from `POST /login`, held for the trading day.
///
/// Distinct from [apiKey] because the two answer different questions. The key
/// says "this request came from our fleet"; the session says "this request
/// came from Selvapuram, signed in as Ragul, and may touch that outlet and no
/// other". Only the second can stop a till reaching another tenant's books,
/// which is why it takes precedence when both are present.
final String? sessionToken;
/// What goes in the Authorization header.
///
/// One accessor rather than the same `??` repeated at each call site, because
/// the request that forgot it would be the one silently sending no
/// credentials at all.
String? get bearerToken {
final session = sessionToken?.trim();
if (session != null && session.isNotEmpty) return session;
final key = apiKey?.trim();
if (key != null && key.isNotEmpty) return key;
return null;
}
/// How long to wait for the back office to confirm a batch before treating
/// the outcome as unknown and leaving every row pending.
///
@@ -179,7 +148,6 @@ class SyncConfig {
String? password,
String? httpBaseUrl,
String? apiKey,
String? sessionToken,
Duration? ackTimeout,
int? batchSize,
}) =>
@@ -194,7 +162,6 @@ class SyncConfig {
password: password ?? this.password,
httpBaseUrl: httpBaseUrl ?? this.httpBaseUrl,
apiKey: apiKey ?? this.apiKey,
sessionToken: sessionToken ?? this.sessionToken,
ackTimeout: ackTimeout ?? this.ackTimeout,
batchSize: batchSize ?? this.batchSize,
);