nearle admin agent
This commit is contained in:
31
services/tools/help/assigning-a-partner.md
Normal file
31
services/tools/help/assigning-a-partner.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
question: What does assigning a delivery partner to a merchant do?
|
||||
also:
|
||||
- how does a shop get riders
|
||||
- merchant has no riders to assign
|
||||
- change which partner supplies a shop
|
||||
- what does partnerid zero mean
|
||||
area: platform
|
||||
source: src/api/tenants.ts, src/api/deliveries.ts
|
||||
---
|
||||
A delivery partner is the company that supplies riders. Assigning one to a
|
||||
merchant makes that partner's riders available on the merchant's assign screen,
|
||||
alongside any riders the merchant hired itself.
|
||||
|
||||
One partner routinely serves many merchants — this is not a one-to-one
|
||||
relationship, and reassigning a merchant does not take the partner away from
|
||||
anyone else.
|
||||
|
||||
**Assigning no partner is a real setting, not an empty one.** A merchant with no
|
||||
partner uses its own riders, and that is a supported way to run a shop rather
|
||||
than a half-finished setup. A merchant with neither a partner nor its own riders
|
||||
has nobody to assign deliveries to, and that is what to check first when a shop
|
||||
reports an empty rider list.
|
||||
|
||||
Only Nearle can set this. It is deliberately not something a merchant can edit
|
||||
about themselves, because a merchant who could set it would be able to move
|
||||
themselves under another partner's riders and billing.
|
||||
|
||||
A partner works one district. If a merchant's branches sit in a district the
|
||||
partner does not cover, the partner's riders will not appear there even though
|
||||
the assignment exists.
|
||||
27
services/tools/help/districts.md
Normal file
27
services/tools/help/districts.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
question: What is a district, and what happens when a partner is onboarded in a new one?
|
||||
also:
|
||||
- applocationid
|
||||
- region not in the list
|
||||
- riders not showing in a new city
|
||||
- can I add a district
|
||||
area: platform
|
||||
source: repositories/partnerRepository.go
|
||||
---
|
||||
A district is the delivery region a partner works and a rider is placed in. It
|
||||
is not the same thing as a branch: a merchant has branches, a district covers
|
||||
whichever of them sit inside it.
|
||||
|
||||
Onboarding a partner into a district that is not open yet **opens it**. The
|
||||
district is created along with the operating defaults every rider query needs,
|
||||
copied from a district already running rather than invented. So a partner can be
|
||||
set up in a city Nearle has not traded in before, without a separate step.
|
||||
|
||||
This matters because a district that exists in name but has no operating
|
||||
configuration hides every rider placed in it. Riders can be created, they appear
|
||||
to save, and they are absent from every assign screen. The onboarding path
|
||||
creates both halves together so that state cannot be reached from the console.
|
||||
|
||||
A partner works one district. If a partner's riders are not appearing for a
|
||||
merchant, check that the merchant's branches are in the same district as the
|
||||
partner, before looking at the riders themselves.
|
||||
32
services/tools/help/onboarding-a-branch.md
Normal file
32
services/tools/help/onboarding-a-branch.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
question: What does creating a branch actually create?
|
||||
also:
|
||||
- new outlet cannot sign in
|
||||
- branch login has no password
|
||||
- do I need a user before I add a branch
|
||||
- onboarding a store what happens
|
||||
area: platform
|
||||
source: repositories/tenantRepository.go, src/auth/session.ts
|
||||
---
|
||||
A branch is never created on its own. It arrives with somebody who can run it,
|
||||
and there are two ways to give it one.
|
||||
|
||||
Name an existing person and they are bound to the new outlet. They must already
|
||||
belong to that same merchant and must not be a till account — a userid from
|
||||
another business, or one that does not exist, is refused with the same message,
|
||||
and the branch is not created at all rather than left standing with nobody.
|
||||
|
||||
Give an email instead and a login is spawned from it. That account is named
|
||||
after the shop, sits on the shop's email, and **is created with no password**.
|
||||
That is deliberate, not a fault: the first person to sign in is told the account
|
||||
needs a password and sets one, and only then can they get in.
|
||||
|
||||
So a newly created branch whose operator reports they "cannot sign in" has
|
||||
usually not been broken — they have not been through the password step yet. The
|
||||
account is real and active; it simply has nothing to check a password against
|
||||
until somebody sets one.
|
||||
|
||||
If the branch was created with neither an operator nor an email, it was not
|
||||
created. That combination is refused outright, because an outlet nobody can sign
|
||||
in to still appears in every list and every branch picker, and the first person
|
||||
to notice is whoever is standing in the shop.
|
||||
26
services/tools/help/platform-vs-merchant.md
Normal file
26
services/tools/help/platform-vs-merchant.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
question: Why can I not see a shop's orders or stock from the platform workspace?
|
||||
also:
|
||||
- buddy will not answer about a merchant
|
||||
- nearle admin cannot see sales
|
||||
- how do I check what is stuck for a tenant
|
||||
- platform account no tenant
|
||||
area: platform
|
||||
source: services/tools/registry.go, services/agents/platform.yaml
|
||||
---
|
||||
A Nearle staff account reads across every merchant and belongs to none. It
|
||||
carries no shop, and every tool that reads orders, stock, tills or deliveries
|
||||
needs one — so from the platform workspace those questions have no answer rather
|
||||
than a slow one.
|
||||
|
||||
That is the design, not a missing feature. "Every merchant at once" is not an
|
||||
answer to "what is stuck?", and a total across unrelated businesses would be a
|
||||
number nobody could act on.
|
||||
|
||||
To look at one merchant's operations, work inside that merchant's own console,
|
||||
where the shop is fixed and the figures mean something.
|
||||
|
||||
What can be answered from here is how Nearle itself works: what onboarding a
|
||||
branch creates, what assigning a delivery partner does, how the global catalogue
|
||||
reaches a shop's shelf, and why a till account is not a console login. If an
|
||||
answer would need a specific shop's data, it will say so rather than estimate.
|
||||
@@ -236,3 +236,83 @@ func TestHelpNeedsNoTenant(t *testing.T) {
|
||||
t.Fatal("staff got no answer")
|
||||
}
|
||||
}
|
||||
|
||||
/* ── The platform passages ──────────────────────────────────────────────── */
|
||||
|
||||
// Nearle's own staff, whose questions are about the platform rather than about
|
||||
// a shop.
|
||||
//
|
||||
// These exist because the `platform` agent holds ONE tool — `help` — and can
|
||||
// hold no other: a staff account carries no tenant, so every tool that reads a
|
||||
// shop's data refuses it. The corpus is therefore the entire capability of the
|
||||
// assistant in the Nearle Admin workspace, and a passage that cannot be
|
||||
// retrieved is a question that has no answer at all there.
|
||||
func TestThePlatformQuestionsFindTheirOwnEntry(t *testing.T) {
|
||||
for question, wantEntry := range map[string]string{
|
||||
"new outlet cannot sign in": "What does creating a branch actually create?",
|
||||
"do I need a user before I add a branch": "What does creating a branch actually create?",
|
||||
"how does a shop get riders": "What does assigning a delivery partner to a merchant do?",
|
||||
"what does partnerid zero mean": "What does assigning a delivery partner to a merchant do?",
|
||||
"riders not showing in a new city": "What is a district, and what happens when a partner is onboarded in a new one?",
|
||||
"nearle admin cannot see sales": "Why can I not see a shop's orders or stock from the platform workspace?",
|
||||
"how do I check what is stuck for a tenant": "Why can I not see a shop's orders or stock from the platform workspace?",
|
||||
} {
|
||||
answers := ask(t, question)
|
||||
if len(answers) == 0 {
|
||||
t.Fatalf("no answer for %q", question)
|
||||
}
|
||||
if answers[0].Question != wantEntry {
|
||||
t.Fatalf("%q was answered with %q, wanted %q", question, answers[0].Question, wantEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestThePlatformPassagesDoNotSwallowTheMerchantOnes(t *testing.T) {
|
||||
// Four passages were added at once, and they share vocabulary with the
|
||||
// merchant ones — branches, riders, partners, shops. A new passage that
|
||||
// outranks an existing answer breaks a question that used to work, silently,
|
||||
// and the person sees a confident answer to something they did not ask.
|
||||
for question, wantEntry := range map[string]string{
|
||||
"how do I add a cashier": "How do I add a cashier?",
|
||||
"what happens when I assign a rider": "What happens when I assign a rider?",
|
||||
"till login not working on the website": "What is the difference between a till account and a console login?",
|
||||
"re-import from the global catalogue": "What does re-importing a product do?",
|
||||
} {
|
||||
answers := ask(t, question)
|
||||
if len(answers) == 0 || answers[0].Question != wantEntry {
|
||||
got := "nothing"
|
||||
if len(answers) > 0 {
|
||||
got = answers[0].Question
|
||||
}
|
||||
t.Fatalf("%q now answers with %q, wanted %q", question, got, wantEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEveryChipOnThePlatformPagesHasAnAnswer(t *testing.T) {
|
||||
// The console's own chips, verbatim from `assistantContext.ts`.
|
||||
//
|
||||
// The rule that file states: a page is only given an agent when that agent
|
||||
// can answer every chip on it, because a chip coming back "I cannot look
|
||||
// that up" reads as a broken assistant rather than an unbuilt feature. In
|
||||
// the platform workspace the corpus IS the assistant, so a chip with no
|
||||
// passage behind it is a dead button.
|
||||
//
|
||||
// Duplicated here rather than imported because the two repositories deploy
|
||||
// separately: this is the half that can fail on its own.
|
||||
for _, chip := range []string{
|
||||
"What does creating a branch actually create?",
|
||||
"Why can I not see a shop's orders from here?",
|
||||
"How does a shop get riders?",
|
||||
"What is the difference between a till account and a console login?",
|
||||
"New outlet cannot sign in",
|
||||
"What is a district?",
|
||||
"What does re-importing a product do?",
|
||||
"Why is a product in my catalogue but not on the shelf?",
|
||||
"Why can I not see a shop's stock from here?",
|
||||
} {
|
||||
if answers := ask(t, chip); len(answers) == 0 {
|
||||
t.Fatalf("the chip %q has no passage behind it — it is a dead button", chip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
services/tools/testdata/help_cashier.json
vendored
6
services/tools/testdata/help_cashier.json
vendored
@@ -12,9 +12,9 @@
|
||||
"source": "src/api/people.ts, src/auth/session.ts"
|
||||
},
|
||||
{
|
||||
"question": "Why do online and counter sales not add up to one total?",
|
||||
"answer": "App orders and counter bills are kept in two separate sets of books, and nothing\nreconciles them into a single figure.\n\nAn app order is placed by a customer and may carry a delivery. A counter bill is\nrung on a till in the shop. They are counted separately everywhere in the\nconsole, which is why a revenue figure from one place will not match a total\nfrom the other.\n\nWhen you need both, read them side by side and say which is which. Adding them\ntogether produces a number that looks authoritative and is not.",
|
||||
"source": "src/features/store-admin/pages/SalesPage.tsx, services/posService.go"
|
||||
"question": "What does creating a branch actually create?",
|
||||
"answer": "A branch is never created on its own. It arrives with somebody who can run it,\nand there are two ways to give it one.\n\nName an existing person and they are bound to the new outlet. They must already\nbelong to that same merchant and must not be a till account — a userid from\nanother business, or one that does not exist, is refused with the same message,\nand the branch is not created at all rather than left standing with nobody.\n\nGive an email instead and a login is spawned from it. That account is named\nafter the shop, sits on the shop's email, and **is created with no password**.\nThat is deliberate, not a fault: the first person to sign in is told the account\nneeds a password and sets one, and only then can they get in.\n\nSo a newly created branch whose operator reports they \"cannot sign in\" has\nusually not been broken — they have not been through the password step yet. The\naccount is real and active; it simply has nothing to check a password against\nuntil somebody sets one.\n\nIf the branch was created with neither an operator nor an email, it was not\ncreated. That combination is refused outright, because an outlet nobody can sign\nin to still appears in every list and every branch picker, and the first person\nto notice is whoever is standing in the shop.",
|
||||
"source": "repositories/tenantRepository.go, src/auth/session.ts"
|
||||
}
|
||||
],
|
||||
"count": 3,
|
||||
|
||||
Reference in New Issue
Block a user