Dev #109

Merged
ImanThiyanga merged 10 commits from Dev into production 2026-10-14 11:16:44 +05:30

10 Commits

Author SHA1 Message Date
ImanThiyanga b3f3b45c27 Merge branch 'production' into Dev
CI/CD - ERP Core Monorepo / Build & Deploy Backend (pull_request) Failing after 11m36s
CI/CD - ERP Core Monorepo / Build & Deploy Frontend (pull_request) Failing after 15m7s
2026-10-14 05:46:37 +00:00
ImanThiyanga a1160e4f15 Merge pull request 'Fix/ui bug fixers rebase repair' (#108) from fix/ui-bug-fixers-rebase-repair into Dev
Reviewed-on: #108
2026-10-14 05:45:31 +00:00
ImanThiyanga 3be425284c Repair botched rebase resolutions from ui-bug-fixers
The rebase onto Dev resolved five conflicts; four were wrong. In the
service files Dev's constructor parameter lists won while the branch's
field declarations and constructor bodies stayed, so the bodies assigned
parameters that no longer existed.

- AdjustmentService: restore fifo, approvals, db and serialTracking
  parameters (Dev's glAccounts kept, configuration dropped).
- FifoCostingService: restore the LowStockTracker field, parameter and
  assignment.
- CountService: restore _serialTracking and _adjustments, and delete
  Dev's PostAdjustmentJournalAsync. Dev's call site did not survive the
  rebase, so the method was orphaned dead code referencing fields this
  class no longer has. The branch routes count variances through
  AdjustmentService.SubmitAsync, which posts via Dev's role-keyed
  glCodes, so nothing is lost by removing it.
- PurchaseInvoicePaymentService: this one compiled. paymentDay was
  computed but the GL period and EntryDate still used now, so a
  back-dated payment posted its journal to today's period. Use
  paymentDay, and resolve "today" through BusinessClock, matching
  SalesInvoicePaymentService.
- ErpDbContextModelSnapshot: the resolution dropped the whole Expense
  module from the definition and relationship sections while leaving its
  navigation entries behind, so the snapshot no longer loaded. Rebuilt as
  the branch's snapshot plus Dev's GlAccountConfig blocks; EF now reports
  no pending model changes.

Tests: BankDepositTestSupport's FakeGeneralLedger gains the
ListAccountsAsync member Dev added to IGeneralLedgerService, and
DualApprovalTests passes a StubGlAccountConfigService in place of the
removed IConfiguration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 09:49:09 +05:30
Sasanka d0354ed169 price adjustment and stock adjustments 2026-10-12 15:02:59 +05:30
Sasanka a788349138 serial numbers 2026-10-12 14:57:15 +05:30
Sasanka 3abcfa6e6f ui bug fixers 2026-10-12 14:56:12 +05:30
ImanThiyanga 0d3f2fba14 Merge branch 'Dev' of https://gitea.hexdive.com/New_REP_SYSTEM/ERP-core into Dev 2026-10-12 14:36:01 +05:30
ImanThiyanga a3591d3643 Sync package-lock.json with package.json so npm ci works again
html-to-image and jspdf were added to package.json without being added to
the lockfile, so `npm ci` - which the frontend Dockerfile runs - failed
with the package.json/package-lock.json out-of-sync error. tsc also could
not resolve either module in SalesInvoicePrint.tsx.

Pre-existing and unrelated to the GL account work; found because the GL
Accounts screen could not be build-verified without it.

Adds those two plus their transitive deps. It also drops @emnapi/core and
@emnapi/runtime: both are optional, and required only by the wasm32-wasi /
sharp-wasm32 variants, which linux-x64 never selects in favour of the
native binaries - so the Docker build is unaffected.

Verified: npm ci succeeds, tsc --noEmit is clean, npm run build compiles.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-07 13:17:52 +05:30
ImanThiyanga c30ff473f5 Add the GL Accounts settings screen
Pickers are populated from GL's own chart of accounts, postable and active
accounts only, so a user can only choose a code the server will accept. A
stored code GL does not have is shown flagged and still selected rather
than appearing blank, which is the state 11 of the 12 mappings are in until
GL's chart is seeded - the broken mapping stays visible instead of looking
merely unset.

Options come from /gl-account-config rather than the GL proxy: that proxy
is gated on the `ledgers` nav permission while this screen is on
`settings`, and one endpoint keeps the picker and the server-side
validation working from the same list. Gated on the existing `settings` key
so no role_permissions edit is needed.

Saving is disabled outright while GL is unreachable, matching the server,
which refuses to store a mapping it could not verify.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-07 13:17:22 +05:30
ImanThiyanga c41aed9a80 Move the GL account mapping out of appsettings into validated master data
The per-module Gl*Code appsettings keys pinned GL's account *codes* in
ERPCore's config, while GL generates codes positionally and refuses a
requested one. Nothing connected the two, so "1100 means Inventory" held
only because someone once created accounts in a particular order - and on
2026-10-07 eleven of the twelve configured codes turned out never to have
existed in GL. Every GRN, adjustment, day-end, invoice and FIFO posting had
been failing with "Account <code> not found".

The mapping is now master data in gl_account_config, keyed by accounting
role rather than by module, and GlAccountConfigService validates every
submitted code against GL's live chart of accounts before storing it. A
code GL does not have, or cannot post to, is refused with the role named -
so the mismatch is unrepresentable rather than merely detected. Correcting
a mapping no longer needs a redeploy.

Notes:
- Fails closed on save (503 if GL is unreachable), deliberately opposite to
  the startup validator, which must still let the app serve.
- Non-postable accounts are rejected too: GL rejects a journal line against
  one, so storing it only defers the failure. The auto-created 1000
  Bank/Cash header is exactly that trap.
- The settings endpoint also serves the selectable accounts, because
  GeneralLedgerController is gated on `ledgers` while this is on `settings`
  - and it keeps the picker and the validation list the same data.
- Reading an unmapped role throws naming the role, instead of posting ""
  and letting GL return an opaque 404 from inside a transaction.
- The appsettings keys are now seed-only: DataSeeder copies them in once so
  existing deployments keep their current mapping. No runtime fallback, or
  there would be two sources of truth again.
- The 32 read sites across 11 services collapsed to 12 roles, since every
  module carried the same value for a given role.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-07 13:04:49 +05:30