Commit Graph

17 Commits

Author SHA1 Message Date
Suriya
d3a7466f4c Sync stock status on restock and expose live stock on getproductbyvariant
Two gaps found while auditing the order/stock flow:

- Receiving stock via an approved stock request only updated
  products.productstatus (a global per-product flag). A location
  flagged outofstock by CreateOrder never got reactivated, since
  nothing touched productlocations.status on the way back in.
  CreateProductStock now reactivates the specific
  (tenant, location, product) row to "available" for every "in"
  entry, the counterpart to how it gets flagged out.

- getproductbyvariant returned no stock info at all, so the app could
  only find out a product was unavailable from the 409 at order time.
  It now accepts an optional locationid and, when passed, returns
  live productstock (same SUM(in)-SUM(out) formula the order check
  uses) and locationstatus per product. Omitting locationid keeps the
  old response shape.

Added MOBILE_ORDER_VERIFICATION.md as a handoff doc for the mobile
team covering the expected request/response shapes and how to verify
their integration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:01:39 +05:30
Suriya
af55325a5b Stop silently dropping order line items
Every order created after orderheaderid 146119 had zero rows in
orderdetails — the header saved fine but items never made it in,
which also meant the stock pre-validation loop (it iterates over
data.Items) never ran, so an order could go through without ever
checking stock. Root cause: whichever client is sending these sends
items as a sibling of "orders" rather than nested inside it, a shape
neither existing parse strategy captures, so encoding/json silently
dropped it.

Add a third parse fallback for that sibling-items shape, and reject
any order with zero items outright instead of letting it through as
a phantom header-only row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:01:26 +05:30
Suriya
5bd1f52d41 Stop forcing new store outlets and their logins to InActive
CreateTenantLocation hardcoded the new location and its auto-spawned
manager login to InActive regardless of what the caller sent (the
frontend already sends Active). AppLogin checks account status before
checking whether a password is set, so a new store's login could
never reach the password-setup screen — permanently stuck on
"Inactive Account. Contact admin."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:01:15 +05:30
Suriya
e48fb4cf57 Fix tenant onboarding creating admin users with configid=0
CreateTenantUser copied the tenant form's fields onto the new
app_users row via copier.Copy, but the onboarding form never sends a
configid, so it defaulted to 0. AppLogin's GetUserByAuthname always
queries configid=1 for the web login, so any tenant onboarded through
this path was permanently unable to log in by email ("Email not
found") no matter what was typed. Set it explicitly, same as roleid.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 17:13:58 +05:30
Suriya
9258ce592c Validate password length on the user-update endpoint
PUT /users/update doubles as the password-setup/reset call (userid +
password only) for the new frontend create-password flow, and had no
validation on that field at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 16:40:47 +05:30
5e998a54eb stock update 2026-07-21 16:17:51 +05:30
Suriya
b7af245910 store wise orders change 2026-07-21 09:25:30 +05:30
Suriya
36f9cf86e7 Add Super Admin login flag and expose web tenant onboarding
issuperadmin on app_users (schema change already applied to the DB)
is now returned by AppLogin/TenantWebLogin's login response, gated
server-side rather than via a client-supplied roleid. Fixes the login
enrichment query (GetTenantUserById) to LEFT JOIN app_location instead
of INNER JOIN — a tenantless super-admin row was previously silently
dropped, so the login "succeeded" but returned an empty struct.

Also exposes createtenantuser on the web route group (was mob-only).
No repository changes were needed for location auto-provisioning:
GORM was already inserting the nested tenantlocations association on
tenant creation, it just wasn't reachable from the web.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 20:45:27 +05:30
Suriya
a9c13292f0 Make subcategory optional and fix category picker for real tenant data
subcategoryid is no longer required to import a catalogue product —
it's a display/grouping hint elsewhere (the codebase already has an
"Uncategorized" fallback for subcategoryid=0), so requiring it was
pure friction with no correctness payoff.

Fixes the category picker at the root: categoryid 2, which tenant
1135's real products actually use, has no row in productcategories at
all (not a filter bug — the master data is genuinely missing it).
Rather than inventing category master data, adds
GET /products/gettenantcategories, which lists categories a tenant's
own products actually use (falling back to a synthesized label when
the master table has no name), so the import category picker always
offers something real instead of an incomplete global list.

Also relaxes the subcategory lookup's tenant filter to include
unowned/global rows (tenantid NULL or 0), not just exact tenant
matches — categoryid 2's real subcategories carry no tenant at all,
so the strict filter was hiding them even when a tenant wanted one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 18:18:51 +05:30
Suriya
fab06bb33e Bridge global catalogue DB to per-store product catalogue
Adds a separate CatalogueDB (pgvector) connection alongside the main
nearledb, plus a new catalogue module (repository/service/controller/
routes) to browse it by brand, category, and keyword, with brand
optional so the whole ~237-product catalogue can be browsed unfiltered.

Adds the actual bridge: importing a catalogue product snapshots it into
the tenant's own products table (keyed on brand+catalogueid, since a
catalogue row's bare id is only unique within its own brand table),
then links it via the existing productlocations upsert. Re-importing
tops up stock and refreshes price instead of duplicating. Also adds an
imported-refs endpoint so the frontend can badge already-imported items
without diffing full product lists, and wires the new AWS S3 image
store used to resolve catalogue product photos.

Bumps Go/Docker to 1.24 for the AWS SDK dependency this needs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 17:34:20 +05:30
950064de6c productRepository created 2026-07-15 15:25:50 +05:30
Suriya
7e9b3f98ba stores login fix 2026-07-09 18:03:44 +05:30
1437a08be5 corrections in stockrequest table 2026-07-09 15:31:36 +05:30
Suriya
135df9fd18 store users login 2026-07-07 12:09:34 +05:30
abe2cb997b stock request table created 2026-07-04 17:49:54 +05:30
Suriya
f220c24c17 new changes 2026-07-01 10:53:57 +05:30
Gokul
0d42ac84e1 initial commit 2026-05-25 11:52:26 +05:30