{% extends "ui/templates/base/layout.html" %} {% block content %}

Office Server & Workstation Agents

Office Server/Storage Agent manages branch storage; Workstation Agents provide per-PC Tally, GST and desktop integration. Existing storage and workstation features remain unchanged.

Scope: {{ storage_scope_title or '-' }}

ERP Local Agent release: {{ erp_local_agent_version or '-' }} ยท automatic updates enabled

{% if request.query_params.get('error') == 'branch_not_linked' %}
Your user is not linked to a branch. Please update the Partner/Branch Manager user profile with branch_id before enabling local storage.
{% endif %}
Storage Nodes
{{ nodes|length }}
Online / Active
{{ nodes|selectattr('is_active')|list|length }}
Recent Storage Jobs
{{ recent_jobs|length if recent_jobs is defined else 0 }}
Recent Download Requests
{{ recent_download_requests|length if recent_download_requests is defined else 0 }}
Workstations Seen
{{ workstation_agents|length if workstation_agents is defined else 0 }}
{% if request.query_params.get('created') == '1' %}
Storage node created. Use the Download ERP Local Agent button in the node row to generate the branch package. Secret and standalone .env are not displayed.
{% endif %} {% if request.query_params.get('error') == 'env_download_disabled' %}
Standalone .env download is disabled for security. Download the pre-configured ERP Local Agent ZIP instead.
{% endif %}
{% if can_manage_branch_storage %}

One-click branch setup

Recommended. ERP will create or reuse the branch node and immediately download the pre-configured LSA2 Windows Service ZIP. Secret is not shown on screen. If a branch already has a storage root, the existing root will be reused and will not be silently changed.

{% if forced_branch_id %}
{% set fb = branch_map.get(forced_branch_id) if branch_map else None %} {{ fb.name if fb else ('Branch ID ' ~ forced_branch_id) }}{% if fb and fb.code %} ({{ fb.code }}){% endif %}
{% else %} {% endif %}

For a new branch setup only. Existing branch nodes keep their already configured root.

Manual node creation

Use only when you want a custom node code/name.

{% if forced_branch_id %}
{% set fb = branch_map.get(forced_branch_id) if branch_map else None %} {{ fb.name if fb else ('Branch ID ' ~ forced_branch_id) }}{% if fb and fb.code %} ({{ fb.code }}){% endif %}
{% else %} {% endif %}
{% else %}
Storage setup package generation is available to Firm Admin, Partner and Branch Manager. This screen is monitoring-only for your current role.
{% endif %}

Office Server / Storage Agents

Partners/Branch Managers see only their managed branch. One branch should have one active node and one fixed storage root. Existing node secrets are not shown again.

{% for node in nodes %} {% set b = branch_map.get(node.branch_id) if branch_map and node.branch_id else None %} {% else %} {% endfor %}
NodeBranchStatusLast SeenRootAction
{{ node.node_name }}
{{ node.node_code }}
{{ b.name if b else (node.branch_id or 'Firm-level') }} {{ node.status }} {{ node.last_seen_at_utc or '-' }} {{ node.storage_root_path or '-' }} {% if can_manage_branch_storage %}
{% if node.status == 'disabled_duplicate' %} Duplicate disabled {% else %}
Installs on another office PC without changing credentials used by existing workstations.
{% endif %}
{% else %}-{% endif %}
No storage nodes registered yet.

Workstation Agents

Each PC keeps a persistent agent identity. Use Install New Workstation on the branch node above for another office PC; it receives its own workstation credential and existing agents keep working.

{% for ws in workstation_agents or [] %} {% else %} {% endfor %}
WorkstationAgentTallyOpen CompaniesLast SeenPhase 2
{{ ws.machine_name }}
{{ ws.platform_name or '-' }}
{{ ws.agent_instance_id[:12] }}...
{{ ws.agent_version or '-' }}
{{ ws.status }}
{{ 'Connected' if ws.tally_connected else 'Not connected' }} {{ ws.tally_company_count or 0 }} {{ ws.last_seen_at_utc or '-' }} {% if can_manage_branch_storage %}
{% else %}-{% endif %}
No workstation agent has connected since the Phase 1 upgrade.

Recent Workstation Agent Jobs

Phase 2 jobs are durable, routed to one workstation, leased for safe retry, and protected by an idempotency key.

{% for job in recent_agent_jobs or [] %} {% else %} {% endfor %}
JobWorkstationActionStatusAttemptsCreated
{{ job.job_uuid[:10] }}... {{ job.workstation.machine_name if job.workstation else ('#' ~ job.workstation_agent_id) }} {{ job.action }} {{ job.status }}{% if job.last_error %}
{{ job.last_error }}
{% endif %}
{{ job.attempts }}/{{ job.max_attempts }} {{ job.created_at_utc or '-' }}
No Phase 2 workstation jobs yet. Use Test route on a connected workstation to verify routing.

Recent Storage Jobs

{% for job in recent_jobs or [] %} {% else %} {% endfor %}
JobStatusCreated
#{{ job.id }}{{ job.status }}{{ job.created_at_utc or '-' }}
No recent storage jobs.

Recent Download Requests

{% for dr in recent_download_requests or [] %} {% else %} {% endfor %}
RequestStatusCreated
#{{ dr.id }}{{ dr.request_status }}{{ dr.created_at_utc or '-' }}
No recent download requests.
{% endblock %}